嗨,送你一张Web性能优化地图

Link: ; rel=preload; as=style

4.6 快速响应的用户界面

PSI(Perceptual Speed Index,感知速度指数)是提升用户体验的重要指标,让用户感觉到页面的反馈比没有反馈体验要好很多。

可以尝试使用骨架屏或添加一些Loading过渡动画提示用户体验。

输入响应(Input responsiveness)指标同样重要,甚至更重要。试想,用户点击了网页后缺毫无反应会是什么心情。JS的单线程大家已经不能再熟悉,这意味着当JS在运行时用户界面处于“锁定”状态,所以JS同步执行的时间越长,用户等待响应的时间也就越长。

据调查,JS执行100毫秒以上用户就会明显觉得网页变卡了。所以要严格限制每个JS任务执行时间不能超过100毫秒。

解决方案是可以将一个大任务拆分成多个小任务分布在不同的Macrotask中执行(通俗的说是将大的JS任务拆分成多个小任务异步执行)。或者使用WebWorkers,它可以在UI线程外执行JS代码运算,不会阻塞UI线程,所以不会影响用户体验。

应用越复杂,主动管理UI线程就越重要

5. 构建优化

现代前端应用都需要有构建的过程,项目在构建过程中是否进行了合理的优化,会对Web应用的性能有着巨大的影响。例如:影响构建后文件的体积、代码执行效率、文件加载时间、首次有效绘制指标等。

5.1 使用预编译

拿Vue举例,如果您使用单文件组件开发项目,组件会在编译阶段将模板编译为渲染函数。最终代码被执行时可以直接执行渲染函数进行渲染。而如果您没有使用单文件组件预编译代码,而是在网页中引入vue.min.js,那么应用在运行时需要先将模板编译成渲染函数,然后再执行渲染函数进行渲染。相比预编译,多了模板编译的步骤,所以会浪费很多性能。

5.2 使用 Tree-shaking、Scope hoisting、Code-splitting

Tree-shaking是一种在构建过程中清除无用代码的技术。使用Tree-shaking可以减少构建后文件的体积。

目前Webpack与Rollup都支持Scope Hoisting。它们可以检查import链,并尽可能的将散乱的模块放到一个函数中,前提是不能造成代码冗余。所以只有被引用了一次的模块才会被合并。使用Scope Hoisting可以让代码体积更小并且可以降低代码在运行时的内存开销,同时它的运行速度更快。前面2.1节介绍了变量从局部作用域到全局作用域的搜索过程越长执行速度越慢,Scope Hoisting可以减少搜索时间。

code-splitting是Webpack中最引人注目的特性之一。此特性能够把代码分离到不同的bundle中,然后可以按需加载或并行加载这些文件。code-splitting可以用于获取更小的bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。

5.3 服务端渲染(SSR)

单页应用需要等JS加载完毕后在前端渲染页面,也就是说在JS加载完毕并开始执行渲染操作前的这段时间里浏览器会产生白屏。

服务端渲染(Server Side Render,简称SSR)的意义在于弥补主要内容在前端渲染的成本,减少白屏时间,提升首次有效绘制的速度。可以使用服务端渲染来获得更快的首次有效绘制。

比较推荐的做法是:使用服务端渲染静态HTML来获得更快的首次有效绘制,一旦JavaScript加载完毕再将页面接管下来。

5.4 使用import函数动态导入模块

使用import函数可以在运行时动态地加载ES2015模块,从而实现按需加载的需求。

这种优化在单页应用中变得尤为重要,在切换路由的时候动态导入当前路由所需的模块,会避免加载冗余的模块(试想如果在首次加载页面时一次性把整个站点所需要的所有模块都同时加载下来会加载多少非必须的JS,应该尽可能的让加载的JS更小,只在首屏加载需要的JS)。

使用静态import导入初始依赖模块。其他情况下使用动态import按需加载依赖

5.5 使用HTTP缓存头

正确设置expires,cache-control和其他HTTP缓存头。

推荐使用Cache-control: immutable避免重新验证。

6. 其他

其他一些值得考虑的优化点:

  • HTTP2使用最高级的CDN(付费的比免费的强的多)优化字体其他垂直领域的性能优化

7. 性能监控

最后,你可能需要一个性能检测工具来持续监视网站的性能。

8. 总结

最后用一张图来总结这篇文章所表达的内容,感谢@anjia帮忙画的这张图。

嗨,送你一张Web性能优化地图


分享到:


相關文章: