使用预取和预加载是网站性能和用户体验提升的一个很好的途径,本文介绍了使用 prefetch 和 prefetch 进行预取和预加载的方法,并使用 webpack 进行实现

Link 的链接类型

<link> 标签的 rel 属性可以定义链接类型,prefetch 是其中的一种,与 href 配合使用可以预取或预加载对应资源

<link rel="prefetch" herf="URL">

preload 是另外一种类型,同样用 href 定义资源地址,但其处理预取外,还会对资源进行解析,所以还要增加属性 as,说明资源的类型

<link rel="preload" href="URL" as="MIME_TYPE">

预取资源

prefetch 表示用户在接下来的浏览中(例如在下一个页面),有可能用到对应资源,提示浏览器要在闲时获取对应资源

先新建文件夹 prefetch-preload-demo(本文所有代码将在此创建),安装相关依赖,并新建文件夹 static

mkdir prefetch-preload-demo

cd prefetch-preload-demo

npm init -y

npm i -D http-server

mkdir static

在 static 中创建 prefetch.htmlmain.jsscript.js

prefetch.html 定义了一个 relprefetch 的链接

<html>
<head>
<title>Prefetch</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="prefetch" href="script.js">
</head>
<body>
<script src="main.js"></script>
</body>
</html>

main.js 创建了一个按钮,并绑定了点击事件

let button = document.createElement('button');
button.innerHTML = 'Add Script';
button.addEventListener('click', e => {
let script = document.createElement("script");
script.src = "script.js";
document.head.appendChild(script);
});
document.body.appendChild(button);

script.js 只是简单的打印了一下

console.log('script run');

运行服务器(也可在 package.json 中增加 server 脚本)

npx http-server

访问 http://localhost:8080 并导航至 static 中,点击 prefetch.html,或者直接访问线上页面,初始状态下,查看控制台的网络选项卡下的内容如下(不要勾选 Disable Cache,点击右侧齿轮,勾选 Use large request rows

  • script.js 被 fetch 下来,size 列的两个数字,275 B 表示下载的字节大小,0 B 表示解析的字节大小(即目前并没有解析)
  • 控制台是空的,即脚本没有运行

点击页面上的 Add Script,会在页面增加地址为 script.js<script> 标签,此时网络选项卡会增加以下内容

  • 下载字节量为 (prefetch cache) ,即直接从预取缓存获取资源,下面的解析后的字节不再为 0
  • 控制台打印出脚本中的调试内容,即这时脚本才被解析并运行

预加载资源

preload 表示用户在当前的浏览中(往往是在当前页面),极有可以可能用到对应资源,提示浏览器要优先获取对应资源

将 prefetch.html 的 link 标签的 prefetch 改为 preload,并增加资源类型 asscript,即得 preload.html

<link rel="preload" href="script.js" as="script">

访问本地服务器对应的 prefetch.html,或者直接访问线上页面,初始状态下,查看控制台的网络选项卡下的内容如下

  • script.js 被优先下载, size 列的解压字节不再为 0,即 preload 除了把脚本下载了下来,还进行了解析
  • 控制台目前仍为空,即脚本虽然被解析,但并没有运行

点击 Add Script,网络选项卡并没有增加任何记录,但是控制台输出了脚本的打印内容

  • 因为脚本已经解析完成,所以连从缓存获取都不需要了,直接运行即可
  • 如果没有在 3 秒内点击 Add Script,控制台会进行警告,因为没有及时使用应该优先加载的资源

The resource https://chanvinxiao.com/demo/html/script.js was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate as value and it is preloaded intentionally.

webpack 的相关处理

运行以下命令安装相关依赖,并新建文件夹 src

npm i -D webpack webpack-cli html-webpack-plugin preload-webpack-plugin@3.0.0-beta.4

mkdir src

  • PreloadWebpackPlugin 的当前版本 2.x 与 webpack 当前版本 4.x 不兼容,所以需要指定版本号为最新的 3.x beta

main.jsscript.js 复制到 src 中,并将 main.js 的点击事件处理更新为

button.addEventListener('click', e => {
import(/* webpackChunkName: "script" */ './script.js');
});
  • import() 为动态加载脚本,webpack 会生成类似以上动态创建 script 标签的代码
  • import 里的注释为特殊含义的魔法注释,如果不设置 webpackChunkName,加载的脚本将被按数字次序命名

增加 webpack.config.js 如下

const HtmlWebpackPlugin = require('html-webpack-plugin');
const PreloadWebpackPlugin = require('preload-webpack-plugin'); module.exports = {
entry: './src/main.js',
plugins: [
new HtmlWebpackPlugin({
filename: 'preload.html'
}),
new PreloadWebpackPlugin()
]
}
  • HtmlWebpackPlugin 将自动生成相应的 html 文件,默认为 index.html,这里通过设置 filename 选项更改
  • PreloadWebpackPlugin 为 HtmlWebpackPlugin 的插件,默认为其动态加载资源增加链接类型为 preloadlink 标签,其 as 的值可根据后缀自动判断

PreloadWebpackPlugin 也支持 prefetch,需要增加 rel 选项为 prefetch

    new HtmlWebpackPlugin({
filename: 'prefetch.html'
}),
new PreloadWebpackPlugin({
rel: 'prefetch'
})

不过要同时生成 preload.html 和 prefetch.html,需要在对应的 PreloadWebpackPlugin 中设置 excludeHtmlNames 排除对方,否则会同时产生 preload 和 prefetch 的 link 标签

    new HtmlWebpackPlugin({
filename: 'preload.html'
}),
new HtmlWebpackPlugin({
filename: 'prefetch.html'
}),
new PreloadWebpackPlugin({
excludeHtmlNames: ['prefetch.html']
}),
new PreloadWebpackPlugin({
rel: 'prefetch',
excludeHtmlNames: ['preload.html']
})

