web前端资源文件的部署和优化

12,710

现在网上也有很多关于前端文件加载的性能优化,我相信大部分的前端程序猿,应该都听说过雅虎的14条优化原则

1. 尽可能的减少 HTTP 的请求数    content
2. 使用 CDN(Content Delivery Network)    server
3. 添加 Expires 头(或者 Cache-control )    server
4. Gzip 组件    server
5. 将 CSS 样式放在页面的上方    css
6. 将脚本移动到底部(包括内联的)    javascript
7. 避免使用 CSS 中的 Expressions    css
8. 将 JavaScript 和 CSS 独立成外部文件    javascript css
9. 减少 DNS 查询    content
10. 压缩 JavaScript 和 CSS (包括内联的)    javascript css
11. 避免重定向    server
12. 移除重复的脚本    javascript
13. 配置实体标签(ETags)    css
14. 使 AJAX 缓存

有些人通过这14个规则总结了一下:

优化方向 优化手段
请求数量 合并脚本和样式表,CSS Sprites,拆分初始化负载,划分主域,字体图标,雪碧图片等
请求带宽 开启服务器GZip,精简JavaScript,移除重复脚本,图像优化(包括图片大小kb)
缓存利用 使用CDN,使用外部JavaScript和CSS,添加Expires头,减少DNS查找,配置ETag,使AjaX可缓存
页面结构 将样式表放在顶部,将脚本放在底部,尽早刷新文档的输出
代码校验 避免CSS表达式,避免重定向

前端资源的优化

今个主要说一下资源部署和优化的一些方案,也借鉴了好多人的理解和图来说一下

1、资源的预加载(prebrowsing)

预加载是浏览器对将来可能被使用资源的一种暗示,一些资源可以在当前页面使用到,一些可能在将来的某些页面中被使用。作为开发人员,我们比浏览器更加了解我们的应用,所以我们可以对我们的核心资源使用该技术。

我们可以使用该技术来预先告知浏览器某些资源可能在未来会被使用。

  • DNS 预解析dns-prefetch

    Head头部里面加入:
    <link rel="dns-prefetch"href="//example.com">
    # 请求这个域名下的文件时就不需要等待DNS查询了,也就是说在浏览器请求资源时,DNS查询就已经准备好了
    # 该技术对使用第三方资源特别有用,比如jquery等
  • 预连接 Preconnect

    # 与 DNS 预解析类似,preconnect 不仅完成 DNS 预解析,同时还将进行 TCP 握手和建立传输层协议
    <link rel="preconnect" href="http://example.com">

    现代浏览器都试着预测网站将来需要哪些连接,然后预先建立 socket 连接,从而消除昂贵的 DNS 查找、TCP 握手和 TLS 往返开销。然而,浏览器还不够聪明,并不能准确预测每个网站的所有预链接目标。好在,在 Firefox 39+ 和 Chrome 46+ 中我们可以使用 preconnect 告诉浏览器我们需要进行哪些预连接。

  • 预获取 Prefetching

    # 顾名思义,提前加载资源(未用到),首先要确定这个资源一定会在未来用到,然后提前加载,放入浏览器缓存中
    <link rel="prefetch" href="image.png">

    prefetch很适用于优化webfonts的性能,但预获取还依赖于一些条件,某些预获取可能会被浏览器忽略,例如从一个非常缓慢的网络中获取一个庞大的字体文件。并且,Firefox 只会在浏览器闲置时进行资源预获取。

  • 优先级Subresource

    这个也是预获取方式,只是不同的是,指定的预获取资源具有最高的优先级,在所有 prefetch 项之前进行
    <link rel="subresource" href="styles.css">
  • 预渲染 Prerender

    # Prerender 预先加载的资源文件,也就是说可以让浏览器提前加载指定页面的所有资源
    <link rel="prerender" href="http://example.com/index.html">
  • 未来 Preload

    # Preload 建议允许始终预加载某些资源,不像prefetch有可能被浏览器忽略,浏览器必须请求preload标记的资源
    <link rel="preload" href="http://example.com/image.png">
    # 存在兼容性
    以上是预加载的基本解释,详细查看详解文章

2、利用304本地缓存资源文件

我们大家都知道,正常的网络请求的返回状态是200,如果我们每次访问页面之后,都要去加载,这样就会浪费带宽,影响页面的性能,那么我们现在就需要304来让浏览器使用本地缓存

