浏览器工作原理:https://www.cnblogs.com/thonrt/p/10008220.html

浏览器渲染原理: https://www.cnblogs.com/thonrt/p/10008742.html

基于上面这两篇文章,我们可以把web性能优化分为两大方面:

  1. 网络传输性能优化
  2. 页面渲染性能优化

本文主要介绍网络传输性能优化。

本人总结网络传输性能优化主要有以下几个点:

  • 减少请求数
  • 减小请求资源体积
  • 提升网络传输速率

下面我们来逐一击破。

1.资源打包和压缩

想要实现首屏渲染优化,必须对资源进行打包和压缩

  • 对css/js进行压缩,就是减小请求资源体积。
  • 对css/js进行资源合并,就是减少请求数

一般会把公共库合并,因为公共库不会经常改变

把不同的页面合并,但还是遵循见机行事,随机应变

至于对css和js压缩合并的工具,本人比较倾向webpack,毕竟从版本2用到版本4的。

2.浏览器缓存

浏览器缓存主要有两个缓存:

  • 强缓存:不会向服务器发送请求
  • 协商缓存: 304状态码

用户行为对浏览器缓存:

  • 地址栏访问,触发缓存机制
  • 新开窗口,前进后退,触发缓存机制
  • F5跳过强缓存,进入协商缓存
  • F5 + Ctrl 跳过强缓存和协商缓存

下面通过文字来解释下这个图

2.1 强缓存,与强缓存有关的header字段:expires和cache-control

1.expires,它的值是一个绝对时间的GMT格式的字符串。如果发送请求的时间在expires之前,那么本地缓存始终有效,否则会发送请求到服务器来获取资源

2.cache-control:max-age,主要是利用max-age值来判断,它是一个相对值。资源第一次请求的时间个cache-control设定的有效期,计算出一个资源过期时间,再拿这个过期时间和当前的请求时间对比,如果请求时间在过期时间之前,就能命中缓存,否则就会发请求到服务器请求资源。

如果Cache-control和expires同时存在,cache-control优先级较高

2.2 协商缓存,与协商缓存有关的header字段:Last-Modified和If-Modified-Since

这两组是成对出现的。即第一次请求的响应带上某个字段(Last-Modified或者Etag),则后续请求则会带上对应的请求字段(If-Modified-Since或者If-None_match)。

如响应头没有Last-Modified或者Etag字段,则请求头也不会有对应的字段。

1.Last-Modified/If-Modified-Since

  • 浏览器第一个请求资源时,服务器在返回资源的同时,在respone的header加上Last-Modified的header,这个header表示在资源服务器上的最后的修改时间
  • 浏览器再次请求这个资源时,在request的header中加上If-Modified-Since的header,这个header就是上一次请求返回的Last-Modified的值
  • 服务器再次受到资源请求时,根据浏览器传过来的If-Modified-Since和服务器上最后的修改资源时间判断资源是否变化。如果没有变化就返回304 Not Modified,但是不会返回资源内容。如果有变化,就正常返回资源内容。当返回304时,不会再添加Last-Modified的header。
  • 浏览器收到304响应后,就会从缓存中加载资源
  • 如果协商缓存没有命中,浏览器直接从服务器加载资源,Last-Modified会更新返回到respone的header中

2.Etag/If-None-Match

  • 浏览器第一个请求资源时,服务器在返回资源的同时,在respone的header加上Etag的header,这个header表示在资源服务器上的最后的标志
  • 浏览器再次请求这个资源时,在request的header中加上If-None-Match的header,这个header就是上一次请求返回的Etag的标志
  • 服务器再次受到资源请求时,根据浏览器传过来的If-None-Match和服务器上最后的修改资源的Etag,判断资源是否变化。如果没有变化就返回304 Not Modified,但是不会返回资源内容。如果有变化,就正常返回资源内容。当返回304时,会再次添加Etag的header。
  • 浏览器收到304响应后,就会从缓存中加载资源
  • 如果协商缓存没有命中,浏览器直接从服务器加载资源,Last-Modified会更新返回到respone的header中

2.3  那有了Last-Modified,为什么还要Etag?

Etag的出现主要是解决last-modified比较难解决的问题:

某些服务器不能精准的获取文件最后的修改时间

某些文件修改频繁,比如在一秒以内修改了N次,If-modified-Since能检查到s级的,这种修改就无法判断。

这时,利用Etag能够更加准确的控制缓存,因为Etag是服务器自动生成或者由开发中生成对应资源在服务器的唯一标识符。

Etag的优先级高于Last-Modified, Etag的缓存会被写入硬盘中

强缓存如何重新加载缓存过的资源?

强缓存不会发送请求到服务端,根据设置的缓存时间,浏览器一直从缓存中获取资源,在这期间,若资源发生变化,浏览器在缓存期间就一直得不到最新的资源。

那怎么解决?

我们在构建的时候,需要为我们为静态资源添加md5 hash后缀,避免资源更新而引起的前后端文件无法同步的问题

这个图更加直观

3. 图片资源优化

在我们实际开发中,真正占用了大量网络传输资源的,并不是这些文件,而是图片。所以对图片进行优化工作的话,你就能看见明显的效果。

