* [ ] 题目:提供页面性能的方法有哪些?
* 资源优化
1. 资源**压缩合并**,减少http请求(js合并)(gzip)(css合并,图片处理css:cssSprite,打包成base64格式)
2. 非核心代码**异步加载**==》异步加载方式==》异步加载的区别
3. 非核心代码也可按需加载(需要的时候才会加载,和异步加载不同)
4. 利用**浏览器缓存**(减少请求)(最重要的一步)==》缓存的分类==》缓存的原理
4. 使用CDN(网络优化,最快的下载资源)(为什么?CDN是不同区域的网络优化,北京访问地址,会就近找到CND进行加载)(距离远走的路由器比较多)
5. 使用webpack的tree Shaking,删除无用代码
5. 预解析DNS(DNS解析)
~~~
~~~
页面中a标签默认预解析,https开头的协议,很多浏览器默认关闭预解析,meta是用来打开预解析。
6. 使用SSR后端渲染,数据直接输出到HTML中(以前ssr:server site render,jsp,php,asp)
* 构建工具优化(webpack为例)
1)js,css代码压缩(optimize-css-assets-webpack-plugin),css提取?
2)Tree Shaking:把一个模块里没用到的东西都摇晃掉。
3)Code Splitting:(代码分割,异步加载)
4)懒加载:通过import异步的加载模块
5)Preloading,Prefething:Prefething(利用空闲时偷偷下载代码。(首屏快,打开模态框快))
6)Webpack与浏览器缓存(Caching):打包后的文件会放在服务器上,如果重新打包,会生成相同的js文件名,此时用户会走浏览器中的缓存,页面逻辑不会更新
7)打包文件过大:公共代码拆分
* [ ] 首屏加载优化(渲染优化)
1)尽可能提高CSS加载速度
使用CDN;对CSS压缩(webpack压缩);减少http请求(多个css合并,css精灵);放入head中;合理使用缓存(cache-control,expires,E-tag,可在后面加版本号)。
2)JS优化
js文本放入body底部(或者defer,async);
按需加载;
* [ ] 渲染优化
* css放前面(head),js放后面(body后)(或js异步加载)
* 懒加载(图片懒加载IntersectionObserver交叉观察者、下拉加载更多)(什么时候用,什么时候加载)
* DOM操作优化(减少重绘和回流)
* 减少DOM查询,对DOM查询做缓存
* 减少DOM操作,多个操作尽量合并在一起执行
(DOM操作是非常非常昂贵的)
* **事件节流**(throttle,减少cpu计算)
* 尽早执行操作(如DOMContentLoaded)
4. css优化
1)预先解析DNS (dns-prefetch)
2)preload prefetch
3)优化重绘和回流
4)不用使用@import
(两点:影响浏览器的并行下载,下载完、解析完后才再下载;下载顺序打乱)
5)嵌套不要超过3级
6)样式重置
7)css压缩合并,head中引入
8)动画优化:css3过渡尽量使用transform和opacity,不用使用left和top(注:transform不会引起回流)
9)删除不必要的零和单位
10)雪碧图
5. js优化
1)DOM优化
2)使用事件委托
3)异步加载
4)按需加载
5)节流和防抖
6)预加载
7)CDN
**高性能前端代码,考虑的不是缓存,而是代码的使用率。**,同步代码打包到一个js文件,意义是不大的(有限)**,多写异步加载代码,才能让网站性能真正的提升。**
* [ ] 页面性能类:异步加载
1. 异步加载的方式
1)动态脚本加载
~~~
动态创建
(function(){
var scriptEle = document.createElement("script");
scriptEle.type = "text/javasctipt";
scriptEle.async = true;
scriptEle.src = "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js";
var x = document.getElementsByTagName("head")[0];
x.insertBefore(scriptEle, x.firstChild);
})();
~~~
2)defer
3)async
4)vue中配合路由进行异步加载(import)
普通脚本会阻塞浏览器解析,但加上这两个,脚本就变成异步了,可以等到**解析完后再执行**。
2. 异步加载的区别
1)async是**异步执行**的,**加载完就会执行**,不能保证顺序,**一定要onload前**,不确定在DOMContentLoaded事件前或后
2)defer是**延迟执行**,即这段Javascript加载时,html并未停止解析,效果像放在脚本body后面一样,按规范**在DOMContentLoad事件前**,实际不确定
defer是在HTML解析完后才会执行,如果多个,按加载顺序执行
3)defer与普通script区别:载入Javascript文件不会阻塞HTML的继续,执行阶段被放到HTML标签完成之后,
4)加载多个js时,async是无序的,defer是有序的。
* [ ] 浏览器缓存

