Skip to content
On this page

性能优化

一个小问题:为什么script标签一般都放在body标签的后面呢?

在这里插入图片描述

从浏览器的渲染过程来看

  1. 解析 HTML 文件,构建 DOM 树,同时浏览器主进程负责下载 CSS 文件
  2. CSS 文件下载完成,解析 CSS 文件成树形的数据结构,然后结合 DOM 树合并成 RenderObject 树
  3. 布局 RenderObject 树 (Layout/reflow),负责 RenderObject 树中的元素的尺寸,位置等计算
  4. 绘制 RenderObject 树 (paint),绘制页面的像素信息
  5. 浏览器主进程将默认的图层和复合图层交给 GPU 进程,GPU 进程再将各个图层合成(composite),最后显示出页面

所以 只要会对渲染操作阻塞或减慢速度的操作,都是可以进行性能优化的一个方向

DOM 和 CSSOM 通常是并行构建的,所以 CSS 加载不会阻塞 DOM 的解析。JS是解释执行的,如果最开始就加载JS的文件,在遇到耗时较久的代码时,会阻塞页面的渲染。这也是为什么script标签一般都放在body标签的后面的原因,先让页面渲染后再执行JS。

根据页面渲染步骤来优化

进行渲染的时候,所有的图片/html文件等等,都是通过请求来的。 所以如果能够减少请求的次数,就是很好的一种优化方式。

  1. 减少http请求,可以通过以下(2、3)方式来减少http的请求的次数
  2. 多张图片合成一张,使用雪碧图。
  3. 合并CSS文件。

当然,如果请求的资源体积越小,请求的速度当然也越快。

  1. 资源压缩,减少体积

假如在一个页面中存在上万张图片。 如果在页面加载时一次性全部请求加载,页面会非常卡顿,这是不现实的。

  1. 懒加载

对于图片、音视频等资源可以在首次初始化界面时只加载当前视口内的资源或处于用户焦点中的那一部分资源,以提高页面渲染速度,从而使用户更轻松得到所需内容。

  1. 数据的分页处理

当页面都已经加载完成了。后续开始进行用户操作时。 当html元素的大小等发生改变时会触发回流的操作。即重渲染。 这是需要消耗内存的,所以我们需要避免对DOM的直接操作。(虚拟dom)

  1. 减少DOM操作

页面在渲染的时候,结合html生成的dom树和cssom树的render,除了减少dom的操作以外,当遇到css表达式时,也会浪费很多的资源。

  1. 避免使用CSS表达式

例如calc() 表达式的使用

安全方面来说,CSS 表达式可以让黑客通过 CSS 类型攻击实现注入代码、恶意重定向和其他攻击行为。例如,黑客可以通过 expression 属性将 Javascript 代码注入到页面中,然后执行具体的攻击行为。

而在性能方面,CSS 表达式是无法缓存的,每次重绘或重新计算时都需要重新计算一遍,因此会降低浏览器的渲染速度。

最后就是代码的层面。

  1. 代码质量优化

减少循环的次数,内存的合理使用和释放,声明合并,循环外提等。
比如实际开发中使用了window.addEventListener在页面销毁时要记得window.removeEventListener将对应绑定的事件清除,释放内存。

  1. 事件委托

还有一些用户可能会重复点击的地方,为了避免一直出发带来的性能问题。
频繁的用户操作就会让我们联想到 防抖和节流 的方法

  1. 防抖和节流

言简易懂: 防抖和节流

  1. 服务器渲染

采用服务端化模板渲染,最终生成的 HTML 内容直接发送给客户端,而不是像 SPA 应用那样,在页面加载后等待 JS 操作,从而大幅度减少页面初始化时间。

  1. Webpack 打包优化

对于 Webpack 插件的使用和配置能够对项目打包过程中占用资源和完成打包时间产生重要影响,如代码分离,懒汉加载、多线程编译、自动预编译等等。

实际做过什么前端项目的优化

  1. 合并icon图标的图片,使用雪碧图,减少请求的次数。

  2. 引入iconfont,也是解决问题1的另一种方法。

  3. 使用SVG。

  4. 压缩图片

  5. 图片的懒加载

  6. 数据的分页展示

  7. 缓存

  8. 异步处理

  9. 防抖节流

  10. 事件委托

  11. 公共组件封装

  12. webpack打包大小优化