如果遇到这题,需要明白,面试官实质要问的就是前端性能优化 。
前端性能优化可以分为执行性能 和 加载性能 。
执行性能 即代码运行过程中的性能优化,常见的如:避免不必要的DOM操作,避免深层次的html元素嵌套,图片懒加载,CSS的代码顺序,减少冗余的js代码……执行性能与每个开发者的技能水平相关,也需要开发者提高对自身的要求。更重要的是执行性能并非本文关注的重点。
加载性能 即在相同的网络环境下,使资源更快的加载回来。接下来介绍一些可以明显提升加载性能的方法。
资源压缩合并,减少HTTP请求
- 雪碧图,图片整合
- JS资源合并
- CSS合并
非核心代码异步加载
常规的html解析执行顺序是,当html解析碰到script
标签或者link
标签,它会去加载js
文件,文件加载回来之后会立即开始执行,等到 JS 执行完成,才会接着继续往下解析HTML (CSS加载回来后不会阻塞后续执行,可以查看”在浏览器输入一个地址发生了什么“的流程图)。也就是说JS
的加载执行会阻塞页面渲染,所以这也就是我们倡导将JS
的加载放在body
之后。
什么是异步加载呢,也就是当碰到需要加载JS
文件时,你去加载,但不阻塞HTML的后续解析。
异步加载的方式
- 动态脚本加载 :使用JS去创建Script节点
- defer :
<script src="defer.js" defer></script>
- async :
<script src="async.js" async></script>
异步加载的区别
defer
是在HTML解析完成之后才会执行;async
是在加载完成之后立即执行。- 如果是异步加载多个JS文件,
defer
会按照加载的顺序依次执行,async
会根据JS文件的加载完成顺序执行。
如果一个页面异步加载了多个JS文件,使用
defer
的话,它会根据加载顺序[1,2,3,4]来执行,也就是如果2,3,4已经加载完成,但1还没有加载完成,它会等1加载完成之后,按照1,2,3,4顺序执行。使用
async
它会根据加载完成的顺序来执行,例如加载顺序是[1,2,3,4],但加载完成顺序和网络与文件大小相关,有可能加载完成顺序是[2,1,3,4]也有可能是[4,2,3,1],他根据加载完成顺序执行
浏览器缓存
强缓存的响应头多了
Expires
过期时间,服务器的绝对时间cache-Control
缓存时间,相对于浏览器,默认3600秒
协商缓存的响应头
Last-Modified
资源最后修改时间Etag
资源的hash值(文件内容不变,hash不会变)
协商缓存的请求头
If-modified-Since
资源最后修改时间If-None-Match
资源的hash值
协商缓存只有文件的hash值改变才能确定文件真的更新了;最后更新时间改了,但资源内容不变,依旧使用缓存
使用CDN
使用CDN是可以很明显提升页面性能的,但现在的前端项目大多数人习惯了使用npm install
,然后import
导入,反而不太熟悉怎么怎么在现代前端项目中使用CDN了。
关于怎么在现代工程化的项目中使用CDN可以看我这篇文章https://juejin.im/post/5d46378a5188255d845fff71
DNS预解析
在”在浏览器输入一个地址发生了什么“ 一文中,我们说了,输入地址后第一步就是进行DNS解析,如果一个页面加载了n多资源,n多 a
标签,这些内容也是需要进行DNS解析的,提前进行DNS解析,也是可以很大程度提高前端性能的。
DNS预解析就两行代码。
强制打开DNS
1 | <meta http-equiv="x-dns-prefetch-control" content="on"> |
预解析特定域名,href
填写你要预解析的域名
1 | <link rel="dns-prefetch" href="//hm.baidu.com"> |
使用GZip压缩
启用GZip压缩可以非常明显看到速度提升,关于如何开启GZip压缩可以看 恰运维一口饭之启用GZIP压缩
其他
更多的性能优化内容可以看看雅虎军规