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
- happypack:提高打包速度
- mini-css-extract-plugin分离css文件,提高用户体验
最新评论
这小生活不错呀
不错,必须顶一下!
看着你还在坚持,很好
看来忙了也没时间更新博客了
NIce。学习了。。。。
网站不错!!!!
简洁实用,好文章!
不错,过来支持一下