DNS Prefetching的小实践

in Tutorials with 22 comments

在实践之前,我们先介绍一下“资源预拉取”的性能优化的技术,这是一种通过预拉取可以告诉浏览器用户在未来可能用到哪些资源的技术。

而预取,一共有两部分:一部分是资源的预取;还有一部分是DNS的预解析。

以前这种实践也被称为“prebrowsing”,但这并不是一种单一的技术,实际上可以拆分成很多小点:dns-prefetch, preconnect, prefetch, subresource, prerender等等。

而今天要讲的“DNS prefetching”就是DNS的预解析的一小部分。

它有什么用

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

比如我们需要让example.com的静态资源提前加载域名解析,在<head>就可以这么写:

<link rel="dns-prefetch" href="//example.com">

当请求这个域名下的文件时就不需要等待DNS查询了。

它怎样用

如chromium的官方文档所说,chrome 会自动把当前页面的所有带href的link的dns都prefetch一遍:

Manual Prefetch
Chromium uses the "href" attribute of hyperlinks to find host names to prefetch. However, some of those hyperlinks may be redirects, for example if the site is trying to count how many times the link is clicked. In those situations, the "true" targeted domain is not necessarily discernible by examining the content of a web page, and so Chromium not able to prefetch the final targeted domain.

再根据官方文档发现,a标签的默认启动在HTTPS不起作用:

DNS Prefetch Control

By default, Chromium does not prefetch host names in hyperlinks that appear in HTTPS pages. This restriction helps prevent an eavesdropper from inferring the host names of hyperlinks that appear in HTTPS pages based on DNS prefetch traffic. The one exception is that Chromium may periodically re-resolve the domain of the HTTPS page itself.

<head>就加上下面的一句代码,就可以强制启动:

<meta http-equiv="x-dns-prefetch-control" content="on">

它能带来什么

合理的dns prefetching能对页面性能带来50ms ~ 300ms的提升,有人做了这方面的统计。

再如chromium的官方文档所说,dns prefetching的网络消耗是极低极低的:

Each request typically involves sending a single UDP packet that is under 100 bytes out, and getting back a response that is around 100 bytes. This minimal impact on network usage is compensated by a significant improvement in user experience.

实践

这次实践是在lpisme主题上实现,主要是对header.php文件操作。而DNS prefetching的实践对象就是www.linpx.com用的CDN上的静态资源,当然我博客只是CDN了图片资源和公共JS

打开header.php,在<meta charset="<?php $this->options->charset(); ?>">后面,添加:

<meta http-equiv="x-dns-prefetch-control" content="on">
<link rel="dns-prefetch" href="<?php $this->options->cdn_add(); ?>" />
<link rel="dns-prefetch" href="//cdn.bootcss.com" />

其中<?php $this->options->cdn_add(); ?>是主题设置里的七牛云存储域名

还有,如果你没有开启HTTPS,<meta http-equiv="x-dns-prefetch-control" content="on">这句是可以删掉的

为了更严谨,还需要添加一个条件判断来圈住上面的代码

<?php if ($this->options->cdn_add): ?>
···
<?php endif; ?>

至此lpisme主题完成DNS prefetching的功能的添加。如果嫌麻烦,我已经push到github上了,直接clone或fetch项目即可。

更新

在上面的代码中再添加一句,如下

<link rel="dns-prefetch" href="//secure.gravatar.com" />

参考

国内的

国外的

Responses
  1. 禅猫 禅猫

    之前看到国外一篇文章,新建一个页面把所有需要预加载的link写进去,然后再iframe到引用页,这样就可以在访问我们网站的时候把所有后续可能会被访问到的资源进行预加载,这个效率更高

    Reply
    1. @禅猫

      我了解过,我下一个主题或许就是这种模式~😂 或许~

      Reply
      1. 禅猫 禅猫
        @Chakhsu Lau

        期待,期待,啥时候照顾照顾WordPress的用户啊😙

        Reply
  2. 主题改动的真不错,比之前更漂亮了

    Reply
    1. @Tokin

      谢谢,花了很长时间,重写了很多次····

      Reply
  3. 韩小七 韩小七

    新主题好漂亮

    Reply
    1. @韩小七

      谢谢,目前主题还在修改中,敬请期待 :)

      Reply
      1. 韩小七 韩小七
        @Chakhsu Lau

        非常期待你的新主题,请问新主题会添加 分类 标签功能吗?

        Reply
  4. 感谢分享哈,已经给自己博客加上了,虽然感觉上很难体会到50ms-300ms的提升

    Reply
    1. @泽泽

      这个,反正理论上是有的 :)

      Reply
  5. 很好看的主题,支持

    Reply
    1. @森纯博客

      谢谢 :)

      Reply
  6. 实践出真理

    Reply
    1. @商学院

      是的 :)

      Reply