HTML <link> 资源预加载

tao
发布于2021-09-22 | 更新于2022-03-10

<link> 外部资源链接元素

HTML 外部资源链接元素(<link>)规定了当前文档与外部资源的关系。该元素常用于链接样式表,此外也可以被用来创建站点图标(比如 PC 端的 favicon 图标和移动设备用以显示在主屏幕的图标)

<link rel="stylesheet" href="/path/to/style.css">
<link rel="icon" href="favicon.ico">
<link rel="apple-touch-icon-precomposed" sizes="114*114" href="apple-icon-114.png" type="image/png">

preload

通过<link>标签的rel属性设置为preload向浏览器声明一个需要提前加载的资源。加载完成后不会立即执行,在需要执行的时候再执行,将加载和执行分离开。

<link rel="preload" as="style" href="/path/to/style.css">
<link rel="preload" as="script" href="/path/to/script.js">

在页面加载的早期就开始获取隐藏在 CSS 或者 JS 中的资源(图片、字体、样式、视频等),更不容易阻塞页面的初步渲染,进而提升性能。

preload将提升资源加载的优先级,不管资源是否使用都将提前加载。因此要避免滥用preload,若不确定资源是必定会加载的,则不要错误使用preload,给页面带来沉重的负担。

对跨域的文件进行预加载时,要给<link>加上crossorigin属性,若不指定crossorigin属性,则会采用匿名模式的 CORS 去加载。预加载请求缺少Origin请求头字段,在之后对该资源的请求中则无法命中,造成两次重复的请求。

<link rel="preload" as="font" crossorigin href="https://www.baidu.com/path/to/font.woff">

prefetch

通过将<link>标签的rel属性设置为prefetch向浏览器声明一个可能需要加载的资源,它会将下载资源的优先级降到最低,浏览器会在闲时去加载对应的资源,并将其存储在缓存中。当用户访问时可以快速的从浏览器缓存中得到,与preload不同的是,它会额外发起一次请求。

截屏2022-03-10 下午12.26.19.png

同时使用preloadprefetch会导致两次重复的请求。

实例:

<html>
<head>
  <title>test</title>
  <link rel="prefetch" as="font" href="http://at.alicdn.com/t/webfont_q7lddel88i.woff2">
  <link rel="prefetch" as="style" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> 
  <link rel="prefetch" as="script" href="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js">
  <link rel="prefetch" as="image" href="https://www.runoob.com/try/demo_source/smiley-2.gif">
  <link rel="prefetch" as="audio" href="https://www.runoob.com/try/demo_source/horse.mp3">
  <style>
    @font-face {
      font-family: 'webfont';
      src: url('http://at.alicdn.com/t/webfont_q7lddel88i.woff2') format('woff2');
    }

    .font {
      font-family: 'webfont';
    }
  </style>
</head> 

<body>
  <div>test</div>
</body>

<script>
  setTimeout(() => {
    const dom = document.createElement('link')
    dom.setAttribute('rel', 'stylesheet')
    dom.setAttribute('href', 'https://unpkg.com/element-ui/lib/theme-chalk/index.css')
    document.head.append(dom)

    const dom1 = document.createElement('div')
    dom1.innerHTML = 'abc'
    dom1.setAttribute('class', 'font')
    document.body.append(dom1)

    const dom2 = document.createElement('script')
    dom2.setAttribute('src', 'https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js')
    document.head.append(dom2)

    const dom3 = document.createElement('img')
    dom3.setAttribute('src', 'https://www.runoob.com/try/demo_source/smiley-2.gif')
    document.body.append(dom3)

    const dom4 = document.createElement('audio')
    dom4.setAttribute('src', 'https://www.runoob.com/try/demo_source/horse.mp3')
    document.body.append(dom4)
  }, 5000)
</script>
</html>

加载设置了 prefetch 的 link 标签上的字体文件时,chrome 浏览器向服务器请求了两次,没有使用缓存中的字体文件:

截屏2022-03-10 下午12.30.09.png

刷新页面后加载字体文件变成 disk cache 中加载之后才使用了 prefetch cache:

截屏2022-03-10 下午12.31.29.png

但是设置了 preload 的 link 标签没有这种情况。


参考文章:
1.用 preload 预加载页面资源