webpack5⽂档解析(下)
声明:所有的⽂章demo都在我的⾥
代码分离
代码分离的有点在于:
1. 切割代码,⽣成不同的打包⽂件,按需加载这些⽂件。
2. 每个bundle的体积更⼩
3. 控制外部资源的加载顺序
常⽤的⽅法有:
1. ⼊⼝起点:使⽤⼊⼝entry⼿动分离
2. 防⽌重复:使⽤SplitChunksPlugin去重和分离chunk
3. 动态导⼊:通过模块的内联函数调⽤分离的代码
⼊⼝起点
新增另⼀个⽂件another-module.js⽂件,并在fig.js中进⾏配置。
entry:{//打包⼊⼝
index:'./src/index.js',
another:'./src/another-module.js'
},
进⾏打包后,结果正常。
优点:常⽤常规的写法。
缺点:1.如果有相同的模块,不会去重,还是会在每个bundle中被重复的引⽤。2.不能将核⼼代码进⾏分割
防⽌重复
⼊⼝依赖
配置dependOn选项,可以在多个chunk之间进⾏共享模块。
SplitChunkPlugin
为了解决多个bundle引⼊相同模块的问题,引⼊这个模块进⾏去重。
SplitChunkPlugin将公共的模块引⼊到已有的⼊⼝中,或者提取到新的chunk。
相关配置如下:
//fig.js
optimization:{
splitChunks:{
chunks:'all'
}
},
SplitChunkPlugin创建了新的chunk,如下图所⽰,shared.bundle.js。将我其他页⾯所使⽤的js引⼊的lodash模块引⼊这个⽂件中。
*** 以上代码在webpack-demo5中
缓存
通常部署⽂件是将webpack打包出来的/dist⽂件,部署到server上,客户端通过访问server的⽹站及资源。
由于客户端访问server时,⾮常耗时和耗流量,于是浏览器采⽤缓存技术,可以直接从缓存中获取相关的内容,降低了请求的速度和流量。但是这也有⼀个缺点:如果⽂件名跟之前的⼀致,浏览器会认为这个⽂件没有做修改,还是会从缓存中获取相关内容。
我们想要的现象是:⽂件没做修改时,浏览器从缓存中获取,⽂件修改了,重新获取。
输出⽂件的⽂件名
webpack提供了⼀个substitution(可替换的模版字符串)的⽅式,通过带括号字符串来模版化⽂件名。其中的[contenthash]是根据资源内容创建唯⼀的hash。当资源内容变化时,[contenthash]也会发⽣变化。
相关配置如下:
entry:'./src/index.js',
output:{//打包出⼝
filename:"[name].[contenthash].js",//打包后的⽂件名称
solve(__dirname,'dist')//路径
},
使⽤contenthash,将内容变化直接反应打包输出⽂件的变化。
⽂件不做修改,再次运⾏npm run build时,⽂档描述如下:
在我的实际操作中,我的打包⽂件是不变的。
第⼀次:
第⼆次:
可能跟webpack版本的关系所致。。。
模块的概念
runtime:每个模块的加载和模块的解析逻辑。
manifest:解析和映射模块之间的联系
提取引导模版
将runtime代码,提取到⼀个单独的chunk中。optimization.runtimeChunk:'single'表⽰为所有的chunk创建⼀个runtime bundle。
代码如下:
optimization:{
runtimeChunk:'single'
},
将所有的第三⽅库,如lodash/react等提取到单独的vendor chunk⽂件中。由于这些第三⽅库不会去频繁的修改源代码,所以可以让更少的向server发请求。
配置如下:
const path=require('path');
const {CleanWebpackPlugin}=require('clean-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
mode:'development',
entry:'./src/index.js',
output:{//打包出⼝
filename:"[name].[contenthash].js",//打包后的⽂件名称
solve(__dirname,'dist')//路径
},
devtool: 'inline-source-map',
devServer:{
contentBase:'./dist'
},
optimization:{
runtimeChunk:'single',
splitChunks:{
cacheGroups:{
vendor:{
test:/[\\/]node_modules[\\/]/,
name:'vendor',
chunks:'all'
webpack打包流程 面试}
}
}
},
plugins:[
new CleanWebpackPlugin({
cleanStaleWebpackAssets:false
}),
new HtmlWebpackPlugin({
title:'管理输出'
})
]
}
结果会出现⼀个带有vendor的⽂件。
在main⽂件⾥,不再含有来⾃node_module的vendor代码,⽽且体积也减少了。
模块标识符
新增print模块,并在index中进⾏引⼊,最终打包的结果跟之前⽐较结果如下:
我本地打包只有main的⽂件进⾏了变化----符合预期
然⽽官⽹上展⽰的例⼦是不⼀样,引出了需要引⼊duleIds:'hashed'---苦笑不得
*** 以上代码在webpack-demo6中
环境变量
可以在package.json中配置相关的命令⾏,可以快速的执⾏开发环境和⽣产环境。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"start": "webpack serve --env development"
},
表⽰执⾏development环境。
模块热替换(HMR)
模块热替换(HMR--hot module replacement):在程序运⾏过程中,若有替换/添加/删除模块,只更新修改的部分,不需要更新整个页⾯。
此功能暂不⽀持⽣产环境。
代码配置如下:
devServer:{
contentBase:'./dist',
hot:true
},
在index页⾯加⼊代码
if(module.hot){
module.hot.accept('./print.js',function(){
console.log('update the module1');
Print()
})
}
注意:执⾏时使⽤npm run start,启动服务,可查看热更替。
*** 以上代码在webpack-demo7中
模块热更替跟热更新是两回事。模块热更新是指修改了某个部分代码,不会刷新页⾯,⽽是在页⾯更新这个模块。热更新是指及时刷新页⾯。
Tree shaking
概念
是指在打包的时候,剔除没有⽤到的代码。
但是只⽀持ES module的import和export⽤法。
实践
打包过程分成3部分:
1. import会被打包成/* harmony import */做前缀,表明这段是import进来的
2. export会被打包成/* harmony export */做前缀,表明这段是export的
3. 纯函数,会被打包成/*#__PURE__*/,表明这个函数是纯函数,可以被tree shaking掉
代码如下:
package.json
"name": "webpack-demo8", "sideEffects":false, fig.js optimization:{
usedExports:true
}
*** 以上代码在webpack-demo8中我的仓库地址,,欢迎star~~(完)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论