默认情况下,Webpack 不支持处理样式文件,需要借助于 loader 和 插件。

加载 css 文件

要加载 css 文件,我们需要 css-loaderopen in new windowstyle-loaderopen in new window.

css-loader 会在所有匹配到的文件中查找 @importurl() 语句,并将它们当成普通的 import 语句来处理。如果 @import 语句指向了一个外部资源,比如一个 url 链接,那么 css-loader 会跳过。

style-loader 会将样式注入到 html 上的 style 元素中。可以通过配置来修改将样式注入 style 元素的方式。同时 style-loader 也实现了 HMR 接口,提供了更好的开发体验。

将样式内联到页面中通常不是一个好的实践方式,我们需要使用 MiniCssExtractPlugin 这个插件来讲 css 导出到文件中。这个插件后面章节会做说明。

安装依赖包:

npm add css-loader style-loader --develop
1

webpack.parts.js 中添加

exports.loadCSS = () => ({
  module: {
    rules: [{ test: /\.css$/, use: ['style-loader', 'css-loader'] }],
  },
});
1
2
3
4
5

上面的配置说明如果文件是 .css 结尾,则需要使用这两个 loader。loader 返回处理后的文件内容,loader 之间可以像 Unix 的管道一样连接起来,从右向左一次处理:

styleLoader(cssLoader(input));
1

将配置组合到 webpack.config.js

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

添加初始样式

src/main.css

body {
  background: cornsilk;
}
1
2
3

在代码中引用这段样式, src/index.js

import "./main.css";
...
1
2

启动开发服务器 npm run start,可以看到浏览器中的背景色发生了变化。这时,修改背景色为 background: lime, 浏览器中的背景色会发生相应变化。

helloworld

PostCSS

PostCSSopen in new window 允许你通过其提供的各种插件对 CSS 做各种转换处理。PostCSS 类似于处理样式的 Babel。后面章节会做说明。

使用 CSS 预处理器

Webpack 支持多种主流的 CSS 预处理器。

深入理解 css-loader

要更好的使用 css-loader,首先需要明白 css-loader 是如何查找文件的。css-loader 默认只处理相对路径导入的模块,绝对路径导入(url("https://mydomain.com/static/demo.png"))或者根路径导入(url("/static/img/demo.png"))的模块不会被处理。

如果项目中需要使用到这些外部模块,需要将这些模块拷贝到项目中来,可以借助 webpack-copy-pluginopen in new window 完成。

如果你需要自定义 css-loader 如何处理要导入的模块,你需要设置 importLoaders 这个选项,来告诉 css-loader 在处理待导入模块之前,该模块必须要被多少个其他模块处理过。

举个例子加以说明。比如需要在 css 文件导入一个 sass 文件,@import "./variables.sass";, 那么为了能处理 sass 文件,loader 的配置需要配置为:

const config = {
  test: /\.css$/,
  use: [
    'style-loader',
    {
      loader: 'css-loader',
      options: { importLoaders: 1 },
    },
    'sass-loader',
  ],
};
1
2
3
4
5
6
7
8
9
10
11

此时,importLoaders 为 1,告诉 css-loader 在处理导入的模块时,需要确保被导入的模块需要被 sass-loader 处理过。如果添加更多的 loader,比如再加一个 postcss-loader, 则 importLoaders 需要改为 2.

importLoaders 选项只在 css-loader 无法处理待导入的模块的时候才会被使用。比如上面的例子 css 文件中导入了一个 sass 文件,要处理 sass 文件需要借助于 sass-loader,因此需要确保在 css-loader 处理模块之前,sass-loader 先处理了该模块。而如果在 sass 文件中导入 sass 文件,则模块本身已经被 sass-loader 处理过,就不需要 css-loader 处理 sass 文件了。

如果需要导入 node_modules 目录下的样式文件,则需要加一个 ~ 前缀。比如导入 bootstrap 的样式文件 @import "~bootstrap/less/bootstrap";~ 告诉 webpack 该模块不是一个相对路径引入的模块,需要在 node_modules 目录下查找。

总结

Webapck 可以处理各种格式的样式文件,默认情况下,所有样式都会编译成 JavaScript bundle。

css-loader 处理 @importurl() 语句,style-loader 负责将样式编译成 js,同时实现了 HMR 接口。

Webapck 支持多种预处理器,可以将各种格式的样式转换成 CSS,常见的预处理器有 Sass,Less 和 Stylus。

PostCSS 借助其自身的插件系统,提供了多种处理 CSS 的能力,比如自动添加前缀等。

默认情况下 css-loader 不会处理绝对路径导入和根目录导入的模块。css-loader 通过 importLoaders 选项支持自定义模块导入处理能力。如果要导入一个 node_moduels 目录下的文件,需要使用 ~ 前缀。

关注微信公众号,获取最新推送~

加微信,深入交流~