深入 Webpack5 等构建工具系列二(5) - webpack 的 style-loader 的使用和编写顺序

893 阅读4分钟

这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战

上一篇文章的最后,我们运行 npm run build 命令对项目中的相关文件进行了打包,其中,css 文件实际上也已经被打包了,或者也可以说 css 文件已经加载成功了。那加载成功后浏览器打开的页面中的文字为什么没有变成红色呢?

image-20210124180418321.png

显然,样式没有作用到 index.html 页面中。我们知道,要想给某个元素添加样式,常用的方法有 3 种:

  • 行内样式(直接把样式写到元素里面作为属性);
  • 页内样式(在 head 元素下添加 style 元素,再在 style 元素下编写样式);
  • 外部样式(对 css 文件进行引入);

而在上图中,可以看到,没有行内样式,head 元素下没有 style 元素,所以也没有页内样式。而如果是使用外部样式,则意味着打包后生成文件的输出位置应该会有单独的 css 文件(因为我们得引入它),那我们来看当前的项目目录:

image-20210124181006471.png

可以看到,build 文件夹下除了 bundle.js 文件并没有 css 文件。可见,这里也没有使用外部样式。

因此,页面中没有使用任何一种方式给这个 div 元素添加样式,所以页面中的字体颜色并不会变成红色。也就是说,我们虽然已经使用 css-loader 成功处理了这个 index.css 文件,但是并没有把处理之后的样式作用到页面中。

认识 style-loader

  • 我们已经可以通过 css-loader 来加载 css 文件了

    • 但是你会发现这个 css 在我们的代码中并没有生效(页面没有效果)
  • 这是为甚莫呢?

    • 因为 css-loader 只是负责将 .css 文件进行解析,并不会将解析之后的 css 插入到页面 中;
    • 如果我们希望再完成插入 style 的操作,那么我们还需要另外一个 loader,即 style-loader
  • 安装 style-loader

    npm i style-loader -D
    
    • 因为这里的话作为开发时依赖就可以了,所以使用 -D

运行 npm i style-loader -D 命令安装好 style-loader 以后,我们下面就要使用它了。怎么用它呢?当然是来到配置文件 wk.config.js 中进行配置啦~

因为 style-loader 也是用来处理 css 的,所以当匹配到 css 文件时,就应该要使用这个 loader 了。因此,对于 style-loader 的配置,也应该在 test: /.css$/ 所在的 Rule 对象的 use 属性中进行编写。

先上代码:

module: {
  rules: [
    {
      // 规则使用正则表达式
      test: /.css$/, // 匹配资源
      use: [
        // { loader: 'css-loader' }
        'css-loader',
        'style-loader'
      ],
      // loader: 'css-loader'
    }
  ]
}

这样配置完以后,就意味着当匹配到 css 文件时,既会使用 style-loader 来处理,也会使用 css-loader 来处理,那么两个 loader 都会使用的话,应该有个先后顺序吧?是的,按常理,先用上面的(左边的),再用下面的(右边的),但是,webpack 有点不一样,人家是反过来的哈,即 loader 是从后往前(从右到左或从下到上)地取值(evaluate)/执行(execute)的。

所以,思考一下,上面配置的写法是不是有问题呢?应该是先用 css-loadercss 文件进行加载(解析),然后才能把加载(解析)完成后的 css 代码通过 style-loader 的处理插入到页面中呀~如果你都没有解析,那怎么能直接就插入到页面中呢?你肯定是插入不进去的。所以,我们这里应该是先用 css-loader 来处理,再用 style-loader 来处理,那因为 webpackloader 的加载顺序是从右到左(或从下到上)加载的,因此,上面的配置应该修改如下:

module: {
  rules: [
    {
      // 规则使用正则表达式
      test: /.css$/, // 匹配资源
      use: [
        // { loader: 'css-loader' }
        // 注意:编写顺序(从下往上,从右往左,从后往前)
        'style-loader',
        'css-loader'
      ],
      // loader: 'css-loader'
    }
  ]
}

你可能会问,在不改变 loader 顺序的情况下,能不能指定某个 loader 先执行呢?其实也有办法,我们后面讲自定义 loader 时,就可以在自定义 loader 中编写一个函数,到时候就会先执行这个函数。但是,正常情况下,loader 的取值(evaluate)/执行(execute)顺序都是从右到左(或从下到上)的。

好,下面我们再来运行 npm run build 对代码进行编译打包,然后再来看浏览器中页面的文字效果:

image-20210124214142410.png

可以看到,文字变成了红色,样式生效了。

实际上,style-loader 通过 js 代码 document.createElement('style') 创建了一个 style 元素,然后把 css 样式放到这个元素下,最后通过页内样式的方式把 css 样式插入到了页面中。