构建文件(也可在 package.json 中增加 build 脚本)

npx webpack

dist 文件夹中将生成 prefetch.html 和 preload.html,访问本地服务器对应地址,即可得到与以上静态页面同样的效果

总结

此文使用静态页面和 webpack 打包两种方式演示了预取和预加载的实现,完整代码见 GitHub,主要技术点如下:

  • ELEMENT.appendChild 动态创建脚本
  • import() 动态加载脚本并设置魔法注释
  • html-webpack-plugin 及其插件的配置

prefetch 和 preload 及 webpack 的相关处理的更多相关文章

  1. prefetch vs preload vs prerender vs preconnect All In One

    prefetch vs preload vs prerender vs preconnect All In One 前端性能优化 prefetch 预获取 https://developer.mozi ...

  2. Webpack 4教程 - 第八部分 使用prefetch和preload进行动态加载

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者.原文出处:https://wanago.io/2018/08/13/webpack-4-course-part ...

  3. webpack优化相关操作

    1.缩小文件搜索的范围 • 优化loader配置 尽量精确使用 include 只命中需要的文件.    module.exports = {      module: {        rules: ...

  4. webpack 配置文件相关解说

    博客地址:https://ainyi.com/10 webpack - 什么是webpack: WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它 ...

  5. prefetch和preload

    前面的话 基于VUE的前端小站改造成SSR服务器端渲染后,HTML文档会自动使用preload和prefetch来预加载所需资源,本文将详细介绍preload和prefetch的使用 资源优先级 在介 ...

  6. webpack配置相关的页面异常

    原文:https://www.cnblogs.com/Hsong/p/9023341.html 前言 在团队协作开发中,为了统一代码风格,避免一些低级错误,应该设有团队成员统一遵守的编码规范.很多语言 ...

  7. 如何配置 webpack 支持 preload, prefetch, dns-prefetch

    如何配置 webpack 支持 preload, prefetch, dns-prefetch webpack , preload, prefetch https://webpack.js.org/p ...

  8. Preload,Prefetch 和它们在 Chrome 之中的优先级

    前言 上周五到的时候,想起之前在手游平台上有处理dns-prefetch的优化,那这篇分享的就更仔细了.今日早读文章由@gy134340翻译并授权分享. 正文从这开始- 今天我们来深入研究一下 Chr ...

  9. Web 性能优化:Preload与Prefetch的使用及在 Chrome 中的优先级

    摘要: 理解Preload与Prefetch. 原文:Web 性能优化:Preload,Prefetch的使用及在 Chrome 中的优先级 作者:前端小智 Fundebug经授权转载,版权归原作者所 ...

随机推荐

  1. 搬运工 Logstash

    1,Logstash 简介 Logstash是一个开源数据收集引擎,具有实时管道功能.Logstash可以动态地将来自不同数据源的数据统一起来,并将数据标准化到你所选择的目的地. 通俗的说,就是搬运工 ...

  2. 模块 heapq_堆排序

    _heapq_堆排序 该模块提供了堆排序算法的实现.堆是二叉树,最大堆中父节点大于或等于两个子节点,最小堆父节点小于或等于两个子节点. 创建堆 heapq有两种方式创建堆, 一种是使用一个空列表,然后 ...

  3. LeetCode(42.接雨水)多解法详解

    接雨水解法详解: 题目: 基本思路:从图上可以看出要想接住雨水,必须是凹字形的,也就是当前位置的左右两边必须存在高度大于它的地方,所以我们要想知道当前位置最多能存储多少水,只需找到左边最高处max_l ...

  4. Python input和print函数

    一.input函数 可以看出,input()函数默认输入的是字符串类型,需要eval()函数将其进行转换. 区别直接赋值的情况,Python可以自动识别数据类型 二.print函数 1.直接输出 无论 ...

  5. dp例题01. 任务价值最大化

    题目Description: 大凯有n项任务可选择去做, 分别对应有开始时间, 结束时间以及任务报酬, 同一时间内最多做一件任务, 现在大凯想知道最多能得到多少报酬, 于是把求解任务交给了你. 输入: ...

  6. Http协议中Cookie使用详细介绍

    Cookie总是保存在客户端中,按在客户端中的存储位置,可分为内存Cookie和硬盘Cookie.内存Cookie由浏览器维护,保存在内存中,浏览器关闭后就消失了,其存在时间是短暂的.硬盘Cookie ...

  7. 混合app禁止切换输入法英文键盘方案

    前言 在此介绍的是h5的部分,非原生,原生可以直接属性禁止. 需求 禁止中文出现在input中.(如果你认为不显示出来中文,那么请往下看) 效果:只显示英文键盘. 遇到的问题 1.在三星低版本上会出现 ...

  8. Scrapy-02-item管道、shell、选择器

    Scrapy-02 item管道: scrapy提供了item对象来对爬取的数据进行保存,它的使用方法和字典类似,不过,相比字典,item多了额外的保护机制,可以避免拼写错误和定义字段错误. 创建的i ...

  9. Java中String转int型的方法以及错误处理

    应要求,本周制作了一个判断一个年份是否是闰年的程序.逻辑很简单,这里就不贴代码了.可是,在这次程序编写中发现了一个问题. 在输入年份时,如果输入1)字母2)空3)超过Int上限时,就会抛excepti ...

  10. P4015 运输问题【zkw费用流】

    输入输出样例 输入 #1复制 2 3 220 280 170 120 210 77 39 105 150 186 122 输出 #1复制 48500 69140zuixiaofeiyo 说明/提示 1 ...