webpack的代码分离:入口起点、重复、动态/懒加载、预请求/加载

当一个项目包含多个入口时,比如多页面应用,将代码分离成更小的文件,使得我们更灵活得管理它们的加载,合理情况下减少加载的时间。
常用的分离方法有:配置入口起点、防止重复、动态加载、懒加载、预请求和预加载等。

一、入口起点

这是迄今为止最简单直观的分离代码的方式。比较直观,只需要如下配置:

module.exports = {
  entry: {
    index: './src/index.js',
    another: './src/another-module.js',
  },
 };

使用键值对的形式配置多个入口,键是打包后的名,值则是源文件路径。这样做很方便的将多个入口的文件分开,但是也有隐患。例如index这个入口引入了某个大型库big.js,another也引入了big.js,打包的时候会重复打包big.js,生成两个文件,这显然是我们不希望看到的。

二、防止重复

防止重复的效果就是解决上面重复打包共同引入库。方法有两种:
一是配置入口依赖,配置 dependOn option 选项,这样可以在多个 chunk 之间共享模块:

module.exports = {
   entry: {
    index: './src/index.js',
    another: './src/another-module.js',
    index: {
      import: './src/index.js',
      dependOn: 'shared',
    },
    another: {
      import: './src/another-module.js',
      dependOn: 'shared',
    },
    shared: 'lodash',
   },
   output: {
     filename: '[name].bundle.js',
     path: path.resolve(__dirname, 'dist'),
   },
 };

这个配置时表明入口都引用了shared这个依赖,然后指明shared是哪个依赖 这里以lodash为例,webpack在打包的时候就会将这个公共的抽离出来,只打包一次。

方法二:使用内置插件SplitChunksPlugin
SplitChunksPlugin 插件可以将公共的依赖模块提取到已有的入口 chunk 中,或者提取到一个新生成的 chunk。

module.exports = {
    mode: 'development',
    entry: {
      index: './src/index.js',
      another: './src/another-module.js',
    },
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist'),
    },
   optimization: {
     splitChunks: {
       chunks: 'all',
     },
   },
  };

三、动态导入、懒加载

webpack支持动态的导入文件,情景是当代码运行到某一处时会导入需要的文件,而动态导入也会在打包时抽离这个导入的代码,例如下方这个函数执行的时候会导入lodash:

async function getComponent() {
  const element = document.createElement('div');
  const { default: _ } = await import('lodash');      	
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');
  return element;
 }

import执行是个Promise。

懒加载个人认为与动态导入方式差不多,先举个例子:

button.onclick = () => {
	import('lodash')
}

当我点击按钮的时候会去加载lodash,如果我一直不点,就不会去加载,页面也不会发出请求。懒加载与动态加载的区别可能就在于它受主观操作影响。

预请求和预加载

Webpack v4.6.0+ 增加了对预获取和预加载的支持。

在声明 import 时,使用下面这些内置指令,可以让 webpack 输出 “resource hint(资源提示)”,来告知浏览器:

prefetch(预请求):将来某些导航下可能需要的资源
preload(预加载):当前导航下可能需要资源

prefetch的写法:

import(/* webpackPrefetch: true */ './path/to/LoginModal.js');

这个注释成为魔法注释,可以写一些指令。

preload的写法:

import(/* webpackPreload: true */ 'ChartingLibrary');

比较通俗的讲解这两个的作用和区别:
prefetch会在浏览器资源较为充足的时候去请求这个文件,相当于告知浏览器这个依赖我未来可能会用得到,但是不急,等有精力再帮我下载。上面的动态导入和懒加载可能会造成一种现象,就是在首屏加载时没有去加载这些资源会显得比较快,但是当点击按钮时,还得去等待请求一下依赖,交互起来可能会有体验感的影响,所以prefetch在空闲时提前请求这些资源,很大程度上能解决这个问题。

preload则是会在父chunk请求时并发请求,也就是告知浏览器,这个我马上要用到了,加急处理。在一些父chunk比较大时可以使用,比如父chunk很大,请求需要花费不少时间,这时候并发的去请求所需的依赖,而且又比较小时,父chunk下载完毕的时候,所需的依赖也下好了。使用preload需要注意分寸,不然会影响性能,很简单的道理,一个文件和它的依赖同时下载,那跟不分离代码有什么区别呢。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值