浏览器性能优化

一、浏览器层面

突破单线程解析渲染阻塞限制 -- 动态创建script的方式载入

浏览器是一个单线程解析模式去解析渲染从服务器端拿到的html文本,css加载的过程中会对后续的脚本资源加载造成阻塞,脚本的加载也会阻塞后续DOM结构的解析造成页面的留白时间增长。

  • 针对不需要DOM操作(主要考虑是需要操作DOM的脚本往往需要获取一些样式信息)的Js脚本可以采用动态创建script的方式载入,动态载入的脚本不阻塞后续资源的加载。
  • 脚本文件加载可以加上defer或者async属性标识防止阻塞

避开Cookie性能bug -- CDN部署静态资源

浏览器在每次都会往同域的任何资源的http请求中自动带上cookie信息的情况,这里有必要进行优化一下,因为像css、js、image这些资源请求是不需要cookie信息的,会无端造成请求带宽的浪费。Cookie free性能优化方案的处理方式是CDN异域静态资源服务器部署我们的前端css、js、image资源

突破浏览器并发连接限制 -- 将资源划分域分开部署

浏览器针对domain,而非页面page做并发连接限制的特性,domain hash的技术优化方案的处理方式是将资源划分域分开部署,但因为过多的域划分会增加多余的DNS开销,这里通行的数量是3个以内。

配置缓存

配置缓存时要切记,浏览器在处理用户请求时,如果命中强缓存,浏览器会直接拉取本地缓存,不会与服务器发生任何通信,也就是说,如果我们在服务器端更新了文件,并不会被浏览器得知,就无法替换失效的缓存。所以我们在构建阶段,需要为我们的静态资源添加md5 hash后缀,避免资源更新而引起的前后端文件无法同步的问题。

二、HTTP层面

减少http请求数量 减轻http数据请求大小

缓存机制

协议缓存方案:利用http缓存协议头cache-control做304缓存,或者更精确的ETAG设置依据资源的修改时间来设置缓存方案。

appCache应用缓存方案:离线应用缓存是h5提供一个比较有效的离线应用方案,利用navigator.online 、window.applicationCache对象、服务器.appcache(以前是.manifest)配置文件保证在脱机下的移动web应用照常能用,如果要做数据的离线还要加上window.localStorage做离线数据的保存。

页面切片预加载方案 -- 对页面合理的分块,在服务器端拼接完成并吐出来

性能优化静态资源维度最后一块内容就是针对页面,如何尽早输出页面模块,减少留白时间是一个思考点。facebook应用的BigPipe方案是个很不错的借鉴思想,还有淘宝也有首页做了相应的切片方案,对页面合理的分块,在服务器和客户端建立某种对应机制,让各个页面块并行的在服务器端拼接完成并吐出来

CDN

用户和服务器之间距离越远,经过的路由器越多,延迟也就越高。使用CDN的目的之一便是解决这一问题,当然不仅仅如此,CDN还可以分担IDC压力。

1.便于CDN业务独立,能够独立配置缓存。

2.抛开无用cookie,减小带宽占用。

HTTP2

三、代码层面

preconnet 预连接

浏览器要建立一个连接,一般需要经过DNS查找,TCP三次握手和TLS协商(如果是https的话),这些过程都是需要相当的耗时的,所以preconnet,就是一项使浏览器能够预先建立一个连接,等真正需要加载资源的时候就能够直接请求了。

prefetch 预加载

能够让浏览器预加载一个资源(HTML,JS,CSS或者图片等),可以让用户跳转到其他页面时,响应速度更快。

prerender 预渲染

而prerender不仅会加载资源,还会解执行页面,进行预渲染,但是这都是根据浏览器自身进行判断。 浏览器可能会分配少量资源对页面进行预渲染挂起部分请求直至页面可见时可能会放弃预渲染,如果消耗资源过多等等情况。。。

内联首屏关键CSS(Critical CSS)

性能优化中有一个重要的指标——首次有效绘制(First Meaningful Paint,简称FMP)即指 页面的首要内容出现在屏幕上的时间。 这一指标影响用户看到页面前所需等待的时间,而 内联首屏关键CSS能减少这一时间。

我们应当只将渲染首屏内容所需的关键CSS内联到HTML中

异步加载CSS

JavaScript动态创建link标签

rel="preload" 异步加载资源

利用GPU硬件加速浏览器渲染(will-change: transform, opacity;)

在页面中创建一个新的渲染层最好的方式就是使用CSS属性will-change,对于目前还不支持will-change属性、但支持创建渲染层的浏览器,可以通过3D transform属性来强制浏览器创建一个新的渲染层。需要注意的是,不要创建过多的渲染层,这意味着新的内存分配和更复杂的层管理。

GPU

减少回流和重绘

使用createDocumentFragment进行批量的 DOM 操作

让要操作的元素进行”离线处理”,处理完后一起更新:display:none cloneNode和 replaceChild

添加 will-change: tranform ,让渲染引擎为其单独实现一个图层,当这些变换发生时,仅仅只是利用合成线程去处理这些变换,而不牵扯到主线程,大大提高渲染效率。

四、构建层面

html压缩 :HtmlWebpackPlugin

作用:

  • 为html文件中引入的外部资源如script、link动态添加每次compile后的hash,防止引用缓存的外部文件问题
  • 可以生成创建html入口文件,比如单页面可以生成一个html文件入口,配置Nhtml-webpack-plugin可以生成N个页面入口

提取css并压缩:extract-text-webpack-plugin

JS压缩:new webpack.optimize.UglifyJsPlugin()

代码分割 提取公共资源 Tree-shaking 图片压缩 雪碧图

五、移动端首屏优化

常规的前端和后端的性能优化在桌面时代已经有最佳实践,主要的是:

  • 降低请求量:合并资源,减少 HTTP 请求数,minify / gzip 压缩,webP,lazyLoad。
  • 加快请求速度:预解析DNS,减少域名数,并行加载,CDN 分发。
  • 缓存:HTTP 协议缓存请求,离线缓存 manifest,离线数据缓存localStorage。
  • 渲染:JS/CSS优化,加载顺序,服务端渲染,pipeline。

六、服务器层面

服务器开启gzip压缩

Nginx可以通过反向代理来实现负载均衡。

Nginx解决跨域:作为反向代理服务器,就是把http请求转发到另一个或者一些服务器上。通过把本地一个url前缀映射到要跨域访问的web服务器上,就可以实现跨域访问。

它的作用便是能够将用户的请求分配到压力较小的服务器上,其机制是轮询。以轮询方式将请求分配到不同服务器上。