美文网首页
加载优化之Link rel 属性

加载优化之Link rel 属性

作者: 前端早晚自习 | 来源:发表于2024-01-16 20:33 被阅读0次

当我们优化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

相关文章

网友评论

      本文标题:加载优化之Link rel 属性

      本文链接:https://www.haomeiwen.com/subject/apihodtx.html