sass-loader

免责声明:sass-loader 是由社区成员维护的第三方包,它可能不支持与 webpack 相同的支持、安全策略或许可证,并且它不受 webpack 维护。

npm node tests coverage discussion size

加载 Sass/SCSS 文件并将其编译为 CSS。

开始

首先,您需要安装 sass-loader

npm install sass-loader sass webpack --save-dev

yarn add -D sass-loader sass webpack

pnpm add -D sass-loader sass webpack

sass-loader 要求您自行安装 Dart SassNode Sass(更多文档见下文)或 Sass Embedded

这允许您控制所有依赖项的版本,并选择要使用的 Sass 实现。

注意

我们强烈建议使用 Dart Sass

警告

Node Sass 不适用于 Yarn PnP 功能,并且不支持 @use 规则

警告

Sass Embedded 是实验性的,处于 beta 阶段,因此某些功能可能无法正常工作

sass-loadercss-loaderstyle-loader 链接,以立即将所有样式应用于 DOM,或使用 mini-css-extract-plugin 将其提取到一个单独的文件中。

然后将加载器添加到您的 Webpack 配置中。例如

app.js

import "./style.scss";

style.scss

$body-color: red;

body {
  color: $body-color;
}

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          // Creates `style` nodes from JS strings
          "style-loader",
          // Translates CSS into CommonJS
          "css-loader",
          // Compiles Sass to CSS
          "sass-loader",
        ],
      },
    ],
  },
};

最后通过您喜欢的方式运行 webpack

production 模式下的 outputStyle(旧 API)和 style(新 API)选项

对于 production 模式,outputStyle(旧 API)和 style(新 API)选项默认为 compressed,除非在 sassOptions 中另有指定。

解析 import at 规则

Webpack 提供了一种 高级机制来解析文件

sass-loader 使用 Sass 的自定义导入器功能将所有查询传递到 Webpack 解析引擎。因此,您可以从 node_modules 中导入 Sass 模块。

@import "bootstrap";

使用 ~ 已弃用,可以从您的代码中删除(我们建议这样做),但出于历史原因,我们仍然支持它。为什么您可以删除它?加载器将首先尝试将 @import 解析为相对路径。如果无法解析,则加载器将尝试在 node_modules 中解析 @import

在模块路径前加上 ~ 告诉 webpack 在 node_modules 中进行搜索。

@import "~bootstrap";

只在前面加上 ~ 很重要,因为 ~/ 解析为 home 目录。Webpack 需要区分 bootstrap~bootstrap,因为 CSS 和 Sass 文件没有用于导入相对文件的特殊语法。编写 @import "style.scss"@import "./style.scss"; 相同

url(...) 问题

由于 Sass 实现不提供 url 重写,所有链接的资产必须相对于输出。

  • 如果你将生成的 CSS 传递给 css-loader,所有 url 必须相对于入口文件(例如 main.scss)。
  • 如果你只是生成 CSS 而没有将其传递给 css-loader,它必须相对于你的 Web 根目录。

你将受到此第一个问题的困扰。自然会期望相对于指定它们的 .sass/.scss 文件解析相对引用(就像在常规 .css 文件中一样)。

谢天谢地,这个问题有两个解决方案

  • 使用 resolve-url-loader 添加缺失的 url 重写。在加载器链中将其放在 sass-loader 之前。
  • 库作者通常提供一个变量来修改资产路径。例如,bootstrap-sass 有一个 $icon-font-path

选项

implementation

类型

type implementation = object | string;

默认值:sass

特殊的 implementation 选项决定使用哪个 Sass 实现。

默认情况下,加载器根据你的依赖项解析实现。只需将所需的实现添加到 package.jsonsassnode-sass 包)并安装依赖项即可。

sass-loader 加载器使用 sassdart-sass)实现的示例

package.json

{
  "devDependencies": {
    "sass-loader": "^7.2.0",
    "sass": "^1.22.10"
  }
}

sass-loader 加载器使用 node-sass 实现的示例

package.json

{
  "devDependencies": {
    "sass-loader": "^7.2.0",
    "node-sass": "^5.0.0"
  }
}

当安装了 node-sasssass 时,请注意这种情况!默认情况下,sass-loader 优先使用 sass。为了避免这种情况,你可以使用 implementation 选项。

implementation 选项接受 sassDart Sass)或 node-sass 作为模块。

object

