Skip to content

懒加载

介绍

有时候,我们页面上并不需要上来就加载很多的文件,而是当用户操作行为的时候才触发那些代码。这个时候我们就可以使用懒加载。

使用

在 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>

MIT License