SCSS 相对于根目录的导入

58

我正在重构一个Angular应用程序,当我将组件移动到新的目录位置时,发现在组件的SCSS文件中处理@import路径有些繁琐。

例如,假设我在应用程序的根目录下有文件src/_mixins.scss,而组件src/app/my-widget/my-widget.component.scss像这样导入SCSS:@import '../../mixins';。一切都好。

但是然后我决定my-widget.component实际上是另一个组件my-thingy.component下的“共享组件”,所以我在src/app/my-thingy下创建了一个shared文件夹,并将src/app/my-widget中的所有内容移动到其中。

希望你还跟得上...所以现在我有了src/app/my-thingy/shared/my-widget,我修改了我的SCSS文件来导入@import '../../../../mixins'

注意:这只是一个简化的例子。其中一些路径相对较深(无意冒犯...或者是有意的?),所有这些./有点多。

简而言之:

如果从一开始,我就可以在所有组件的SCSS文件中相对于根目录导入_mixins.scss,那将非常方便,这样我就不必在重构时不断调整@import路径了。(例如:@import '~/mixins'之类的)。是否存在这样的功能?

我尝试过的方法(可悲地失败了):

  1. @import '~/mixins'; /** 我本来很有希望的 **/
  2. @import 'mixins'; /** 这里可能有点过于乐观了 **/
  3. @import '~//mixins'; /** 现在我只是胡编乱造了 **/
我知道我已经必须修改我的模组文件,以便将其指向新的组件路径,因为要把所有这些东西“搬来搬去”,但是... 嘿,少一件事情,对吧?
6个回答

78
  • 如果您使用Angular CLI,请查看全局样式,特别是"stylePreprocessorOptions"选项。
  • 对于webpack,您可以在sassLoader插件配置中配置includePaths
  • gulp构建也类似,您可以将includePaths传递给sass插件。

不管您的构建工具是什么,sass都会将这些路径视为根路径,因此您可以直接导入它们,所以:

includePaths: ["anywhere/on/my/disk"]

你可以只使用 @import 'styles',而不是 @import 'anywhere/on/my/disk/styles'


4
我在使用自动化CLI命令将Angular 5升级到Angular 7后,在使用Karma的npm test时遇到了问题。结果发现angular.json中的“test.options”部分也需要stylePreprocessorOptions - Boris Yakubchik
谢谢Boris,我也有完全相同的问题! - Ash McConnell
无法弄清楚:假设我在我的Angular库中使用@import "@import "~mapbox-gl/dist/mapbox-gl.css,它指向安装在node_modules/mapbox-gl/...中的第三方MapBox库CSS - 如何使其指向我安装库的应用程序的正确方向,而不是https://localhost:4200/~/mapbox-gl/... - Alexander

19
如果我正确理解了问题,那么使用@import 'src/app/...'是有效的。
例如:
@import 'src/mixins';
请注意路径前面没有斜杠。
(这是在Angular 9上测试的)
Translated:
Note that there's no leading backslash on the path.
(this is tested on Angular 9)

很明显,这在Angular 16中已经不再起作用了,唉。 - PhiLho

16
你可以使用{}来引用项目路径的顶层,当使用meteor-scss时,类似这样的东西就会起作用。
@import "{}/node_modules/module-name/stylesheet";

您还可以使用波浪线操作符~。如果使用webpack(或angular-cli),请按照以下方式访问node_modules下的库 -- 感谢@splintor

@import "~module-name/stylesheet";

6
如果使用 webpack(或 angular-cli),访问位于 node_modules 的库也可以使用波浪符号进行 - @import "~module-name/stylesheet"; - splintor
如答案所述,{}代表项目根目录。因此,从根目录(绝对引用)引用文件可能比从文件位置(例如通过../../)相对引用更容易。 - helcode
Angular的webpack配置和Jetbrains的sass工具都不知道如何解析这种语法。 - Kevin Beal
上述引用使用meteor-scss - helcode

7
路径的定义取决于您使用的 Angular 版本。在我们的项目中,旧版本使用 `angular-cli.json`,新版本使用 `angular.json`:
对于 "@angular/cli": "~1.7.4" 的版本,请使用 angular-cli.json:
"stylePreprocessorOptions": {
    "includePaths": [
      "../src",
      "./scss"
    ]
  },

对于 "@angular/cli": "~7.0.6":

"stylePreprocessorOptions": {
    "includePaths": [
       "./src",
       "./src/scss"
    ]
 }

而且我想补充一点,如果你使用预处理器路径,那么在导入时不应该使用波浪号。我是通过吃亏才学到这个教训的。 - Janne Harju

4
解决angular-cli的方法是在.angular-cli.json中添加stylePreprocessorOptions。
{
    "apps": [{
        ...
        "stylePreprocessorOptions": {
            "includePaths": [
                "./app/global-styles"
            ]
        },
        ...
    }]
}

如果您使用服务器端渲染,请记得在ssr和主应用程序构建中都添加此内容,否则您将会遇到NodeInvocationException: Prerendering failed because of error: Error: Cannot find module 'C:\Users\...\ClientApp\dist-server\main.bundle.js'的错误。

{
    "apps": [{
            ...
            "outDir": "dist",
            "stylePreprocessorOptions": {
                "includePaths": [
                    "./app/global-styles"
                ]
            },
            ...
        },
        {
            ...
            "name": "ssr",
            "outDir": "dist-server",
            "stylePreprocessorOptions": {
                "includePaths": [
                    "./app/global-styles"
                ]
            },
            ...
        }
    ]
}

3
我成功的方法是:
/* file src/assets/scss/app.scss */

@import "src/assets/css/style";
  1. 将文件名末尾的“.css”删除,
  2. 从“src/assets/…”(无反斜杠)导入

这个操作是在Angular 11 + Webpack中从.scss文件导入了一个.css文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接