陌上寒

陌上寒个人博客

webpack4两个常用的plugin之 happypack和mini-css-extract-plugin

《webpack4两个常用的plugin之 happypack和mini-css-extract-plugin》

happypack是做什么的?

webpack打包哪一步最耗时?可能要数loader对文件的转换操作了,我们前面说过,我们使用loader将文件转换为我们需要的类型,文件数量巨大,webpack执行又是单线程的,转换的操作只能一个一个的处理,不能多件事一起做。
我们需要Webpack 能同一时间处理多个任务,发挥多核 CPU 电脑的威力,HappyPack 就能让 Webpack 做到这点,我们将需要通过loader处理的文件先交给happypack去处理,happypack 在收集到这些文件的处理权限后,统一分配CPU资源

happypack工作原理

happypack 通过new HappyPack(),去实例化一个HappyPack对象,其实就是告诉Happypack核心调度器如何通过一系列loader去转换一类文件,并且可以指定如何为这类转换器作分配子进程。
核心调度器的逻辑代码在主进程里,也就是运行webpack的进程中,核心调度器会将一个个任务分配给当前空闲的子进程,子进程处理完后会将结果发送给核心调度器,它们之间的数据交换是通过进进程间的通讯API实现的。
核心调度器收到来自子进程处理完毕的结果后,会通知webpack该文件已经处理完毕

举个栗子🌰

我们先看一个demo,体会一下happypack

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HappyPack = require('happypack')
//构造出一个共享进程池,在进程池中包含4个子进程
const happyThreadPool = HappyPack.ThreadPool({
    size: 4
})
module.exports = {
    //省略部分配置
      module: {
           rules: [
                {
                test: /\.js$/,
            //将对.js文件的处理转交给id为babel的happypack实例
                use: ['happypack/loader?id=babel']
                //排除node_modules下的js,合理的使用排除可以事半功倍
                exclued:path.resolve(__dirname,'node_modules')
            },
              {
                test: /\.css$/,
                  //将对.css文件的处理转交给id为css的happypack实例
                    use: ExtractTextPlugin.extract({
                    fallback: "style-loader",
                    use: ['happypack/loader?id=css']
                })
            } ]
       },
      plugins: [
            new HappyPack({
            // 用唯一的标识符 id 来代表当前的 HappyPack 是用来处理一类特定的文件
            id: 'babel',
            // 如何处理 .js 文件,用法和 Loader 配置中一样
            loaders: ['babel-loader?cacheDirectory=true'],
            //使用共享进程池中的自进程去处理任务
            threadPool: happyThreadPool,
            //是否允许happypack输出日志,默认true
            verbose: true
        }),
          new HappyPack({
            id: 'css',
            // 如何处理 .css 文件,用法和 Loader 配置中一样
            loaders: ['css-loader!postcss-loader'],
            threadPool: happyThreadPool
        }),
      ]
}

代码如上,在module中通过rules去匹配文件,对我们匹配上的文件分配loader,如果要使用happypack,就添加一个唯一标识符“id”(happypack/loader?id=babel),然后在plugin中实例化happypack,happypack中有几个参数,我们介绍一下

  • id:如上所说,在module中对匹配到的文件如果要使用happypack,就设置一个唯一标识符“id”,两个id相对应
  • loaders 和我们之前介绍的loader用法相同
  • threads :代表开启几个子进程去处理这一类型的文件,默认是3个,必须是正数
  • verbose:是否允许happypack输出日志,默认true允许
  • threadPool : 代表共享进程池,即多个happypack实例都使用同一个共享进程池中的子进程去处理任务,以防止资源占用过多,

注意⚠️

注意,webpack4中的happypack要使用5.0.0版本,如果你是从webpack3升级到webpack4,记得升级happypack
上面的loader中出现一个陌生词cacheDirectory:
cacheDirectory默认值为 false。
当有设置时,指定的目录将用来缓存 loader 的执行结果。之后的 webpack 构建,将会尝试读取缓存,来避免在每次执行时,可能产生的、高性能消耗的 Babel 重新编译过程(recompilation process)。如果设置了一个空值 (loader: ‘babel-loader?cacheDirectory’) 或者 true (loader: babel-loader?cacheDirectory=true),loader 将使用默认的缓存目录 node_modules/.cache/babel-loader,如果在任何根目录下都没有找到 node_modules 目录,将会降级回退到操作系统默认的临时文件目录。
关于happy的介绍就那么多
上边的代码中出现了MiniCssExtractPlugin,这是什么?

mini-css-extract-plugin

这个plugin看起来可能有点陌生,但是这个extract-text-webpack-plugin,可能不那么陌生了,它们都是用来从js中分离css的,webpack3中还是extract-text-webpack-plugin,但是在webpack4中你如果还要使用它你必须这样

npm i -D extract-text-webpack-plugin@next

就是要升级到v4.0.0-beta.0,不过在webpack4中推荐使用mini-css-extract-plugin,
为什么要分离css?如果不分离css,那么css会和js打包在一起,当页面加载时,不会只有加载完相应的js文件,才会加载css样式,这个期间页面展示可能会很不友好,所以,分离css很有必要。使用起来也很容易继续,看代码片段:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
//部分代码省略
    module: {
        rules: [{
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    "css-loader"
                ]
            },
            {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    "less-loader"
                ]
            },
            {
                test: /\.scss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    "sass-loader"
                ]
            }
        ]
    },
    plugins:[
         new MiniCssExtractPlugin({
            filename: "[name].css",
            chunkFilename: "[id].css"
        })
    ]
}

我们在从零搭建webpack4之output输出介绍过

  • filename:这个是输出文件的名
  • chunkFilename :此选项决定了非入口(non-entry) chunk 文件的名称,可以理解为通过异步加载(分块打包)打包出来的文件名称

异步加载会打包出很多css,这可能不是我们想要的,因为可能每个页面的css样式代码量很小,实在是没有必要,所以我们可以将其合并
将多个css chunk合并成一个css文件

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {            
          name: 'styles',
          test: /\.scss|css$/,
          chunks: 'all',    // merge all the css chunk to one file
          enforce: true
        }
      }
    }
  }
}

总结

今天介绍了两个常用的plugin

  1. happypack:提高打包速度
  2. mini-css-extract-plugin分离css文件,提高用户体验

福利

周末到了,整理了一套007电影送给大家,公众号后台回复“007”即可领取
《webpack4两个常用的plugin之 happypack和mini-css-extract-plugin》

参考链接
webpack优化之HappyPack 实战

发表评论

电子邮件地址不会被公开。