打包分析

我们可以使用打包分析工具来查看Webpack打包的过程,Webpack提供了许多分析工具,例如analyse
https://github.com/webpack/analyse

配置命令行参数:

  1. {
  2. // ...
  3. "scripts": {
  4. "dev": "webpack serve --config ./build/webpack.dev.js",
  5. // webpack --profile --json > stats.json
  6. "build:test": "webpack --profile --json > stats.json --config ./build/webpack.dev.js",
  7. "build": "webpack --config ./build/webpack.prod.js"
  8. },
  9. // ...
  10. }

然后就会生成stats.json文件,此时的json文件非常的长而且我们观看会非常的困难,访问analyse 网站且上传生成的stats.json文件就能帮我们自动生成分析报告。

Webpack还提供了其他的打包分析的交互图,详情Webpack中文:
代码分离 | webpack 中文文档

Prefetch/Preload

Webpck中文:
代码分离 | webpack 中文文档

我们在前面学习知道在使用optimization.splitChunks.chunks默认值是async,为什么不是all呢?Webpack期望我们写的代码是什么样子的呢?

  1. // ...
  2. module.exports = {
  3. // ...
  4. optimization: {
  5. usedExports: true,
  6. splitChunks: {
  7. // 分割引入代码库的方式,默认为 async 异步,可选 all:同步和异步
  8. chunks: 'all',
  9. // 引入的代码库最小为20000字节
  10. minSize: 20000,
  11. minRemainingSize: 0,
  12. maxSize: 100000,
  13. // 代码库至少被引入1次
  14. minChunks: 1,
  15. // 同时加载的模块数最大是 30
  16. maxAsyncRequests: 30,
  17. maxInitialRequests: 30,
  18. enforceSizeThreshold: 50000,
  19. cacheGroups: {
  20. defaultVendors: {
  21. // 是否是 node_modules 下的代码库
  22. test: /[\\/]node_modules[\\/]/,
  23. priority: -10,
  24. // 如果一个模块被打包过就不再进行打包
  25. reuseExistingChunk: true,
  26. },
  27. default: {
  28. minChunks: 2,
  29. priority: -20,
  30. reuseExistingChunk: true,
  31. },
  32. },
  33. },
  34. },
  35. // ...
  36. }
  1. document.addEventListener("click", () => {
  2. const element = document.createElement("div");
  3. element.innerHTML = "Hello Word!";
  4. document.body.appendChild(element);
  5. })

这个时候运行打包命令npm run build:test后查看index.html页面就会空白的内容,随后点击就会发现出现了Hello Word。这样看起来没有问题,这样的代码还能进行优化吗,答案是可以的。

异步加载click.js:

  1. document.addEventListener("click", () => {
  2. import("./click.js").then(({ default: func }) => {
  3. func();
  4. })
  5. })
  1. export default function () {
  2. const element = document.createElement("div");
  3. element.innerHTML = "Hello Word!";
  4. document.body.appendChild(element);
  5. }

以上代码我们改写成了异步加载的方式,假如业务代码非常多的时候进行异步加载利用率就提高了很多,同时也会让页面加载时间缩短。

我们来看看慕课网的JS文件加载情况。
command+Shift+P
整体的代码利用率还是非常不错的,但是我们可以看到页面总共加载了 793KB 的代码但实际使用 266KB 的代码,如果能把大部分代码改成异步加载的代码页面的加载会大大的提升,这就是Webpack的配置代码默认为async的原因。
我们在看一个场景:一个网站进入后,我们点击登录会弹窗一个登录的弹窗,实际上这个弹窗是不应该在首页加载的时候就加载进来的,我们可以在点击登录的时候异步加载弹窗,但是这时还有个问题,就是点击的时候进行异步加载弹窗会不会延迟卡顿呢?

prefetch

我们可以使用prefetch进行加载弹窗的代码,prefetch发现首页主要的JS文件全部加载完毕后利用网络闲暇进行加载异步代码。

  1. document.addEventListener("click", () => {
  2. import( /* webpackPrefetch: true */ "./click.js").then(({ default: func }) => {
  3. func();
  4. })
  5. })

preload

prefetch指令相比,preload指令有许多不同之处:

  • preload chunk会在父chunk加载时,以并行方式开始加载;prefetch chunk会在父chunk加载结束后开始加载。
  • preload chunk具有中等优先级,并立即下载;prefetch chunk在浏览器闲置时下载。
  • preload chunk会在父chunk中立即请求,用于当下时刻。prefetch chunk会用于未来的某个时刻。
  • 浏览器支持程度不同。
    1. document.addEventListener("click", () => {
    2. import( /* webpackPreload: true */ "./click.js").then(({ default: func }) => {
    3. func();
    4. })
    5. })

    Tip 不正确地使用webpackPreload会有损性能,请谨慎使用。