HTTP协议日记 #1期:html标签属性实现页面性能优化

prefetch 🔗︎

空闲时间加载。对当前页面性能影响较小,适用于提前获取下一页面的资源,进入浏览器缓存。

注意点: 默认不带cookie, credentials属性会让请求带上cookie

<link rel='prefetch' href='...' as='script' credentials='include'>

甚至可以动态设置缓存时间。

app.get('next-page', (req, res) => {
  const header = req.headers['purpose'] || req.headers['sec-purpose']
  if(header === 'prefetch') {
    res.set('Cache-Control', 'max-age=10')
  }
  res.send('next page content')
})

也可以用Service Worker控制。

preload 🔗︎

立即加载关键资源,无需等待DOM树解析。当某个资源(如字体、CSS、JS、图像等)是页面加载的关键部分,但无法通过正常的加载顺序立即获得时,使用 preload 让浏览器优先加载这些资源。

注意点:资源加载是同步的

<link rel="preload" href="styles.css" as="style">

preconnect 🔗︎

提前建立到外部资源服务器的网络连接,包括 DNS 解析、TCP 握手和 TLS 协商。如果仅仅想要提前解析,可以 用dns-preconnect

适合用于需要访问第三方资源的场景,比如字体库、CDN 资源等。 只预先建立网络连接,并不实际下载资源。减少了请求外部资源时的延迟。

设置可以在服务端动态设置

app.get('/', (req, res) => {

  res.set('Link', [
    '<https://example.com>; rel=preconnect',
    '<https://fonts.googleapis.com>; rel=preconnect'
  ])

  res.flushHeaders(); // 立即发送

  const rs = fs.createReadStream('content')
  rs.pipe(res)
})

启发 🔗︎

ssr时可先返回静态部分,包含以上的一些资源。然后再处理耗时的核心html生成。 如果服务器响应较慢,浏览器仍然需要等到响应完成才会执行加载。这个时候可以用Early Hints 103。


http.createServer((req,res) => {
  res.writeHead(200, {
    'Content-Type': 'text/html',
    'Transfer-Encoding': 'chunked'
  })


  // 先返回静态部分
  setTimeout(async  () => {
    const firstScreenData = await getFirstData()
    res.write(`<link rel='preload' href='${firstScreenData.src}' as='image'> `)
  },1000)

  // 再返回复杂计算部分
  // todo
})

Early Hints 103 🔗︎

适用于服务器响应时间较长、想要最大程度优化用户感知加载速度的场景。


app.get('/', (req, res) => {
  res.status(103).set({
    Link: [
      '</styles/main.css>; rel=preload; as=style',
      '</images/a.jpg>; rel=preload; as=image'
    ].join(',')
  })
  .end()

  //  再返回真实的内容
  const rs = fs.createReadStream('content')
  res.set('Content-Type', 'text/html')
  rs.pipe(res)
})

当发布很酷的东西时,请第一时间通知我

订阅电子邮件,以获得我的最新文章。我不会向您发送垃圾邮件。随时取消订阅。