懒加载
介绍
有时候,我们页面上并不需要上来就加载很多的文件,而是当用户操作行为的时候才触发那些代码。这个时候我们就可以使用懒加载。
使用
在 webpack 中,我们可以使用import()
来进行文件的懒加载。 这样该模块就属于异步 chunk 了,webpack 在打包的时候会多打包出来一个该模块的文件。 而浏览器最初加载时候,在源代码只会加载 main.js,当用户点击操作之后,会以 jsonP 的形式发送一个请求,请求该模块,之后浏览器会将该模块缓存起来。
index.js
js
// import _ from "lodash-es";
const btn = document.querySelector("button");
btn.addEventListener("click", async () => {
/* import() 是ES的一个草案,但是webpack支持import()动态的导入
* import()返回一个promise,可以配合async 和 await
但是这样做是会失去tree-shaking的,因为是动态导入,webpack打包的时候分析不出来是具体使用哪个模块
*/
const { chunk } = await import("lodash-es");
const res = chunk([1, 2, 3, 4, 5, 6, 7, 8], 3);
console.log(res);
});
懒加载配合 tree-shaking
使用 import()懒加载的时候就失去了 tree-shaking,webpack 只会分析静态写好的那些导入。 我们可以转一个弯,当 webpack 打包这个模块的时候,我们指定引入这个 chunk,这样 webpack 就知道我们需要使用哪个函数,其他的全部 tree-shaking 掉。
试着把上述代码修改:
js
/_ 只能是在异步 chunk 加载的时候进行分析,这里就需要转一个弯 _/;
const { chunk } = await import("./utils.js");
const res = chunk([1, 2, 3, 4, 5, 6, 7, 8], 3);
最佳实践
js
// import _ from "lodash-es";
const btn = document.querySelector("button");
btn.addEventListener("click", async () => {
/* import() 是ES的一个草案,但是webpack支持import()动态的导入
* import()返回一个promise,可以配合async 和 await
但是这样做是会失去tree-shaking的,因为是动态导入,webpack打包的时候分析不出来
*/
// const { chunk } = await import("lodash-es");
// const res = chunk([1, 2, 3, 4, 5, 6, 7, 8], 3);
/* 只能是在异步chunk加载的时候进行分析,这里就需要转一个弯 */
const { chunk } = await import("./utils.js");
const res = chunk([1, 2, 3, 4, 5, 6, 7, 8], 3);
console.log(res);
});
js
export { chunk } from "lodash-es";
/*
这里在加载chunk的时候,webpack就知道这里只用到了chunk函数,其它的全部tree-shaking了
*/
js
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
mode: "production",
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
new CleanWebpackPlugin(),
],
};
json
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"clean-webpack-plugin": "^3.0.0",
"html-webpack-plugin": "^3.2.0",
"lodash-es": "^4.17.15",
"webpack": "^4.41.6",
"webpack-cli": "^3.3.11"
}
}
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button>点击</button>
<script type="text/javascript" src="main.js"></script>
</body>
</html>