代码分离. 这一章的目的在于重用以及基本的缓存
首先第一部分在于提出公用的,比如都是 loadsh
是公用的部分。
如果正常发布的话,index.js
和 another-module.js
. 都会打包 loadsh
.
index.js
import _ from 'lodash';
console.log(_.join(['index','loaded'], ' '));
another-module.js
import _ from 'lodash';
console.log(_.join(['Another', 'module', 'loaded!'], ' '));
01 代码分离的方法 主动选择分享哪些模块
entry: {
index: {
import: './src/index.js',
dependOn: 'shared',
},
another: {
import: './src/another-module.js',
dependOn: 'shared',
},
shared: 'lodash'
}
shared
关键字可以例举出公共的模块。
在具体的路径中 dependOn
选择 shared
.
就可以选择哪些依赖。shared
也可以是数组。
我想到另一种可能,我有多种 shared
模式有多种可能,于是我测试了一下。
entry: {
index: {
import: './src/index.js',
dependOn: 'shared',
},
another: {
import: './src/another-module.js',
dependOn: ['shared', 'shared1'],
},
shared: 'lodash',
shared1: 'moment'
}
这样也可以。
这样相对来说比较灵活。
只是文档中有一句我实在是不明白
如果我们要在一个 HTML 页面上使用多个入口时,还需设置
optimization.runtimeChunk: 'single'
,否则还会遇到这里所述的麻烦。
我查看了这个链接以后,理解了问题的意思。
就是不同的入口应该是重新实例化对象,来解决文章中文问题。
但是为什么加 optimization.runtimeChunk: 'single'
就能解决,我查了下含义
optimization.runtimeChunk 具体作用是什么?
其实就是解决缓存问题的,虽然我还没有做过实验,所以这里我并没有理解。
02 代码分离的方法 自动分离公共模块
回到最初的入口方式
entry: {
index: './src/index.js',
another: './src/another-module.js',
},
但是有办法能够自动分离,而不用选择
optimization: {
splitChunks: {
chunks: 'all'
}
}
就能自动将公共的模块分离出来,我查了下 splitChunks
SplitChunksPlugin
splitChunks: {
chunks: 'async',
minSize: 20000,
minRemainingSize: 0,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
enforceSizeThreshold: 50000,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
我开始会担心,提取成一个公共 chunk
是否会太大,这些属性证明我想多了。
代码分离这件事,主要还是优化速度。你经常改变的是业务逻辑,公共组件其实很少变,提取出来,最大化利用浏览器缓存。
大概是这样子,具体属性可以等用到了再研究。
03 dynamic import
动态导入这个东西队伍贫乏的 webpack 知识,以前似乎也有类似的方法,能够实现动态加载和拆分模块,使用 jsonp
去动态加载,只是语法似乎和这个不太一样。
说起来也简单,首先我引入 moment
, 然后写个方法动态加载。
dynamic.js
export default async () => {
let { default: m } = await import("moment");
let timeString = m().format('MMMM Do YYYY, h:mm:ss.SSS a');
console.log("-----dynamicImport in test------");
console.log(timeString);
return timeString;
}
然后外部引用后,直接编译。
moment
会有两个,一个语言包一个程序,一般正常是一个。
原理可以看这里 深入了解 webpack 模块加载原理
就是 jsonp
加载。
那么这时候还有另外一种用法,就是写在按钮事件里或者其他延时加载的方法。
dynamicImportBtn.innerHTML = 'dynamic import btn';
dynamicImportBtn.onclick = async () => {
let { default: m } = await import("moment");
let timeString = m().format('MMMM Do YYYY, h:mm:ss.SSS a');
console.log("-----dynamicImport in test------");
console.log(timeString);
}
element.append(dynamicImportBtn);
果然在点击按钮以后,才会加载对应 js
.
04. 预加载
prefetch(预获取):将来某些导航下可能需要的资源
preload(预加载):当前导航下可能需要资源
在代码中的应用就是, 你提前加入这一段注释,告诉 webpack 你需要对这段代码执行什么策略
let { default: m } = await import(/* webpackPreload: true */ "moment");
最后会在html
中生成, 但是需要注意的点是,前提你是通过 webpack 来生成 html
开始我以为这个是 webpck 通过 js 实现的,原来是 html
标准。
可以参考这两篇文章
https://www.webhek.com/post/link-prefetch.html
https://www.cnblogs.com/cangqinglang/p/11308243.html
总结来说就是
preload
并行下载
prefetch
闲时下载
自己估算好使用场景,选择预加载以及预加载的顺序
这里我不过多研究以及测试,后续需要用到之后在进行学习了测试
05. end
这一章主要还是为了教会我们如何使用 webpack 对代码进行分割。
给出了几种方式
- 提取公共代码,将公共代码单独提取,以便减小体积,也充分利用浏览器缓存。
- 拆分代码,不同逻辑的代码进行拆分,达到同样的效果
- 预加载,不管是图片也好,模块也好。预加载达到优化速度的请求
最后文中给出了几种分析包的方式,插件。
后续有机会实验一下。