**分析**:客户端发起请求,首先判断是否缓存,如果没有向服务器请求资源;如果有,判断缓存是否过期(过期策略,强缓存),如果没有过期,直接读取本地资源(**200ok **from disk cache,from memory cache);如果过期,判断协商缓存(协商策略),**重新向服务器发起验证**;如果验证不通过,向服务器请求资源,如果验证通过,收到**304响应**,并依据存储策略,根据**响应头更新缓存(Cache-Control,Content-Loation,Date,ETag,Expires,Vary)**。
浏览器存的备份(副本)(放在了本地磁盘上)
页面的缓存状态是由header(请求头和响应头)决定的。四个参数。
1)**http header中与缓存有关的key:**
Cache-Control:指定缓存机制,覆盖其他设置
Expires:指定缓存的过期时间
Last-Modified:资源最后一次的修改时间
ETag:唯一标识请求资源的字符串。
2)**缓存协商策略**:用于**重新验证缓存资源是否有效。**
If-Modified-Since:缓存校验字段,值为资源最后一次的修改时间(与Last-Modified相同)
If-Unmodified-Since:同上,处理方式与之相反
If-Match:缓存校验字段,值为唯一标识请求资源的字符串(同ETag)
If-None-Match:同上,处理方式与之相反
1. 缓存的分类
1)**强缓存(直接用)**
http请求头上
Expires(response headers),Cache-Control(response headers)
Expires:(Expires:Thu,21 Jan 2017 23:39:02 GMt)
过期时间,key和value值,value值表示的是**绝对时间**(服务器的绝对时间,有可能和本地浏览器不一致,会有偏差)
Expires要和Last-Modified结合使用
Cache-Control:Cache-Control: max-age = 3600
**拿到到资源之后,在3600s之内不再请求服务器,直接从浏览器拿缓存。**
max-age(s):缓存最大的有效时间。
no-cache:指定不缓存响应,资源不进行缓存,但不代表不缓存,而是在缓存前向服务器确认资源是否被修改。(因此不缓存,还有加private指令,并将时间设为过去的时间)
**相对时间**(不管客户端和服务端时间是否一致,使用客户端相对时间,单位是秒)
如果两个都有,以Cache-Control为准
强缓存:无论是绝对时间还是相对时间,在这时间之内不会和服务器通信了(不会再向服务器发送请求了),直接从浏览器中拿取。
2)**协商缓存(和服务器协商,文件是否能使用)**
**Last-Modified(response headers) If-Modified-Since(request)**
**Etag(response) If-None-Match(request)**
Last-Modified:上次修改的时间,拿到文件的时候,浏览器给资源文件的浏览器**响应头**中加一个Last-Modified(下发一个时间在response headers中),是一个时间,当**强缓存失效**(过期),再次请求时,使用If-Modified-Since携带上次获取的时间,
(If-Modified-Since这个字段携带Last-Modified这个字段的时间,两个是一个值,在Http请求头中)
缺点:修改时间变了,但内容没有变化,(完全可以从副本拿),**Etage可解决**。
Etag:服务器下发一个Etag值,**是一个hash值,验证资源是否已经修改**(优点:)
Etag和If-None-Match是一个值
Etag的优先级比较高。
注意:**服务器返回304是缓存,200不是缓存说法不对**
一旦资源命中强缓存,**浏览器便不会向服务器发送请求**,而是直接读取缓存,Chrome下现象是**200 OK(from disk cache)或者200 ok(from memory cache)**
缓存过期后,**继续请求该资源**,对于现在浏览器,有两种做法:
1)根据响应中的Etag,在request header中添加If-None-Math,**服务器收到请求**,如果相同,则命中协商缓存,**返回304**
2)Last-Modified和If-Modified-Since,**服务器收到请求后**,进行比较,若相同,命中协商缓存,**返回304响应**。
3)并非所有浏览器,IE会返回200
2. 另外的缓存方式
LocalStorage和sessionStorage
* [ ] 如何优化SPA应用的首屏加载速度慢的问题
1)公用js库通过script标签外部引入,减少app.bundle的大小,让浏览器并行下载资源文件,提高下载速度。
2)配置路由时,页面和组件使用懒加载的方式注入,所需app.bundle体积。
3)加一个首屏loading图,提升用户体验(骨架屏)
* [ ] Vue改变数组触发视图更新
~~~
push(),pop(),shift(), unshift(), splice(), sort()
reverse(),Vue.set(target, key, value)
~~~
## 你有对 Vue 项目进行哪些优化?
**(1)代码层面的优化**
* v-if 和 v-show 区分使用场景
* computed 和 watch 区分使用场景
* v-for 遍历必须为 item 添加 key(优化遍历性能),且避免同时使用 v-if
* 长列表性能优化
* **事件的销毁**
* 图片资源懒加载
* 路由懒加载
* 第三方插件的按需引入
* 优化无限列表性能
* 服务端渲染 SSR or 预渲染
**(2)Webpack 层面的优化**
* Webpack 对图片进行压缩
* 减少 ES6 转为 ES5 的冗余代码
* 提取公共代码
* 模板预编译
* 提取组件的 CSS
* 优化 SourceMap
* 构建结果输出分析
* Vue 项目的编译优化
**(3)基础的 Web 技术的优化**
* 开启 gzip 压缩
* 浏览器缓存
* CDN 的使用
* 使用 Chrome Performance 查找性能瓶颈