加载优化之Link rel 属性

当我们优化web 应用时,项目加载速度很慢,引用了很多大图片,和外部的js 和 图片等。在尝试切片,按需引入,懒加载等等手段之后可以试下link 的rel 属性它们带来的好处包括允许前端开发人员来控制资源的加载,减少往返路径并且在浏览页面时可以更快的加载到资源等等。

preload

指定页面很快就需要的资源,这些资源是你希望在页面生命周期的早期就开始加载的,早于浏览器的主要渲染机制启动。这可以确保它们更早可用,并且不太可能阻塞页面的渲染,从而提高性能。尽管名称中包含“load”一词,但它并不加载和执行脚本,而只是安排脚本以更高的优先级进行下载和缓存。

可以提高资源优先级, 预加载资源和缓存, 在用到的时候从缓存取

preload 还有其他优点。使用 as 来指定要预加载的内容类型允许浏览器:

  • 更准确地优先加载资源。
  • 将资源存储在缓存中以备将来使用,在适当的情况下复用资源。
  • 对资源应用正确的内容安全策略
  • 为其设置正确的 Accept 请求标头。

示例代码 jquery 正常加载, main.js 采用preload , preload 提升资源加载顺序, 适用于 提前加载当前页面比较重要的资源

 <head>
    <meta charset="utf-8">
  
    <script  src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.js"></script>

    <link rel="preload" as="script" href="https://mdn.github.io/html-examples/link-rel-preload/js-and-css/main.js">
    
  </head>
image.png

prefetch

<link rel="prefetch"> 在浏览器中支持已久,但它是用于预取将在下一次导航/页面加载时使用的资源(例如,当你跳转到下一页时)。这是可以的,但对于当前页面没有用!此外,浏览器会给预取(prefetch)的资源比预加载(preload)的资源更低的优先级——当前页面比下一页更重要

通过图片可以看出,prefetch 不会提升资源的优先级 是在浏览器空闲的时候加载, 不需要指定 as 属性等, 适用于加载下一个页面资源,类似与requestIdleCallback ?

prefetch 的资源在网络堆栈中至少缓存 5 分钟,无论它是不是可以缓存的。

<!DOCTYPE html>
<html lang="">
  <head>

    <link rel="prefetch" href="https://mdn.github.io/html-examples/link-rel-preload/js-and-css/main.js">
    
  </head>
  <body>
    <div id="app"></div>
    <script defer src="https://mdn.github.io/html-examples/link-rel-preload/js-and-css/main.js"></script>
    <!-- built files will be auto injected -->
  </body>
</html>

image.png

dns-prefetch

DNS prefetching通过指定具体的URL来告知客户端未来会用到相关的资源,这样浏览器可以尽早的解析DNS。

为什么要使用 dns-prefetch?

当浏览器从(第三方)服务器请求资源时,必须先将该跨源域名解析为 IP 地址,然后浏览器才能发出请求。此过程称为 DNS 解析。虽然 DNS 缓存可以帮助减少此延迟,但 DNS 解析可能会给请求增加明显的延迟。对于打开了与许多第三方的连接的网站,此延迟可能会大大降低加载性能。

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link rel="dns-prefetch" href="https://fonts.googleapis.com/" />
    <!-- 其他 head 元素 -->
  </head>
  <body>
    <!-- 你的页面内容 -->
  </body>
</html>

preconnect

dns-prefetch 只执行 DNS 查询,而 preconnect 则是建立与服务器的连接。这个过程包括 DNS 解析,以及建立 TCP 连接,如果是 HTTPS 网站,就进一步执行 TLS 握手。将这两者结合起来,可以进一步减少跨源请求的感知延迟。你可以像这样安全地将它们结合起来使用:

<link rel="preconnect" href="https://fonts.googleapis.com/" crossorigin />
<link rel="dns-prefetch" href="https://fonts.googleapis.com/" />

prerender

  • <link rel="prerender"> 在后台渲染指定的网页,如果用户导航到该页面,可以加速其加载。由于有可能浪费用户的带宽,Chrome 将 prerender 视为 NoState 预取

脚本和预加载

当你想要预加载一个脚本,但需要将执行推迟到确切需要它的时候,这很有用

// 动态预加载
function loadScript(url,type='preload',as="script"){
    var link = document.createElement("link");
    link.href = url
    link.rel = type;
    link.as = as;
    document.head.appendChild(link);
}

// 执行
function execScript(url){
    var script = document.createElement("script");
    script.src = url;
    document.body.appendChild(script);
}

// 加载这个js,但不执行
loadScript("myscript.js")
// 某个时机执行
setTimeout(function(){
    execScript("myscript.js")
},1000)

Preload 和 Prefetch 的具体实践

Webpack插件之preload-webpack-plugin
大部分项目中都是通过打包工具将资源引入到html 中的, 而且将资源路径硬编码在了页面中(实际上,ticket_bg.a5bb7c33.png后缀中的hash是构建过程自动生成的,所以硬编码的方式很多场景下本身就行不通)。webpack插件preload-webpack-plugin可以帮助我们将该过程自动化,结合htmlWebpackPlugin在构建过程中插入link标签。


plugins: [
  new HtmlWebpackPlugin(),
  new PreloadWebpackPlugin({
    rel: 'preload',
    as(entry) {
      if (/.css$/.test(entry)) return 'style';
      if (/.woff$/.test(entry)) return 'font';
      if (/.png$/.test(entry)) return 'image';
      return 'script';
    }
  })
]

参考资料:

使用 Preload&Prefetch 优化前端页面的资源加载
preload
prefetch
requestIdleCallback

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容