浏览器有一个重要的对象performance,很多的和时间节点有关的数据都可以从这个对象上去获取
渲染优化
布局和绘制
动画可以走复合的过程,不会触发回流和重绘;
复合是关键渲染路径中最后一个环节,主要的作用就是把页面拆解成不同的图层;使用 transform 和 opacity 可以把涉及到的元素提取到一个图层,那么这些元素的发生视觉上变化的时候就只会触发复合,而不会触发布局和重绘。
高频事件防抖
比如滚动,这类事件在一帧里会触发多次,我们只关心滚动到哪里,解决页面卡顿大利器 requestAnimationFrame(每一帧的布局和绘制之前)。
代码优化
- js 优化
同时 100kb 的文件,js 和图片加载时间相同,但是 js 之后要经过编译,解析,执行等等更耗时,虽然这个过程是跟浏览器处理引擎有关,但如果再代码层面进行配合,实际上可以优化这个过程
两种方案:代码拆分,按需加载,和 tree shaking(代码减重);另外从解析和执行来看,应该减少主线程的工作量,避免长任务,避免超过 1kb 的脚本,使用 raf 进行时间调度 - html 优化
减少 iframes 使用;避免节点深层次嵌套;避免 table 布局,开销很大;css js 尽量外链
资源优化
压缩与合并
减少 http 请求数,减少请求资源大小
html 压缩:使用 HtmlWebpackPlugin 的时候配置 minify
css 压缩:mini-css-extract-plugin
js 压缩:
uglifyjs:单线程压缩代码,也就是说多个js文件需要被压缩,它需要一个个文件进行压缩。所以说在正式环境打包压缩代码速度非常慢
webpack-parallel-uglify-plugin:w4
terser-webpack-plugin:w4 并行处理
TerserPlugin:w5
预计算:const day = 7 - 5;线上的话直接变成 const day = 2;在编译器把一些能计算出结果的代码先计算出来,这样子就不会在运行时进行计算(terse 自动帮你做)
图片优化
选择合适的图片格式
JPEG/JPG:首屏轮播图
png:做小的图标或者 logo
webp:不是标准 google
小图标可以用 iconfont处理,字体文件非常小
合适的图片大小
图片资源优先级:重要的图片(首屏图片)先进行加载
懒加载
构建优化
webpack 的优化配置
Tree-shaking(前提是模块化)
w4 里设置 mode:production会开启 tersePlugin
其简单的工作原理是找到入口文件,入口相当于树的根节点,去看入口文件引用了什么东西。又会进一步去分析这些应用的包或者模块里面又引用了什么模块。不断地进行分析之后把所有需要的东西保留下来,把那些引入了但是没有用到的shaking下去,最后打包生成的bundle只包含运行时真正需要的代码
但是有时候会涉及到在全局作用域上添加或者修改属性,export是体现不出来的,就会被shaking掉,把所有不需要被shaking掉的文件放在sideEffect数组里
webpack 依赖优化
第一种是利用 noParse 参数提高构建速度。noParse的意思就是不解析,直接通知 webpack 忽略较大的库
第二种方式通过DllPlugin插件,避免打包时对不变的库重复构建提高构建速度。比如项目中引入的react,react-dom
webpack 代码拆分
对于大型的 web 应用,如果我们把所有的东西都打包到一起是十分低效和不可接受的。需要把bundle拆分成若干个小的bundles/chunks。把大的文件拆分成小的文件分散进行加载,先加载更重要的文件以缩短首屏加载时间,可提升用户体验。第一种方式在entry中添加其他入口,这样工程就会被拆分成多个不同的 bundle。这种方式比较直接,但是需要手工去添加和维护。第二种方式通过 splitChunks 插件提取公有代码,拆分业务代码与第三方库。react 相关的单独提取;cra 的分包策略第一步把 webpack 运行时(runtimeChunks)的东西抽离出来,第二步就是把所有 react 相关的都给分离出来,他有个 chunks 写的是 all 是什么意思: initialChunk asyncChunk(异步 import 的那些东西,懒加载的那些)
webpack 持久缓存
w5:cache,w4:cache-loader
传输加载优化
启用 Gzip
Gzip 是用来进行网络资源压缩,减少资源文件在网络传输大小的技术
插曲:Compression-webpack-plugin 不要使用,前端这边不需要做 gzip,如果前端做了 gzip,服务端那边也把 gzip 打开,他去和浏览器商量,浏览器在请求头中会带上Accept-Encoding这个参数来说明自己支持哪些内容编码方式,服务端返回的Response Headers中则存在一个Content-Encoding,用来说明数据的压缩方法,问浏览器支不支持 gzip,浏览器说我不支持,那代码就不能用了;所以前端不需要做 gzip,只要把没做过 gzip 的代码送到去送到服务器或者 proxy,然后这个代理去和浏览器商量,gzip 这部分应该在 nginx 那边去做,或者在 cdn 或者 oss 这边去做,前端做会有协商失败的情况
启用Keep Alive
对TCP连接进行复用,http 1.1开始这个参数就是默认开启的
http 资源缓存
index.html 走强缓存 现在流行的方式是文件hash+强缓存的一个方案。比如hash+ cache control: max-age=1年。
css js 文件走强缓存或者协商缓存
http 1.0 没有实现 Cache-Control,需要写上 pragma
高阶
服务端渲染:在服务端完成页面插值/数据组装,直接返回包含有数据的页面
客户端渲染:客户端分别请求页面静态资源和接口数据,然后操作DOM赋值到页面。
.net、jsp 前后端不分离,直到 ajax 出现,客户端渲染就开始
https://zhuanlan.zhihu.com/p/...
SSR:
优点:
1.优秀的SEO
2.首屏加载快
缺点:
1.负载大:由于渲染任务都交由服务端进行,在高并发的情况下,对于服务端负载压力大。
2.复用性能差:因为返回的是整个页面,对于每个路由都要重新进行页面刷新,复用性能 上不友好。
3.前后端耦合严重,前端开发依赖于后端,开发形式上不友好。
传统CSR:
优点:
1.节省服务器性能。
2.局部刷新,无需每次都请求完整页面,体验更好。
3.前后端分离开发。
缺点:
1.由于页面显示过程要进行JS文件拉取和React代码执行,首屏加载时间会比较慢。
2.对于SEO(Search Engine Optimazition,即搜索引擎优化),完全无能为力,因为搜索引擎爬虫只认识html结构的内容,而不能识别JS代码内容。
同构渲染:
优点:兼顾前端渲染的大部分优点和后端渲染SEO和首屏加载的优点
缺点:1.需要额外的开发构建成本 2.对服务器有一定负载