3.1 不要在HTML中缩放图像

比如在一个200*200的容器里面放了一张400*400的图片,一张200kb和2M的图片的传输时间会是200m和12s的差距,所以当你需要多大的图片的时候,就在服务器准备多大的图片,尽量固定图片尺寸。

3.2 使用雪碧图 Css Sprite , Svg Sprite

这里给大家推荐一个在线生成雪碧图的工具:https://www.toptal.com/developers/css/sprite-generator

还有插件生成雪碧图的方法:webpack-spritesmith

首先介绍写插件生成雪碧图的思路:

首先,把所有的小图标放置在一个文件夹内便于管理

然后,我们需要插件去读取这个文件下内的所有图片资源文件,以文件夹名称生成一张雪碧图到指定的位置,并且输出能够正确使用的css文件

3.3 使用字体图标 iconfont

无论是压缩的图片还是雪碧图,终归还是图片,只要是图片就会占用大量传输网络资源。但是字体图标的出现,让前端看到了另外一个神奇的世界。

我最喜欢用的是阿里矢量图标库(网址:http://www.iconfont.cn/ ),里面有大量的矢量图资源,而且你只需要像在淘宝采购一样把他们添加至购物车就能把它们带回家,整理完资源后还能自动生成 CDN 链接,可以说是完美的一条龙服务了。(图片来自官网首页)

图片能做的很多事情,矢量图都能作,而且它只是往 HTML 里插入字符和 CSS 样式而已,和图片请求比起来资源占用完全不在一个数量级,如果你的项目里有小图标,就是用矢量图吧。

但如果我们做的是公司或者团队的项目,需要使用到许多自定义的字体图标,可爱的设计小姐姐们只是丢给你了几份.svg图片,你又该如何去做呢?

其实也很简单,阿里矢量图标库就提供了上传本地 SVG 资源的功能,这里另外推荐一个网站——icomoon。icomoon 这个网站也为我们提供了将 SVG 图片自动转化成 CSS 样式的功能。(图片来自 icomoon 首页)

我们可以点击 Import Icons 按钮导入我们本地的 SVG 资源,然后选中他们,接下来生成 CSS 的事情,就交给 icomoon 吧,具体的操作,就和阿里矢量图标库类同了。

3.4 使用Webp

WebP 格式,是谷歌公司开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有 JPEG 的 2/3,并能节省大量的服务器带宽资源和数据空间。Facebook、Ebay 等知名网站已经开始测试并使用 WebP 格式。

我们可以使用官网提供的 Linux 命令行工具对项目中的图片进行 WebP 编码,也可以使用我们的线上服务,这里我推荐叉拍云(网址:https://www.upyun.com/webp )。但是在实际的上线工作中,我们还是得编写 Shell 脚本用命令行工具进行自动化编译,测试阶段用线上服务方便快捷。

4 使用CDN

Last but not least,再好的性能优化实例,也必须在 CDN 的支撑下才能到达极致。

如果我们在 Linux 下使用命令$ traceroute targetIp或者在 Windows 下使用批处理> tracert targetIp,都可以定位用户与目标计算机之间经过的所有路由器,不言而喻,用户和服务器之间距离越远,经过的路由器越多,延迟也就越高。使用 CDN 的目的之一便是解决这一问题,当然不仅仅如此,CDN 还可以分担 IDC 压力。

当然,凭着我们单个人的资金实力(除非你是王思聪)是必定搭建不起来 CDN 的,不过我们可以使用各大企业提供的服务,诸如腾讯云等,配置也十分简单,这里就请大家自行去推敲啦。

最新文章

  1. Zabbix监控mysql主从复制状态
  2. scrapy爬虫笔记(三)------写入源文件的爬取
  3. myeclipse 常用快捷键总结
  4. 【HTML】Intermediate2:Text: AbbreviationsQuotations Code
  5. [六]JFreeChart实践五之与Struts2整合
  6. Eclipse + Pydev 配置Python开发环境
  7. Word续上表
  8. Android开发手记(28) Handler和Looper
  9. OpenGL ES 2.0 剪裁测试
  10. LwIP学习笔记——STM32 ENC28J60移植与入门
  11. 用mysql dump 导入与导出的方法
  12. centos 编译安装nginx
  13. JS模拟实现封装的三种方法
  14. Appium适配Android7.0以上版本
  15. python与RabbitMQ
  16. MapReduce编程模型简介和总结
  17. 将本地的代码推送到公网的github账号去
  18. Python2.7-hashlib
  19. HDU 4059 The Boss on Mars(容斥原理 + 四次方求和)
  20. shell脚本read -t 超时输入测试

热门文章

  1. CTF—攻防练习之HTTP—SQL注入(SSI注入)
  2. 【HANA系列】SAP HANA SQL获取时间中的小时
  3. PJzhang:python基础入门的7个疗程-six
  4. 关联规则(Apriori算法)
  5. Caused by: com.rabbitmq.client.AuthenticationFailureException: ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN. For details see the broker logfile.的几种原因
  6. python 爬虫小案例
  7. vim配置及插件安装笔记
  8. # 丢包&&掉帧&&文件删除
  9. uniapp配置scss支持
  10. python-day29(正式学习)