利用 webpack 按需加载模块

115 阅读2分钟

为什么要按需加载呢?

  • 单页面应用,如果我们不拆分代码、按需加载,会导致首屏加载时间过长,加载多余资源,用户等待时间长,体验差。
  • 那么让当前页面未使用模块不加载,能够改善首屏加载速度

拆分什么代码?

  • 当静态导入的模块很明显的降低了代码的加载速度且被使用的可能性很低,或者并不需要马上使用它。

例如:例如后台管理系统项目

  • 项目中的一些第三方库体积可能非常巨大,像 xlsx.js 、 echarts 、 html2canvas 等。
  • 而当用户在登录页时不需要这些模块,登录页就加载明显费力不讨好

一、import

  • 静态引入
    • import 命令只能用在模块顶层,先于模块内的其他语句执行
    • 语法 import xxx from 'xxx';
  • 动态引入
    • import()函数,支持动态加载模块,是异步加载返回 Promise 对象
    • 语法 import('aa/bb/cc.js').then((c)=>{console.log(c)});

二、webpack + import()

  • 1.需要确保浏览器支持 Promise
  • 2.webpack 内置了对 import('xx') 的支持,使用 import 导入 返回一个 Promise
  • 3.使用了 import('xx') 会生成新的 chunk ,当代码执行到这个语句时才会去加载对应的 chunk 文件
  • 4.import(/* webpackChunkName: "defineName" */ 'xx') 自定义chunk 的名称为 ‘defineName’
  • 5.vue、react 的路由懒加载也是这种方式
  • 示例代码:
  dom.addEventListener("click", e => {
    e.preventDefault();

    import('/modules/my-module.js')
      .then(module => {
        module.loadPageInto(main);
      })
      .catch(err => {
        main.textContent = err.message;
      });
  });

三、Vue 异步加载组件

image.png

四、import() 动态导入不成功

  • 如果使用了 import('xx') 动态导入一个模块,而且这个模块还有其他子模块被静态导入了,则可能会使动态导入失效。
  • 所以动态导入的模块不能再被其他模块静态导入

拆分代码还有什么好处?

  • 合理利用浏览器的缓存
  • 像vue、react、echarts 等,我们一般不会去修改他们的版本号,修改最频繁的是业务代码。也就说,当我们修改了业务代码,vue、react 之类的框架是不需要更新本地缓存的,如果没有拆分代码混杂在一起,文件名的hash值变了,浏览器便会重新获取资源,造成了资源的浪费。