加载样式

Webpack 本身不处理样式,您必须使用 loader 和插件来加载样式文件。在本章中,您将配置如何加载 CSS,并了解浏览器自动刷新的工作原理。当您对 CSS 进行更改时,不必完全刷新。相反,它仅仅是对变动的部分进行更新。

加载 CSS

要加载 CSS,您需要使用 css-loaderstyle-loadercss-loader 遍历匹配文件中的 @importurl(),并将它们视为常规ES2015 import。如果 @import 指向外部资源,则 css-loader 会跳过它,因为 Webpack 只处理内部资源。

style-loader 通过 style 元素注入样式。它还实现了热模块替换接口,提供了愉快的开发体验。

匹配的文件可以通过文件加载器url-loader 之类的 loader 进行处理,更多的细节将在本书的“ 加载资源”部分讨论。

由于内联 CSS 不适合生产环境,因此使用 MiniCssExtractPlugin 生成单独的 CSS 文件是有意义的。您将在下一章中完成此操作。

首先,我们开始安装:

npm install css-loader style-loader --save-dev

现在让我们在 Webpack 中配置它们。在部分配置文件的末尾添加一个新函数:

webpack.parts.js

exports.loadCSS = ({ include, exclude } = {}) => ({
  module: {
    rules: [
      {
        test: /\.css$/,
        include,
        exclude,

        use: ["style-loader", "css-loader"],
      },
    ],
  },
});

您还需要将这个片段连接到主配置文件中:

webpack.config.js

const commonConfig = merge([
  ...
  
  parts.loadCSS(),
]);

添加的配置意味着以 .css 结尾的文件应该调用给定的 loader。test 字段 是一串正则表达式,用来描述文件名称的匹配规则。

loader 是应用于源文件的转换器,并返回转换结果。它们像 Unix 中的管道一样,可以连接使用。它们从右到左执行,这意味着 loaders: ["style-loader", "css-loader"] 可以读作 styleLoader(cssLoader(input))

如果要禁用 css-loader url 解析功能,那么就在 loader 选项中设置 url: false。同样,它也适用于 @import。要禁用 import 解析功能,可以设置 import: false

如果您不需要 HMR 功能,支持旧的 Internet Explorer 和 source maps,请考虑使用 micro-style-loader 而不是 style-loader

初始化 CSS

现在,添加初始的 CSS 文件:

src/main.css

body {
  background: cornsilk;
}

此外,您需要让 webpack 发现它。如果没有一个入口点来指向它的话,webpack 是找不到该文件的:

src/index.js

import "./main.css";

...

执行 npm start ,如果您使用的是默认端口,那么我们直接在浏览器打访问 http://localhost:8080。现在打开 main.css 并将背景颜色更改为 limebackground: lime)。

Hello-world-with-lime-background

CSS模块附录介绍了一种 CSS 局部作用域的方法,这样避免了所有的 CSS 样式都具备全局作用域。

加载 Less

less,a-css-precessor

Less 是包含函数功能的 CSS 处理器,在 Webpack 中使用 Less 不需要花费很多精力,因为 less-loader 已经处理的差不多了。你需要安装 Less,因为它是 less-loader 的依赖。

然后加入下面的配置:

{
  test: /\.less$/,
  use: ["style-loader", "css-loader", "less-loader"],
},

less-loader 支持 Less 插件,source maps 等。要了解这些工作原理,您可以查看一下这个项目。

加载 Sass

sass,一种广泛使用的css预处理器

Sass 是一种广泛使用的 CSS 预处理器,在 Webpack 中需要 sass-loader 使用,另外,还要安装 node-sasssass-loader 依赖于它。

然后在 Webpack 中添加以下配置就可以了:

{
  test: /\.scss$/,
  use: ["style-loader", "css-loader", "sass-loader"],
},

如果您想要更高的性能,特别是在开发过程中,请查看 fast-sass-loader

加载 Stylus 和 Yeticss

stylus,一款css处理器

Stylus 是另一款 CSS 处理器,通过 stylus-loader 可以很好地将它融入 Webpack。yeticss 是一个适用于它的模式库。

请参考以下配置:

{
  ...
  module: {
    rules: [
      {
        test: /\.styl$/,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "stylus-loader",
            options: {
              use: [require("yeticss")],
            },
          },
        ],
      },
    ],
  },
},

如果要在 Stylus 中使用 yeticss ,您必须将其导入到 .styl 文件中:

@import "yeticss"
//or
@import "yeticss/components/type"

PostCSS

PostCSS,一种CSS转换器
PostCSS 允许您通过 JavaScript 插件对 CSS 执行转换,您甚至可以找到类似 Sass 功能的插件。PostCSS 相当于 CSS 的 Babel。postcss-loader 可以将它与 Webpack 搭配使用。

下面的例子说明了如何使用 PostCSS 自动设置浏览器厂商前缀。另外,这个配置还添加了 press——一个 PostCSS 插件——允许您在 CSS 中使用类似 Sass 的标签。您可以将此技术与其他 loader 混合使用,以启动自动添加前缀。