HTTP 304

  • 用户首次请求该文件的时候,通过HTTP HEAD的Last-Modified字段将该文件的最后修改日期发送到客户端,让客户端知道该文件的版本
  • 浏览器再次请求该文件的时候,会自动将该时间作为请求的HTTP HEAD的If-Modified-Since字段内容
  • 服务端根据If-Modified-Since字段的内容(如果存在该字段)来判断客户端的文件是否已经过期,如果已经过期,则重新返回新的文件,如果没有,则只需要返回304状态码,不需要返回文件内容。文件是否过期可以从Cache-Control设置max-age值,那么在此值内的时间里就不会重新访问服务器
  • 对于静态文件,例如:CSS、图片,服务器会自动完成 Last Modified 和 If Modified Since 的比较,完成缓存或者更新
  • 对于动态页面,就是动态产生的页面,往往没有包含 Last Modified 信息,这样浏览器、网关等都不会做缓存,也就是在每次请求的时候都完成一个 200 的请求。因此,对于动态页面做缓存加速,首先要在 Response 的 HTTP Header 中增加 Last Modified 定义,其次根据 Request 中的 If Modified Since 和被请求内容的更新时间来返回 200 或者 304 。虽然在返回 304 的时候已经做了一次数据库查询,但是可以避免接下来更多的数据库查询,并且没有返回页面内容而只是一个 HTTP Header,从而大大的降低带宽的消耗,对于用户的感觉也是提高。

如果想清除缓存文件,可以按CTRL-F5 (有时称之为“强刷-hard refresh”),这时候会发现浏览器省略了If-Modified-Since和If-None-Match请求头,也就是无条件的请求页面中的每个资源.

如果服务器资源更新了,前端还在使用缓存文件,如果想让页面更新缓存文件怎么办?不可能让用户自己去清除自己的缓存吧?

下面我们来说一种缓存更新的文件

3、版本号更新资源文件

<link href="./static/css/main.css?v=1.0.0" rel="stylesheet">
或
<link href="./static/css/main.css?time=1245639" rel="stylesheet">

如果我们更新了main.css文件,那么只需要更改v=后面的版本号即可重新加载main.css资源文件,其实也可以用hash值来表示

<link href="./static/css/main_88f0972.css" rel="stylesheet">

还有一种情况就是,如果我有n个文件,但是我只更新了其中一个文件,这个时候我不想其他的文件更新的话,那么我们就需要做到一点,只改变我要更新的文件的版本号或者其他的值即可更新此资源文件

4、CDN静态资源部署

也就是说,把静态资源文件和动态网页分集群部署,静态资源会被部署到CDN节点上,网页中引用的资源也会变成对应的部署路径

原理:不同地区的用户会访问到离自己最近的相同网络线路上的CDN节点,当请求达到CDN节点后,节点会判断自己的内容缓存是否有效,如果有效,则立即响应缓存内容给用户,从而加快响应速度。如果CDN节点的缓存失效,它会根据服务配置去我们的内容源服务器获取最新的资源响应给用户,并将内容缓存下来以便响应给后续访问的用户。因此,一个地区内只要有一个用户先加载资源,在CDN中建立了缓存,该地区的其他后续用户都能因此而受益。

不同地区的用户访问同一个域名却能得到不同CDN节点的IP地址,这要依赖于CDN服务商提供的智能域名解析服务,浏览器发起域名查询时,这种智能DNS服务会根据用户IP计算并返回离它最近的同网络CDN节点IP,引导浏览器与此节点建立连接以获取资源。

也有一些第三方的CDN: 前端公共库CDN加速

5、非覆盖式发布资源

目前很多更新自由文件都是覆盖式的发布,但是覆盖式的发布会造成一些问题

待发布资源覆盖已发布资源,无论是先上线页面,还是先上线静态资源都会在部署过程中发生页面错乱的问题。所以就需要非覆盖式发布,用文件的哈希值来对资源文件进行重命名,把哈希字符串放到资源文件发布路径中,这样,内容有修改的资源就变成了一个新的文件发布到线上,不会覆盖已有的资源文件,这样用户在访问的时候就不会出现错乱的问题。

这种资源很多,不止css,包括js,图片路径,字体图标库等

<link href="./static/css/main_88f0972.css" rel="stylesheet">

下面借鉴一个图来示例一下,很容易看懂:

这种方法虽然优化了资源文件,但是它无法通过手动来维护,需要一些工具来支持,
推荐几个构建工具:

还有其他的就不说了,自己可以google一下,好多的内容我也是看了很多篇的讲资源优化的方案总结出来的,有不对的地方可以请批评指出,上面有些讲解我也是在做笔记的时候记录的,来源我没有标记,感谢那些人的精彩讲解,大家共同学习

来源:blog.csdn.net/xllily_11/a…
或者www.zhihu.com/question/20…

原文来自我的blog:codehtml