例如,要使用 Dart Sass,你可以传递

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "sass-loader",
            options: {
              // Prefer `dart-sass`
              implementation: require("sass"),
            },
          },
        ],
      },
    ],
  },
};

string

例如,要使用 Dart Sass,你可以传递

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "sass-loader",
            options: {
              // Prefer `dart-sass`
              implementation: require.resolve("sass"),
            },
          },
        ],
      },
    ],
  },
};

sassOptions

类型

type sassOptions =
  | import("sass").LegacyOptions<"async">
  | ((
      content: string | Buffer,
      loaderContext: LoaderContext,
      meta: any,
    ) => import("sass").LegacyOptions<"async">);

默认值:Sass 实现的默认值

Dart SassNode Sass 实现的选项。

注意

对于 dart-sasscharset 选项的默认值为 true,我们强烈建议不要将值更改为 false,因为 webpack 不支持除 utf-8 之外的文件。

注意

对于 sass 扩展,indentedSyntax 选项的值为 true

注意

datafile 等选项不可用,将被忽略。

ℹ 我们强烈建议不要更改 outFilesourceMapContentssourceMapEmbedsourceMapRoot 选项,因为当 sourceMap 选项为 true 时,sass-loader 会自动设置这些选项。

注意

可以使用 this.webpackLoaderContext 属性在自定义导入器中访问 加载器上下文

sass (dart-sass) 和 node-sass 选项之间有细微差别。

使用它们之前,请查阅文档

object

使用对象来设置 Sass 实现。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "sass-loader",
            options: {
              sassOptions: {
                indentWidth: 4,
                includePaths: ["absolute/path/a", "absolute/path/b"],
              },
            },
          },
        ],
      },
    ],
  },
};

function

允许通过根据加载器上下文设置不同的选项来设置 Sass 实现。

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "sass-loader",
            options: {
              sassOptions: (content, loaderContext) => {
                // More information about available properties https://webpack.js.cn/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === "styles/foo.scss") {
                  return {
                    includePaths: ["absolute/path/c", "absolute/path/d"],
                  };
                }

                return {
                  includePaths: ["absolute/path/a", "absolute/path/b"],
                };
              },
            },
          },
        ],
      },
    ],
  },
};

sourceMap

类型

type sourceMap = boolean;

默认值:取决于 compiler.devtool

启用/禁用源映射的生成。

默认情况下,源映射的生成取决于 devtool 选项。除 evalfalse 值外,所有值都启用源映射生成。

ℹ 如果 sourceMapsourceMapRootsourceMapEmbedsourceMapContentsomitSourceMapUrltrue,则将忽略 sassOptions 中的这些选项。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              sourceMap: true,
            },
          },
          {
            loader: "sass-loader",
            options: {
              sourceMap: true,
            },
          },
        ],
      },
    ],
  },
};

ℹ 在某些罕见情况下,node-sass 可能会输出无效的源映射(这是 node-sass 中的错误)。

为了避免这种情况,你可以尝试将 node-sass 更新到最新版本,或者可以在 sassOptions 中将 outputStyle 选项设置为 compressed

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "sass-loader",
            options: {
              sourceMap: true,
              sassOptions: {
                outputStyle: "compressed",
              },
            },
          },
        ],
      },
    ],
  },
};

additionalData

类型

type additionalData =
  | string
  | ((content: string | Buffer, loaderContext: LoaderContext) => string);

默认值:undefined

在实际入口文件之前添加 Sass/SCSS 代码。在这种情况下,sass-loader 不会覆盖 data 选项,而只是添加入口的内容。

当你的某些 Sass 变量取决于环境时,这会特别有用

string

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "sass-loader",
            options: {
              additionalData: "$env: " + process.env.NODE_ENV + ";",
            },
          },
        ],
      },
    ],
  },
};

function

同步
module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "sass-loader",
            options: {
              additionalData: (content, loaderContext) => {
                // More information about available properties https://webpack.js.cn/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === "styles/foo.scss") {
                  return "$value: 100px;" + content;
                }

                return "$value: 200px;" + content;
              },
            },
          },
        ],
      },
    ],
  },
};
异步
module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "sass-loader",
            options: {
              additionalData: async (content, loaderContext) => {
                // More information about available properties https://webpack.js.cn/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === "styles/foo.scss") {
                  return "$value: 100px;" + content;
                }

                return "$value: 200px;" + content;
              },
            },
          },
        ],
      },
    ],
  },
};

