为什么打开网页会有白屏,这中间做了什么:
初始化 webview -> 请求页面 -> 下载数据 -> 解析HTML -> 请求 js/css 资源 -> dom 渲染 -> 解析JS 执行 -> JS 请求数据 -> 解析渲染 -> 下载渲染图片
桌面时代的最佳实践
降低请求量:合并资源,减少 HTTP 请求数,minify / gzip 压缩,webP,lazyLoad。
加快请求速度:预解析DNS,减少域名数,并行加载,CDN 分发。
缓存:HTTP 协议缓存请求,离线缓存 manifest,离线数据缓存localStorage。
渲染:JS/CSS优化,加载顺序,服务端渲染,pipeline
- 对首屏优化,影响最大的是网络请求
缓存优化:每次询问后台是否有更新。或者设置一个过期时间(多长时间不去询问更新)。js/css文件通过加上hash判断版本更新。json数据先渲染本地的,再向服务端请求,二次渲染最新数据。
正在用的离线包
预加载
html字符串写入后台配置服务,js/css上传cdn。同时保留一套原来的html。
用户访问客户端,请求预加载接口,后台下发预加载的html字符串/js/css文件;当用户进入对应html时,如果预加载成功(正确的版本资源),阻止webview的静态资源请求,直接使用预下载的css/js。
1 dns-prefetch:dns预抓取,预先告知浏览器,之后要访问‘a.com’域名,浏览器会先查询dns,以后不需要等待查询dns,效果有限。在url栏的输入命中历史记录,Chrome就会提前解析DNS、预拉取页面。
<link rel="dns-prefetch" href="//a.com">
2 Preconnect:不光会解析DNS,还会建立TCP握手连接和TLS协议(如果需要)
场景:需要加载第三方资源(字体,js包,与css并行建立dns连接)
<link rel="preconnect" href="//a.com">
3 Prefetch: 建立连接,下载资源,而且进行缓存。一定会用到的资源。弱网络不会请求大资源。
<link rel="prefetch" href="a.png">
正如Bram Stein在他的文章中指出,prefetch很适用于优化webfonts的性能。以前,字体文件必须等DOM和CSSOM创建好后才能下载,可如果prefetch了字体,这个瓶颈就能轻松解决了。
4 subresource: 指定资源是最高优先级的,在当前页就下载,用到。
<link rel="subresource" href="a.png">
5 prerender: 预加载指定页面的所有资源。
<link rel="prerender" href="a.html">
lazyload:不重要的图片,如背景图片,延迟加载,如vue-lazyload,jq的lazyload包
滚屏加载:如商品列表,避免打开另一个页面重绘
第三方资源:如页面统计、地图显示、分享组件,异步加载
百分比进度条:让用户不枯燥
使用图片的替代(css3, svg, iconfont)
小图片用base64
如果要在head引入js,要放在所有css的前面。不影响css并行加载。
DOMContentLoaded 和 load
在现在浏览器中,为了减缓渲染被阻塞的情况,现代的浏览器都使用了猜测预加载。当解析被阻塞的时候,浏览器会有一个轻量级的HTML(或CSS)扫描器(scanner)继续在文档中扫描,查找那些将来可能能够用到的资源文件的url,在渲染器使用它们之前将其下载下来。
现代浏览器不会等到所有html被解析完成才渲染,浏览器可以渲染不完整的DOM tree 和 CSSOM,减少白屏时间,减少firstpaint时间。
jQuery 中经常使用的 $(document).ready(function() { // …代码… }); 其实监听的就是 DOMContentLoaded 事件,这是可以访问所以DOM元素,减少交互时间,HTML解析加载完成;而 $(document).load(function() { // …代码… }); 监听的是 load 事件
onload事件所有的浏览器都支持,DOMContentLoaded IE67不支持
js放的位置
script标签如果带上特殊属性:
1 async: 先不阻塞,异步去加载资源,加载成功了,阻塞,解析js
2 defer: 先不阻塞,等DOMContentLoaded 阻塞。
js放的位置,不会改变 DOMContentLoaded 的触发时间
重绘 和 回流
有没有一种方式可以避免重绘和回流呢?那么就是用CSS启用硬件加速。硬件加速就是GPU加速。
开启GPU加速的方式常见的触发硬件加速的css属性:
transform opacity filters Will-change
用法:
可以用translate替代top/left…改变
用opacity替代visibility
不要一条一条地修改 DOM 的样式,预先定义好 class,然后修改 DOM 的 className
把 DOM 离线后修改,比如:先把 DOM 给 display:none (有一次 Reflow),然后你修改100次,然后再把它显示出来,当然每个浏览器都做了相应的优化所以没必要这么弄
不要把 DOM 结点的属性值放在一个循环里当成循环里的变量,例如循环调用 getBoundingClientRect() 方法,将会导致页面一直处于回流的过程。
不要使用 table 布局,因为你改动一点点都将影响整个 table 的布局
动画实现的速度的选择
参考
https://www.jianshu.com/p/a336e5ebe623
https://www.cnblogs.com/caizhenbo/p/6679478.html