一文大白话讲清楚webpack基本使用——7——代码分离和懒加载(动态加载)
1. 建议按文章顺序从头看,一看到底,豁然开朗
- 第一篇:
- 一文大白话讲清楚啥是个webpack
- 第二篇:
- 一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建
- 第三篇
- 一文大白话讲清楚webpack基本使用——2——css相关loader的配置和使用
- 第四篇
- 一文大白话讲清楚webpack基本使用——3——图像相关loader的配置和使用
- 第五篇
- 一文大白话讲清楚webpack基本使用——4——vue-loader的配置和使用
- 第六篇
- #一文大白话讲清楚webpack基本使用——5——babel的配置和使用
- 第七篇
- 一文大白话讲清楚webpack基本使用——6——热更新及其原理
- 然后看本篇,代码分离和懒加载
2. 啥是代码分离
- 我们前几篇文章讲了webpack的基本使用,当我们构建完项目后,会生成一个bundle.js
- 问题是如果我们的模块特别多,最后生成的bundle.js体积就会很大,这样加载速率就会变慢,会影响性能,我们希望能不能不要生成一个bundle.js,而是生成好几个把bundle.js,这样单个bundle.js的体积就会变小进行拆分
- 可以,这就是代码分离技术
- 代码分离就是通过配置,将打包生成的代码文件拆分成多个较小的文件,而不是将所有的代码打包到一个文件中,这样做的好处是可以提高初始加载速度,减小每个页面的加载所需要的数据量
3. 代码分离的方式
3.1 配置多入口
- 既然我们配置了一个入口文件,最后构建打包了一个bundle.js,那很当然想到,我们可以配置多个入口,打包多个bundle.js,这样就实现了代码分离
- 为了演示,我们在src目录下再创建一个secondmain.js和main.js形成对比
- 然后我们在secondmain.js里面写上业务逻辑,我们在secondmain里面除了其他业务逻辑之外,同时也引用add.js,形成依赖,这是为了一会讲入口依赖,不影响现在讲代码分离,只是js业务逻辑而已
import {add} from './modulejs/add'
console.log(add(2,3))
const p=document.createElement('p')
p.textContent=‘I`m another entry secondMain.js`
p.style="font-size:18px;color:green"
document.body.appendChild(p)
- 然后我们在webpack.config.js里面配置多入口,把secondmain.js入口加进去
entry:{//配置入口文件,根据入口文件建立依赖关系
main:'./src/main.js',
secondmain:'./src/secondmain.js'
}
- 然后我们重新构建
npm run build
-
发现构建打包出来两个bundle.js,而且index.html里面注入了两个js
-
我们在浏览器运行一下html,看看secondmain.js是否执行
-
发现完美执行了。到这里看似已经完事了,但是还有个小问题,就是我们刚才在secondmain.js里面引用的add.js,为啥说她有问题,因为我们在main.js里面也引入他了
-
相当于secondmain.js和add.js形成了依赖关系
-
main.js和add.js也形成了依赖关系
-
那么就会导致通过两个入口构建的包里面都会包含一份add.js
-
我们打开构建后的包看一下是不是都有
-
-
果然,两个都有一份add.js<这不是我们想要的,这会浪费构建包的大小,我们希望把add.js单独抽取出来构建一个包,然后单独引用他,这样就不会重复了
-
很好,那就用entry dependencies
-
他的作用就是把多入口中共同的依赖单独打包供其他包引用
-
我们重新配置一下
entry:{//配置入口文件,根据入口文件建立依赖关系
main:{
import:'./src/main.js',
dependOn:'shared',
},
secondmain:{
import:'./src/secondmain.js',
dependOn:'shared'
},
shared:['./src/modulejs/add.js']
},
- 然后我们重新构建
npm run build
- 返现这次打了三个包,只有其中一个有add.js打包产物,然后index.html里面对这个共享保进行了引入
- 搞定
- 这也是为什么有些人把entry Dependencies也单独列出来作为一种代码拆分的方式了
3.2 SplitChunks
-
我们先把多入口注销掉,不注销也行,是为了控制单一变量好讲
-
这个玩意是干啥的呢,别着急我们来观察一下我们的main.js,会发现可以分为两部分,一部分是import进来的依赖包,一部分是我们自己的主体代码
-
SplitChunks就是把我们的依赖包和主题代码拆分开,分开打包,
-
SplitChunks用于代码分割,从而优化打包输出,提高加载效率和重复使用率,内部是通过webpack内置插件SplitChunksPlugin来实现,所以不需要额外安装,直接配置使用即可
optimization:{
splitChunks:{
chunks:'all'//async,默认值,只对异步加载的代码块进行分割;initial,分割同步代码块;all,二者都分割
}
}
- 然后我们重新构建
npm run build
-
发现想必之前的一个包,这会多打出来一个包,这个包就是import的依赖构建出来的包
-
当然,SplitChunks的强大之处不仅在于chunks属性的配置,还有很多牛逼的配置,我们挨个讲一下
3.3 SplitChunks属性详解
3.3.1 Chunks
- 这个上面我们已经讲过了,不再重复
3.3.2 minSize
- 设置生成代码块的最小体积,只有大于这个自己数的代码块才会被有效生成,也就是说如果一个包拆分出来达不到minSize的大小,就不会拆分出来
3.3.3 maxSize
- maxSize,如果代码块的体积大于maxSize,则进一步细分
3.3.4 cacheGroups
- 配置缓存组,可以将多个模块合并到一个文件中去,避免重复加载
3.3.4.1 test
- 缓存组的匹配规则 /[\/]node_modules[\/]/,匹配第三方模块
3.3.4.2 priority
- 缓存租的优先级,数字越大,优先级越高。
3.3.5 minChunks
- 块的最小被引用次数,达到这个次数才会被引用
3.3.6 maxAsyncRequest
- 按需加载时的最大并行请求数
3.3.7 maxInitialRequest
- 入口点处的最大并行请求数
3.3.8 name
- 根据拆分出来的块生成的名称,如果是true,将自动生成
3.3.9 reuseExistingChunk
- ture,如果当前模块包含已经被拆分出去的模块,则复用
3.3.10 default
- 默认的缓存组,用于处理非第三方模块
3.4 动态导入
- 这里要讲一下动态导入导入和懒加载的关系,很多人搞不清
- 先回一下我们说热重载和热更新的关系,热重载是是实现热更新的技术手段
- 这里,动态导入是实现懒加载的技术手段,也就是说,懒加载是一种模式,动态导入时模式背后的技术支持
- 然后再说什么是动态导入,就是需要的时候再去加载,不需要就先不加载
- 比如我们在通过main.js在index.html页面中加一个button,点击这个button,就去加载一个dynamic.js模块,调用模块里面的方法给页面增加p标签,点一次增加一个
- 首先在,modulejs目录下新建dynamic.js,然后写上业务逻辑
function addOnePToBody(){
let p=document.createElement('p')
p.textContent='I`m p created by function from dynamic.js'
document.body.appendChild(p)
}
export {
addOnePToBody
}
- 然后我们在main.js里面通过import动态引入dynamic.js
const btn=document.createElement('button')
btn.textContent='click me to addP by dynamic.js'
document.body.appendChild(btn)
btn.onclick=()=>{
import('./modulejs/dynamic.js').then(res=>{//通过import动态引入返回的是一个promise对象,then方法里面的res就是我们dynamic.js 里面export出来的对象
res.addOnePToBody()
})
}
- 然后我们重新构建
npm run build
-
发现多了一个包,就是我们的dynamic.js构建的包
-
然后我们浏览器运行index.html,看看首次加载的时候,这个js是否被加载
-
发现首次只加载了一个js,dynamic.js动态引用的包并没有被加载,他会在我们点击按钮时才会被加载执行,我们点击一下按钮试一下
-
发现加载了js并且在页面上成功的进行了p标签渲染
-
OK,恭喜你又学会了一项技能
3.5 代码分离和懒加载的区别
- 不用多说了吧,懒加载一定是代码分离,代码分离不一定是懒加载
- 就这么简单