webpackImporter

类型

type webpackImporter = boolean;

默认值:true

启用/禁用默认的 Webpack 导入器。

在某些情况下,这可以提高性能。谨慎使用它,因为别名和以 ~ 开头的 @import at 规则将不起作用。你可以传递自己的 importer 来解决此问题(请参阅 importer 文档)。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "sass-loader",
            options: {
              webpackImporter: false,
            },
          },
        ],
      },
    ],
  },
};

warnRuleAsWarning

类型

type warnRuleAsWarning = boolean;

默认值:true

@warn 规则视为 webpack 警告。

style.scss

$known-prefixes: webkit, moz, ms, o;

@mixin prefix($property, $value, $prefixes) {
  @each $prefix in $prefixes {
    @if not index($known-prefixes, $prefix) {
      @warn "Unknown prefix #{$prefix}.";
    }

    -#{$prefix}-#{$property}: $value;
  }
  #{$property}: $value;
}

.tilt {
  // Oops, we typo'd "webkit" as "wekbit"!
  @include prefix(transform, rotate(15deg), wekbit ms);
}

显示的代码将引发 webpack 警告,而不是记录。

若要忽略不必要的警告,可以使用 ignoreWarnings 选项。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "sass-loader",
            options: {
              warnRuleAsWarning: true,
            },
          },
        ],
      },
    ],
  },
};

api

类型

type api = "legacy" | "modern";

默认值:"legacy"

允许在 legacymodern API 之间切换。可以在 此处 找到更多信息。

警告

“modern” API 是实验性的,因此某些功能可能无法正常工作(已知:内置 importer 无法正常工作,并且在初始运行时不会监视带错误的文件),可以 在此处 关注此问题。

警告

sass 选项对于 modernold API 来说是不同的。请参阅 文档,了解如何迁移到新选项。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "sass-loader",
            options: {
              api: "modern",
              sassOptions: {
                // Your sass options
              },
            },
          },
        ],
      },
    ],
  },
};

如何启用 @debug 输出

默认情况下,禁用 @debug 消息的输出。若要启用,请将以下内容添加到 webpack.config.js

module.exports = {
  stats: {
    loggingDebug: ["sass-loader"],
  },
  // ...
};

示例

将 CSS 提取到单独的文件中

对于生产构建,建议从捆绑包中提取 CSS,以便以后能够并行加载 CSS/JS 资源。

有四种从捆绑包中提取样式表的方法

1. mini-css-extract-plugin

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          // fallback to style-loader in development
          process.env.NODE_ENV !== "production"
            ? "style-loader"
            : MiniCssExtractPlugin.loader,
          "css-loader",
          "sass-loader",
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
};

2. 资产模块

webpack.config.js

module.exports = {
  entry: [__dirname + "/src/scss/app.scss"],
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [],
      },
      {
        test: /\.scss$/,
        exclude: /node_modules/,
        type: "asset/resource",
        generator: {
          filename: "bundle.css",
        },
        use: ["sass-loader"],
      },
    ],
  },
};

3. extract-loader(更简单,但专门用于 css-loader 的输出)

4. file-loader(已弃用——仅应在 Webpack v4 中使用)

webpack.config.js

module.exports = {
  entry: [__dirname + "/src/scss/app.scss"],
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [],
      },
      {
        test: /\.scss$/,
        exclude: /node_modules/,
        use: [
          {
            loader: "file-loader",
            options: { outputPath: "css/", name: "[name].min.css" },
          },
          "sass-loader",
        ],
      },
    ],
  },
};

(来源:https://stackoverflow.com/a/60029923/2969615)

源映射

启用/禁用源映射的生成。

若要启用 CSS 源映射,需要将 sourceMap 选项传递给 sass-loader css-loader。

webpack.config.js

module.exports = {
  devtool: "source-map", // any "source-map"-like devtool is possible
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              sourceMap: true,
            },
          },
          {
            loader: "sass-loader",
            options: {
              sourceMap: true,
            },
          },
        ],
      },
    ],
  },
};

如果想要在 Chrome 中编辑原始 Sass 文件,有一篇不错的博文。查看 test/sourceMap 以获取正在运行的示例。

贡献

如果您尚未阅读,请花点时间阅读我们的贡献指南。

贡献

许可证

MIT