"Error: Undefined variable" in Rails sass compilation

"Error: Undefined variable" in Rails sass compilation

我正在构建一个 rails 应用程序并遇到一些奇怪的 sass 编译问题。

我的设置:

我的 application.scss 基本上加载了几个 sass 设置了一些变量的文件,最后导入了有效使用导入变量的 layout.scss

// application.scss
@import "normalize";
@import "variables/colors";
@import "variables/typography";
@import "variables/sizes";
@import "layout";

// variables/_typography.scss
$ui-font-family: "Poppins", sans-serif;
$ui-font-family-title: "Lato", sans-serif;

// layout.scss
h1, h2, h3, h4, h5, h6 {
  font-family: $ui-font-family-title;
}

// views/layouts/application.html.erb
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

一开始它有效,但后来我注意到有时我会收到一个错误提示

Error: Undefined variable: "$ui-font-family-title".
        on line 3:16 of app/assets/stylesheets/layout.scss
>>   font-family: $ui-font-family-title;

然而,有时在重新编译资产后(由于任何 scss 文件中的更改)我注意到它可能工作或失败(出现该错误)。

我在每个 sass 文件中添加了一个 @debug "Compiling filename" 以了解编译顺序并发现一些对我来说很奇怪的东西。

它总是编译每个sass文件两次,问题是有时它编译一次变量,因此在第二次编译layout.scss时失败。

这是它工作时的样子:

这是失败时的样子:

如您所见,当它失败时它会连续两次编译 layout.scss 文件,我的猜测是因为在第二次迭代时它没有导入其他文件,所以它不能按预期找到变量。

你知道这里可能出了什么问题吗?

我真的找到问题了

似乎在 Sprockets 4.0 上,它编译 scss 文件的方式定义在这里:

# app/assets/config/manifest.js
//= link_tree ../images
//= link_directory ../stylesheets .css

这基本上是选择 stylesheets 文件夹中的任何 css/scss 文件进行编译。

因此,此问题的解决方案是更新清单以仅使用 link 作为您想要作为入口点的唯一文件,还是仅保留 application.scss 文件在文件夹的第一层并将所有其他文件夹移动到子文件夹,这样它们就不会成为清单的目标。

我现在完成了这个,它有效:

// application.scss
@import "utils/normalize";
@import "variables/colors";
@import "variables/typography";
@import "variables/sizes";
@import "pages/layout";

所以 stylesheets/ 中唯一的 scss 文件(至少在第一层深)是 application.scss.

您可以在 sprockets upgrading docs 上找到更多信息:

You may also find that some files that were not previously compiled as top-level targets are now. For instance, if your existing app has any js files directly at ./app/assets/javascripts or css/scss files ./app/assets/stylesheets, Rails with Sprockets 4 will now compile them as top-level targets. Since they were not previously treated as such, you probably don't mean them to be; if they are .scss partials referencing variables meant to be defined in other files, it may even result in an error message that looks like Undefined variable: $some_variable.