日更挑战-Webpack打包拆包流程
越不懂的越爱装
大家都同等:IT世界没有难不难,只有是否了解过
挑战目录
什么是Webpack
是一个将各种资源(包括浏览器不能直接识别的),打包成浏览器能识别的模块化打包工具。
如何打包
- 从配置文件和命令行中合并参数
- 用上面的参数创建Compiler对象,加载所有配置的插件
- 执行Compiler的run方法开始构建
- 通过配置文件配置的入口文件,串行开始,递归搜索所有依赖的文件(一切文件都看做模块)。
- 每找到一种后缀的文件时,将文件传入通过rules配置的loader处理后生成处理过的数据。
- 根据上述处理出的文件数据,和依赖关系。组装成一个个chunk,然后将chunk转成一个个文件。加入到输出列表
- 根据配置将文件输出到输出目录
- 在上述过程中广播各种事件通知响应的插件进行处理。获得最终的处理文件。
什么是 module、chunk和bundle
- module:指要处理的原始文件
- 所有文件都被视为模块,简单来说就是你通过import语句引入的代码
- chunk:指文件数据
-
chunk对应module,可能是一对多也可能是一对一。
-
webpack根据功能拆分出来的。
拆分依据主要有以下三种:1. 项目入口(entry) 入口会拆成一个chunk,多个项目入口会拆分成多个不同的chunk 2. 通过import()动态引入的代码 例如路由里组件的动态载入,导致每个路由界面都会拆成一个chunk 3. 通过splitChunks拆分代码 看下面"通过splitChunks拆分代码"的具体介绍
-
- bundle:指文件,
- 一般和chunk是一对一的关系
- 对chunk进行编译压缩打包等处理之后的产出
通过splitChunks拆分代码
-
splitChunks默认配置(webpack4什么都不做时)
splitChunks配置项都是作用于cacheGroup上的
module.exports = { //... optimization: { splitChunks: { chunks: 'async', minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } } } };
-
chunks 拆分模块的范围(async、initial和all),没有单独拆分出来的放到cacheGroups配置的chunk里面
async:只从异步加载得模块(动态加载import())里拆分新的chunk
initial:只从入口模块进行拆分新的chunk
all:以上两者都包括
-
cacheGroups 配置其他的模块组合起来的大类(将多个模块组成一个大的chunk)
-
maxInitialRequests 一个入口最多拆分出来的chunk个数,超过这个就不会再单独拆分出来chunk
- 入口文件算一个
- 动态加载的模块不算
- runtimeChunk拆分出的runtime不算
- 只算js文件
- 在maxInitialRequests临界点时: 更大的模块会被拆分优先
-
maxAsyncRequests 动态加载的模块,导入操作时连带的最多chunk个数
- import()文件本身算一个
- 不算js以外的公共资源请求
- 在maxAsyncRequests临界点时: 更大的模块会被拆分优先
-
minChunks、maxAsyncRequests、maxInitialRequests的值必须设置为大于等于1的数
-
当chunk没有名字时,通过splitChunks分出的模块的名字用id替代,当然你也可以通过name属性自定义
-
当父chunk和子chunk同时引入相同的module时,并不会将其分割出来而是删除掉子chunk里面共同的module,保留父chunk的module,这个是因为 optimization.removeAvaliableModules 默认是true
-
当两个cacheGroup.priority相同时,先定义的会先命中
-
除了js,splitChunks也适用于css
-
-
splitChunks配置大全:
pass
如何优化输出结果,提高构建速度
-
UglifyJSPlugin优化项
- 压缩js,删除日志和debugger,使用uglifyjs插件压缩js代码
- 使用多进程并行运行来提高构建速度
- 启用文件缓存来提高构建速度
configureWebpack: config => { if (process.env.NODE_ENV === "production") { const plugins = []; plugins.push( new UglifyJSPlugin({ uglifyOptions: { //删除注释 output: {comments: false}, //删除console 和 debugger 删除警告 compress: { warnings: false, drop_debugger: true, drop_console: true } }, cache: true, // 启用文件缓存 parallel: true // 使用多进程并行运行来提高构建速度 }) ); config.plugins = [...config.plugins, ...plugins]; } },
-
提取公共代码:
- 抽取公共模块(文件)代码
- 抽取公共依赖(第三方模块)
1. 通过前面的splitChunks配置 2. 通过commons-chunk-plugin插件 3. 通过externals配置来提取常用库
-
压缩css:使用cssnano插件压缩css代码
- 在配置loader是追加参数css-loader?minimize
-
cdn加速:
- 将引用的静态文件设置为cdn上的路径
-
删除死代码:在启动webpack时追加参数
- 启动webpack时追加参数--optimize-minimize,自动识别不会走到的代码并删除。
-
预编译资源模块:
- 通过 DllPlugin对不会修改的npm包来进行预编译
- 通过
DllReferencePlugin
将预编译的模块加载进来
-
多线程加载编译:使用happypack
-
提高uglify的速度:使用webpack-uglify-parllel多核并行压缩
-
剔除多余代码:使用tree shocking和scope
-
剔除组件库中的多余组件:使用官方的插件
什么是loader
-
加载器:加载和解析非js文件的能力。
-
自定义loader:满足以下规则的,则认为是一个loader
在模块的入口js文件中,导出一个
什么是plugin
扩展功能:或者webpack的功能。要知道这里的作用需要发挥想象力。
常用的loader
- file-loader
- url-loader:可以在文件很小的时候,通过转成base64进行加速
- source-map-loader:生成额外的source-map文件,方便浏览器调试。
- img-loader:
- eslint-loader:通过eslint检测代码。
常用的plugin
- define-plugin:定义环境变量
- commons-chunk-plugin:提取公共代码
- uglifyjs-webpack-plugin:压缩(丑化)js代码