上一节我们学习到webpack中如何处理css文件,以及在使用了 css预处理器 后又改怎么处理。文章末尾我们也提到了两个需要解决的问题:

  1. 随着项目推进,一直将css写入js中会导致文件逐渐臃肿;
  2. css兼容性
    这一节,我们将针对这两个问题提出相应的解决方案。

css文件提取

上一节中我们使用到了 style-loadercss-loader 以及 sass-loader 三种loader,在这三种loader的协同作用下,.scss文件先通过sass-loader转成普通的css文件,再通过css-loader将css转换成commonjs模块并打包到js中,最后通过style-loader将js文件中的css样式加载到head里的style标签中去。

除了上面提到的第一个问题外,这样也会导致页面会有短暂的错乱,然后等js文件加载完成后,页面样式才会恢复正常,这显然不符合我们的要求,用户的体验也非常不好。此时,我们需要将js中的css单独提取出来,作为css文件引入页面,这样就可以解决这个问题。而且js的文件体积会更小,上述第一个问题也能被解决。

如何使用

要将js中的css提取成单独的文件,我们需要用到一个 插件mini-css-extract-plugin

安装

yarn add -D mini-css-extract-plugin

配置

前几节我们主要使用的是webpack中的 loader ,与 loader 不同的是,插件 在使用之前需要先引入进来,然后在wbepack.config.js的 plugin 字段中添加配置:

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

module.exports = {
    /* ... */
    plugins: [
    	new MiniCssExtractPlugin({
         filename: 'css/index.[contenthash:10].css',
       }),
    ]
    /* ... */
}

其中,在实例化这个插件时,可以传入配置。上述配置中指定了提取出css文件的输出路径。

在配置完插件之后,我们来回顾一下之前的处理方式,最终的结果是通过 style-loader 将css的内容插入到页面的style标签中。而现在我们要实现的是将css文件单独提取出来。所以我们需要将 style-loader 替换掉。

mini-css-extract-plugin 插件内部提供了一个用于提取css的loader: MiniCssExtractPlugin.loader,我们只需要将 style-loader 替换为 MiniCssExtractPlugin.loader 即可:

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

module.exports = {
    /* ... */
    module: {
        rules: [
            /* ... */
            {
              test: /\.s[ac]ss/,
              exclude: /(node_modules|build)/,
              use: [
                MiniCssExtractPlugin.loader,,
                'css-loader',
                'sass-loader'
              ],
            },
        ]
    },
    plugins: [
    	new MiniCssExtractPlugin({
         filename: 'css/index.[contenthash:10].css',
       }),
    ]
    /* ... */
}

css兼容性处理

在日常开发中,为了让css样式能够适用于大多数的设备或者浏览器,我们需要对css做好兼容性处理。

css的兼容性处理需要用到 postcsspostcss 是一个用 JavaScript 工具和插件转换 CSS 代码的工具。在webpack中使用它需要用到两个包:postcss-loader 以及 postcss-preset-env

其中,postcss-preset-env 的作用是帮助 postcss-loader 找到 browserslist 的配置,加载指定的兼容性。browserslist 一般会配置到package.json下,或者在根目录下有一个 .browserslistrc 的文件去写相关的配置。

注意:package.json中的配置与.browserslistrc文件,两者只能存其一,否则会报错!!

安装

yarn add -D postcss-loader postcss-preset-env

配置

我们在上面的loader配置基础上进行一些修改:

{
  test: /\.s[ac]ss$/i,
  use: [
    MiniCssExtractPlugin.loader,
    'css-loader',
    {
      loader: 'postcss-loader',
      options: {
        postcssOptions: {
          plugins: [
            [
              'postcss-preset-env',
              {
                // Options
              },
            ],
          ],
        },
      }
    },
    // 将 Sass 编译成 CSS
    'sass-loader',
  ],
},

然后在 package.json 文件中添加如下配置(更多配置可以参考:browserslist):

"browserslist": {
    "development": [ // 开发环境
      "last 1 chrome version",
      "last 1 safari version",
      "last 1 firefox version"
    ],
    "production": [ // 生产环境
      "> 0.2%",
      "not dead",
      "not op_mini all"
    ]
}

或者也可以在根目录下创建.browserslistrc文件。

注意:配置项是有顺序的!!> 0.2%写到后面会报错

> 0.2%
not dead
not op_mini all

关于postcss-loader更多的配置可以参考

css文件压缩

在对css文件做完兼容性处理并提取成单个文件之后,我们可以进一步对其进行优化,将抽出的css文件进行压缩。此时我们需要用到一个插件: optimize-css-assets-webpack-plugin

安装

yarn add -D optimize-css-assets-webpack-plugin

使用

使用非常简单 ,只需要在 webpack.config.js 中引入使用即可。默认配置已经可以满足压缩需要,如果需要添加配置,可以参考

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    /* ... */
    module: {
      rules: [
        /* ... */
        {
          test: /\.s[ac]ss$/i,
          use: [
            MiniCssExtractPlugin.loader,
            'css-loader',
            {
              loader: 'postcss-loader',
              options: {
                postcssOptions: {
                  plugins: [
                    [
                      'postcss-preset-env',
                      {
                        // Options
                      },
                    ],
                  ],
                },
              }
            },
            // 将 Sass 编译成 CSS
            'sass-loader',
          ],
        },
      ]
    },
    plugins: [
    	new MiniCssExtractPlugin({
         filename: 'css/index.[contenthash:10].css',
       }),
       new OptimizeCssAssetsWebpackPlugin()
    ]
    /* ... */
}

预告

通过这两节,我们已经知道了webpack中如何对css文件进行处理,并在此过程中对其做了一些优化,包括提取单个css文件,兼容性处理以及css代码压缩。

下一节我们一起来看下,除了css文件与js文件外,其他的文件webpack要如何进行处理呢?拭目以待吧~