常用的loader和plugin和devtool
-
loader
-
babel-loader 转译js代码
可以使用include和exclude帮助我们避免不必要的转译,开启缓存转译可以提升工作效率
use:{ exclude:/(node_module|bower_components)/, loader:'babel-loader?cacheDirectory=true' }
-
css-loader 转译css文件 对@import和require处理
-
style-loader 把css-loader转译后得结果插入到脚本中 显示样式
-
sass-loader/less-loader预编译和转换sass/less文件
-
file-loader 将加载文件、图片 import/require() 解析为url,将文件发送到输出文件夹,返回文件的url
-
url-loader 是file-loader的扩展可以设置对图片的大小限制,小于限制用base64编译返回输出,大于限制使用file-loader传递参数
-
-
plugin
- DllPlugin 作用和optimization.splitChunk作用相似,拆分bundles,提高构建速度
- SplitChunksPlugin 分离公共的第三方模块及业务代码
- MiniCssExtractPlugin 抽离css,删除和压缩css代码,是extract-text-webpackplugin插件的webpack5升级用法,可以实现contenthash,保证只要css文件内容不变,就不会重复构建css文件
- HtmlWebpackPlugin 为html文件动态引入外部资源给script、link添加编译后的hash,防止引用缓存文件问题、可以生成创建html入口文件,比如单页生成一个html入口文件,多页面生成多个html
- UglifyjsWebpackPlugin 删除和压缩js代码
- CleanWebpackPlugin 每次编译会删除上一次编译的dist文件
- CopyPlugin 复制开发环境中public中的文件
-
devtool
生产环境中使用 inline-source-map
开发环境中使用 eval-cheap-module-source-map
生成source-map文件,可以看到清晰的build后的代码结构,方便出错调试
- cheap可以提高souremap的生成效率
- eval 提高持续构建效率
代码分割的几种方式
- 在入口entry手动分离代码
- 使用optimization.splitChunks、SplitChunkPlugin分离代码
- 动态引入 使用import导入,使用的时候再去下载对应的文件
- Tree-shaking webpack内置优化,去除没有用到的代码
- 防止重复 CommonsChunkPlugin去重和分离chunk
SplitChunkPlugin的用法
optimization: {
splitChunks: {
chunks: 'all',
minSize: 0,
minRemainingSize: 0,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
enforceSizeThreshold: 50000,
cacheGroups: {
defaultVendors: {
// test: /[\\/]node_modules[\\/]/,
test(module) {
if (/[\\/]node_modules[\\/]/.test(module.resource) && module.resource.lastIndexOf('.css') === -1) {
return true
}
},
priority: -10,
reuseExistingChunk: true,
filename: function(chunk) {
return 'js/chunks-vendors-[contenthash:8].js'
},
// exclude: '*.css'
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
}
- chunks
- saync 表示只从异步加载的模块(动态加载 import())进行拆分
- initial 表示拆分同步代码
- all表示以上两者都拆分
- minSize表示分离后最小块文件的大小,单位是字节
- minRemainingSize
- minChunks 引入的次数大于1次进行代码分割
- maxAsyncRequests 最大异步请求数量 就是同时加载的模块最大模块数量
- maxInitialRequests 入口文件做代码分割最多分成30个文件
- enforceSizeThreshold
- cacheGroups 位于node_modules中的模块做代码分割 使用正则,根据模块的分类进行打包
- priority 根据优先级决定打包到哪个组里,打包到优先级高的组里
- reuseExistingChunk 如果一个模块已经被打包过了,那么再打包时就忽略这个上模块
热替换
devServer中hot:ture启动热替换,改变html页面不刷新,只更新改变的部分
Tree Shaking
ESM es module
去掉不需要,用不到的代码或者模块
sideEffects 在package.json中设置,webpack认为可以删除的就可以删除
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P2roak9x-1629114600765)(C:\Users\yt\AppData\Roaming\Typora\typora-user-images\image-20210802093249316.png)]
不删除css文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DNFpH1rE-1629114600769)(C:\Users\yt\AppData\Roaming\Typora\typora-user-images\image-20210802093359226.png)]
关于TreeShaking的原理
Tree shaking是一种通过清除多余代码方式来优化项目打包体积的技术,专业术语叫
Dead code elimination
tree shaking只能在静态modules下工作,由于ES6模块加载是静态的,因此整个依赖树可以被静态的推导出解析语法树。
原理:
- ES6 Modules引入静态分析,编译的时候能够判断到底加载了哪些模块
- 静态分析程序流,判断哪些模块和变量没有被引用,进而删除对应代码。
common.js和es6的模块导出区别
我们在webpack中使用的export和import,会经过Babel转换为CommonJs规范。
- CommonJS模块输出的是一个值的拷贝,ES6模块输出的是值的引用。
- CommonJS模块是加载时运行,ES6模块是编译时输出接口
- CommonJS是单个值的导出,ES6可以导出多个
- CommonJS是动态语法可以写在判断里,ES6静态语法只能写在顶层
- CommonJS的this是当前模块,es6的this是undefined
webpack Plugin的工作原理
读取配置的过程中会先执行 new HelloPlugin(options) 初始化一个 HelloPlugin 获得其实例。
初始化 compiler 对象后调用 HelloPlugin.apply(compiler) 给插件实例传入 compiler 对象。
插件实例在获取到 compiler 对象后,就可以通过compiler.plugin(事件名称, 回调函数) 监听到 Webpack 广播出来的事件。 并且可以通过 compiler 对象去操作 Webpack。
https://blog.csdn.net/frontend_frank/article/details/106205260 可以看一下这位博主的文章。
preload和prefetch
可以在html中的link标签添加rel=preload等
<head>
<link rel="preload" as="font" href="<%= require('/assets/fonts/AvenirNextLTPro-Demi.otf') %>" crossorigin>
<link rel="preload" as="font" href="<%= require('/assets/fonts/AvenirNextLTPro-Regular.otf') %>" crossorigin>
</head>
在webpack中
插件preload-webpack-plugin,结合htmlWebpackPlugin在构建构成中插入link标签
const PreloadWebpackPlugin = require('preload-webpack-plugin');
...
plugins: [
new PreloadWebpackPlugin({
rel: 'preload',
as(entry) { //资源类型
if (/\.css$/.test(entry)) return 'style';
if (/\.woff$/.test(entry)) return 'font';
if (/\.png$/.test(entry)) return 'image';
return 'script';
},
include: 'asyncChunks', // preload模块范围,还可取值'initial'|'allChunks'|'allAssets',
fileBlacklist: [/\.svg/] // 资源黑名单
fileWhitelist: [/\.script/] // 资源白名单
})
]
include属性默认asyncChunks,表示预加载异步js模块;allAssets表示预处理所有类型资源(图片、字体等)
preload用来声明当前页面的关键资源,强制浏览器尽快加载;而prefetch用来声明将来可能用到的资源,在浏览器空闲时进行加载。
编写loader和plugin
compile编译
垫片 装下面两个包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NTfZB5kJ-1629114600775)(C:\Users\yt\AppData\Roaming\Typora\typora-user-images\image-20210802114123567.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q1lCd7CG-1629114600778)(C:\Users\yt\AppData\Roaming\Typora\typora-user-images\image-20210802114129914.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DJx2DyH3-1629114600783)(C:\Users\yt\AppData\Roaming\Typora\typora-user-images\image-20210802114203601.png)]