使用预取和预加载是网站性能和用户体验提升的一个很好的途径,本文介绍了使用 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. vue-父组件传递参数到子组件

    案例: 父组件 <template> <div id="app"> <h1>vuex</h1> <h3>count:{{ ...

  2. 数据分析_numpy_基础2

    数据分析_numpy_基础2 sqrt 开方 arr = np.arange(10) arr # array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) np.sqrt(arr) ...

  3. Linux和Windows环境下安装Nginx

    Nginx的安装 windows环境下安装Nginx 安装 Nginx 的下载地址如下: http://nginx.org/en/download.html 选择时尽量选择 Stable 稳定版本,点 ...

  4. 【tensorflow2.0】处理图片数据-cifar2分类

    1.准备数据 cifar2数据集为cifar10数据集的子集,只包括前两种类别airplane和automobile. 训练集有airplane和automobile图片各5000张,测试集有airp ...

  5. Django-FileField与ImageField

    1: 在views中用户表添加:class userinfo: avatar = models.FileField(upload_to='avatars/', default="/avata ...

  6. 1+X Web前端开发(中级)理论考试样题(附答案)

    传送门 教育部:职业教育将启动"1+X"证书制度改革 职业教育改革1+X证书制度试点启动 1+X成绩/证书查询入口 一.单选题(每小题2分,共30小题,共 60 分) 1.在Boo ...

  7. 新建jsp文件,The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path错误解决方法

    新建一个jsp文件后,有一个错误,The superclass "javax.servlet.http.HttpServlet" was not found on the Java ...

  8. Base64编码与解码原理

    Base64编码是使用64个可打印ASCII字符(A-Z.a-z.0-9.+./)将任意字节序列数据编码成ASCII字符串,另有“=”符号用作后缀用途. base64索引表 base64编码与解码的基 ...

  9. HTTP Session例子

    HTTP协议是“一次性单向”协议.服务端不能主动连接客户端,只能被动等待并答复客户端请求.客户端连接服务端,发出一个HTTP Request,服务端处理请求,并且返回一个HTTP Response给客 ...

  10. Linux Shell编程,双括号运算符(())

    双括号运算符是shell非常强大的扩展. 这里简要介绍两种使用方式: 1.条件判断 跟在if.while.until,for等需要逻辑条件的命令后,进行逻辑判断 if(( expr));then … ...