{
  test: /\.css$/,
  use: [
    "style-loader",
    "css-loader",
    {
      loader: "postcss-loader",
      options: {
        plugins: () => ([
          require("autoprefixer"),
          require("precss"),
        ]),
      },
    },
  ],
},

记住安装导入 autoprefixerprecss,这样它们才能正常工作。自动添加前缀章节中详细讨论了该技术。

PostCSS 支持基于 postcss.config.js 的配置。它在内部基于 cosmiconfig,因此它也支持其他格式的配置。

cssnext

cssnext 是一个 PostCSS 插件,用来体验一些未来的 CSS 特性。您可以通过 postcss-cssnext 使用它。

请参考以下配置:

{
  use: {
    loader: "postcss-loader",
    options: {
      plugins: () => [require("postcss-cssnext")()],
    },
  },
},

有关可用选项,请参阅官方使用说明

cssnext 包括自动添加前缀功能!您不需要额外配置。

理解文件查找

为了充分使用 css-loader,您应该理解它如何执行查找。css-loader 默认处理相对导入,它不会触及绝对导入(url("/static/img/demo.png"))。如果您依赖此类导入,则必须将文件复制到项目中。

copy-webpack-plugin 可以用于将文件复制到 Webpack 中,但您也可以将文件复制到Webpack 之外。前一种方法的好处是 webpack-dev-server 可以访问到它。

如果你使用 Sass 或 Less,resolve-url-loader 会派上用场,它支持了 CSS 内部资源的相对导入,避免资源定位失败的问题。

处理 css-loader 导入

如果要以特定方式处理 css-loader 导入,则应将 importLoaders 选项设置为一个数字,该数字告诉加载程序在对所找到的导入文件执行 css-loader 之前需要执行多少个 loader 。如果您通过@import语句从 CSS 导入其他 CSS 文件,并希望通过特定的 loader 处理导入,则此技术至关重要。

请考虑从 CSS 文件导入以下内容:

@import "./variables.sass";

要处理 Sass 文件,您必须编写配置:

{
  test: /\.css$/,
  use: [
    "style-loader",
    {
      loader: "css-loader",
      options: {
        importLoaders: 1,
      },
    },
    "sass-loader",
  ],
},

如果您向链中添加了更多 loader(例如 postcss-loader),则必须相应地调整 importLoaders 选项。

从 node_modules 目录加载文件

您可以直接从 node_modules 目录加载文件。考虑 Bootstrap 及其用法,例如:

@import "~bootstrap/less/bootstrap";

波形符(~)告诉 Webpack 它不是默认的相对导入。如果包含波浪号,则它会在 node_modules 中执行查找(默认设置,可以通过 resolve.modules 字段进行配置)。

如果您正在使用 postcss-loader,则可以跳过使用 ~,就像 postcss-loader issue tracker 讨论的内容一样。postcss-loader 可以在没有波形符号的情况下解析导入。

启用源映射

如果要为 CSS 启用源映射,则应为 css-loader 启用 sourceMap 选项,并将 output.publicPath 设置为开发服务器的绝对 URL 地址。如果链中有多个 loader,则必须分别为每个 loader 启用源映射。css-loader issue 29 进一步讨论了这个问题。

将 CSS 转换为字符串

特别是对于 Angular 2,如果你能够以字符串格式获得 CSS,将其嵌入到组件中,这将非常方便。css-to-string-loader 可以解决这个问题。

使用 Bootstrap

有几种方法可以在 webpack 中使用 Bootstrap。其中一个方法就是使用 Bootstrap npm 包,并执行如上所述的 loader 配置。

Bootstrap Sass 版本 是另一种选择。在这种情况下,您应该将 _sass-loader 的 precision 选项设置为至少 8。这是 bootstrap-sass 中发现的一个已知问题

第三种选择是通过 bootstrap-loader。它拥有许多功能,但也可以进行定制。

总结

Webpack 可以加载各种各样的样式文件。这里介绍的方法默认情况下将样式编写到 JavaScript 包中。

回顾一下:

  • css-loader 抓取样式中的 @importurl()style-loader 将其转换为 JavaScript 并实现了 Webpack 的热模块替换接口。
  • Webpack 通过 loader 可以编译各种格式的 CSS 文件,这些包括Sass、Less 和 Stylus。
  • PostCSS 允许您通过其插件系统转换 CSS。cssnext 是 PostCSS 插件集合中的一个案例,它实现了很多 CSS 未来特性。
  • 默认情况下,css-loader 不会触及绝对导入。它允许通过importLoaders 选项自定义加载行为。您可以通过在导入前添加 ~ 字符来对 node_modules 目录执行查找。
  • 要使用 source maps,您必须在你使用的每一个 css loader 中启用 sourceMap (除了 style-loader );另外,您还应该将 output.publicPath 设置为开发服务器的绝对 URL 地址。
  • 在 Webpack 中使用 Bootstrap 需要特别小心。您可以使用一般的 loader,也可以基于 bootstrap-loader 来进行定制。

虽然这里介绍的加载方法足以用于开发,但它并不适合生产环境。你将在下一章发现这个问题背后的原因,并且学会通过将 CSS 从源码中抽离来解决这个问题。

用户头像
登录后发表评论