美文网首页
Webpack实战(五):轻松读懂Webpack如何分离样式文件

Webpack实战(五):轻松读懂Webpack如何分离样式文件

作者: 前端岚枫 | 来源:发表于2020-01-18 10:21 被阅读0次

    在上一篇文章中我给大家分享了预处理器(loader),里面讲到了style-loader 和css-loader,有关样式引入的问题,但是上面的样式文件只是引入到style标签里面,并不是我想要的样式文件独立分离。

    如果想了解有关css-loader和style-loader可以参考以下地址:

    Webpack实战(四):教教你如何轻松搞定-预处理器(loader)

    通过js引入样式文件只是把样式添加到style标签内,而不是引入一个独立的css文件,一般来说,在生产环境下,我们希望样式存在于CSS文件中而不是style标签中,因为文件更有利于客户端进行缓存。

    Webpack社区有专门的插件:extract-text-webpack-plugin(适用于Webpack 4之前版本)和mini-css-extract-plugin(适用于Webpack 4及以上版本),它们就是专门用于提取样式到CSS文件的。

    1. extract-text-webpack-plugin
      extract-text-webpack-plugin安装命令代码如下:
    # for webpack 3 
    npm install --save-dev extract-text-webpack-plugin
    # for webpack 2 
    npm install --save-dev extract-text-webpack-plugin@2.1.2
    # for webpack 1 
    npm install --save-dev extract-text-webpack-plugin@1.0.1
    

    由于webpack版本不一样,extract-text-webpack-plugin安装的出来版本的也不一样。

    配置代码如下:

    const ExtractTextPlugin = require("extract-text-webpack-plugin");
     const path = require('path')
    module.exports = {
      context: path.join(__dirname, './src'),
      entry: {
        index: './index.js'
      },
      output: {
        path: path.join(__dirname, 'dist'),
        filename: 'index.js'
      },
      mode: 'development',
      module: {
        rules: [
          {
            test: /\.css$/i,
           use: ExtractTextPlugin.extract({
              fallback: "style-loader",
              use: "css-loader"
            }),
            exclude: /node_modules/
          },
          {
            test: /\.js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
              loader: 'babel-loader',
              options: {
                cacheDirectory: true,
                presets: [
                  [
                    'env', {
                      modules: false
                    }
                  ]
                ]
              }
            }
          }
        ],
      },
      plugins: [
        new ExtractTextPlugin("styles.css") //提取后css文件名称
      ]
    }
    

    在module.rules中我们设置了处理CSS文件和js文件的规则,其中css配置的use字段并没有直接传入loader,而是使用了插件的extract方法包了一层。内部的fallback属性用于指定当插件无法提取样式时所采用的loader,use(extract方法里面的)用于指定在提取样式之前采用哪些loader来预先进行处理。除此之外,还要在Webpack的plugins配置中添加该插件,并传入提取后的资源文件名。
    由于我电脑项目里装的4.0以上的webpack版本,这里不再做打包测试。
    样式的提取是以资源入口开始的整个chunk为单位的。比如我们的应用从index.js开始引入了几百个模块,这些模块都引入了它们各自的样式文件,但是最终生成的c s s文件只有一个,因为它们都来自同一个入口模块。上面我们讲styles.css作为文件名传给extract-text-webpack-plugin,但是当项目有多个入口的时候就会发生重名问题。就像我们前面动态配置的output.filename一样。这里我们也将要对插件提取的css文件使用类似模版的命名方式。

    下面是入口的index.js和about.js

    // index.js
    import './index.css'
    
    // about.js
    import './about.css'
    

    we bpack.config.js配置部分代码如下

    const ExtractTextPlugin = require("extract-text-webpack-plugin");
     const path = require('path')
    module.exports = {
      context: path.join(__dirname, './src'),
      entry: {
        index: './index.js',
        about: './about.js'
      },
      output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name].js'
      },
      mode: 'development',
      module: {
        rules: [
          {
            test: /\.css$/i,
           use: ExtractTextPlugin.extract({
              fallback: "style-loader",
              use: "css-loader"
            }),
            exclude: /node_modules/
          },
          {
            test: /\.js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
              loader: 'babel-loader',
              options: {
                cacheDirectory: true,
                presets: [
                  [
                    'env', {
                      modules: false
                    }
                  ]
                ]
              }
            }
          }
        ],
      },
      plugins: [
        new ExtractTextPlugin("[name].css") //提取后css文件名称
      ]
    }
    

    我们使用[name].css来动态生成c s s文件名,name为即entry中我们为每一个入口分配的名字(index、about),由此可以推出[name]指的是chunk(chunk是对一组有依赖关系的模块的封装)的名字。

    1. mini-css-extract-plugin
      mini-css-extract-plugin 是 extract-text-webpack-plugin的升级版本,它拥有更多的特性和更好的性能。最突出的一条就是 mini-css-extract-plugin支持按需加载css,举个例子,a.js通过import()函数异步加载了b.js,b.js里面加载了style.css,那么style.css最终只能被同步加载(通过HTML的link标签)。但是现在mini-css-extract-plugin会单独打包出一个0.css(假设使用默认配置),这个CSS文件将由a.js通过动态插入link标签的方式加载。
      首先安装mini-css-extract-plugin
    npm install --save-dev mini-css-extract-plugin
    

    下面是入口的index.js和index2.js

    // index.js
    import './common.css'
    
    // index2.js
    import './style.css'
    

    web pack.config.js配置如下:

    const path = require('path')
    const MiniCssExtractPlugin = require('mini-css-extract-plugin')
    module.exports = {
      context: path.join(__dirname, './src'),
      entry: {
        index: './index.js',
        index2: './index2.js'
      },
      output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name].js'
      },
      mode: 'development',
      module: {
        rules: [
          {
            test: /\.css$/i,
            use: [{
              loader: MiniCssExtractPlugin.loader,
              options: {
                publicPath: '../'
              },
            }, 'css-loader'],
            exclude: /node_modules/
          },
          {
            test: /\.js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
              loader: 'babel-loader',
              options: {
                cacheDirectory: true,
                presets: [
                  [
                    'env', {
                      modules: false
                    }
                  ]
                ]
              }
            }
          }
        ],
      },
      plugins: [new MiniCssExtractPlugin({
        filename: '[name].css',
        chunkFilename: '[id].css'
      })],
    }
    

    打包效果如下:


    在这里插入图片描述

    可以发现最后输出两个c s s文件名分别为chunk 名,index.css,index2.css

    在配置上mini-css-extract-plugin与extract-text-webpack-plugin有以下几点不同

    • loader规则设置的形式不同,并且mini-css-extract-plugin支持配置publicPath,用来指定异步CSS的加载路径。
    • 不需要设置fallback。
    • 在plugins设置中,除了指定同步加载的CSS资源名(filename),还要指定异步加载的CSS资源名(chunkFilename)。

    总结

    Webpack样式文件分离,主要用两个插件mini-css-extract-plugin与extract-text-webpack-plugin,它们有着各自的特点,但是如果webpack版本4.0以上建议用mini-css-extract-plugin,它拥有更多的特性,特别是按需加载cs s,解决了一些性能问题。

    如果想了解更多,请扫描二维码:


    在这里插入图片描述

    相关文章

      网友评论

          本文标题:Webpack实战(五):轻松读懂Webpack如何分离样式文件

          本文链接:https://www.haomeiwen.com/subject/tnlkzctx.html