文章目录
引入
所有新技术的出现都是为了解决现有的问题或者是旧技术没法解决的问题。prefetch和preload也是如此。
现在有两个问题:
- 首先,代码的懒加载固然能是首页加载的速度变快,可是相应的,待到用户与页面交互再加载交互相关代码会使得用户首次交互的体验不佳(长时间没有对操作进行响应)。
- 其次,在
SplitChunksPlugin
的默认配置中,chunks
字段默认是为async
的。也就是说,Webpack官方是希望我们使用异步的方式来进行模块的加载的。
这就导出了一个新的问题,异步加载模块是Webpack官方所希望开发者实现的,而且异步加载也能提升首页加载速度,但是又会导致异步加载的那部分代码逻辑迟迟不能执行,可能导致用户的交互长时间没有响应。
这个时候就需要prefetch
或preload
了。
例子
新创建一个click.js
:
export default () => {
const ele = document.createElement('div');
ele.innerText = 'Meskjei';
document.body.appendChild(ele);
}
然后在index.js
中:
document.addEventListener('click', async (e)=>{
const { default: func } = await import('./click');
func();
});
这其实其实才是Webpack官方希望我们写的代码,这样在首页加载的时候不必加载click.js
。
可以看出,页面在加载的时候仅加载了main.js
而没有加载click.js
。(打包后为0.js
)
而点击页面之后,click.js
便进行了加载。
前面提到过,这样做是可能会让用户的交互长时间没有响应的。原因就是待到交互时才进行模块的加载,可能时间会比较长。由此,我们引入prefetch,即预取。
所谓预取,就是提前获取将来可能会用到的资源。prefetch chunk
会在父chunk
加载完成之后进行加载。
那么该怎么做呢?我们要通过一种称作Magic Comment(魔法注释)的方式,让Webpack输出"resource hint(资源提示)",来告知浏览器。
在这个例子中就是:
然后在index.js
中:
document.addEventListener('click', async (e)=>{
const { default: func } = await import(/* webpackPrefetch: true */'./click');
func();
});
这样写完之后,重新打包刷新页面,可以看到在index.js
加载完成之后,浏览器又会去自动加载click.js(0.js)
。
实际上这样做,Webpack替我们在head
内添加了这样一行:
<link rel="prefetch" as="script" href="0.js">
preload和prefetch在用法上相差不大,效果上的差别如下(引自官方文档):
- preload chunk 会在父 chunk 加载时,以并行方式开始加载。prefetch chunk 会在父 chunk 加载结束后开始加载。
- preload chunk 具有中等优先级,并立即下载。prefetch chunk 在浏览器闲置时下载。
- preload chunk 会在父 chunk 中立即请求,用于当下时刻。prefetch chunk 会用于未来的某个时刻。
- 浏览器支持程度不同。