谈谈前端优化

一、优化的原则和方向
1.1 前端性能优化的原则其实就是更好的用户体验,具体实现的目标大体有两个:
  • 合理使用内存或缓存,减少请求;
  • 减少 CPU 或 GPU 的计算,达到更快的展现。
1.2 前端在性能优化的方向大致有两个:
  • 减少页面体积,提升网络加载;
  • 优化页面渲染
二、方向详情
2.1 较少页面体积,提升网络加载
  • 静态资源的压缩合并(JS 代码压缩合并、 CSS 代码压缩合并、雪碧图)
    • i. 压缩是为了减小文件的体积,减轻网络负载,达到更快的下载;
    • ii. 合并和雪碧图都是为了减少文件的请求次数,但不是合并的就一定比没有合并时加载快,要考虑合并之后的体积,若文件合并之后太大也不利于性能优化,所以在实际项目中要做好权衡。
  • 静态资源缓存(资源名称加 MD5 戳)
    • i. 可以通过链接名称控制缓存: 通过前端构建工具为打包的文件添加 MD5 后缀,这样当打包上线时请求的链接将发生改变,可以防止由于缓存导致静态资源更新失效;
  • 使用 CDN 让资源加载更快
2.2 优化页面渲染
  • CSS 放在头部, JS 放后面
    • 浏览器在渲染解析过程中,若遇到 <link href="..."><script src="..."> 这种外链加载 CSS 和 JS 的标签,浏览器会异步下载并解析执行。 CSS 放在头部是为了让浏览器今早解析执行 CSS 文件,渲染出页面的样式,若放在底部会出现渲染卡顿的情况,影响性能和体验。
    • 而当渲染过程中遇到 script 标签时就会执行 JS 代码,从而阻塞页面渲染,因为浏览器渲染和 JS 执行共用一个县城,而且这里必须是单线程操作,多线程会产生渲染 DOM 冲突。所以要将 JS 放在底部,等到页面渲染完成之后再去解析执行 JS,保证用户体验性。
    • 另外,JS 执行如果涉及 DOM 操作,得等待 DOM 解析完成才行,JS 放在底部执行是,HTML 肯定都解析成了 DOM 结构。 JS 如果放在 HTML 顶部,JS 执行的实行 HTML 还没来得及转换为 DOM 结构,可能会引起报错。
  • 懒加载(图片来加载、下拉加载更多)

    • i. 先将 src 赋值成一个通用的浏览图,下拉的时候再动态赋值成正式的图片。通用的预览图可以是体积比较小的,这样加载会很快,待页面下拉,图片显示出来时,再去替换 srcdata-src 的值。( data- 开头的属性浏览器渲染的时候会忽略掉,提高渲染性能)
      <img src="preview.png" data-src="realImg.png" />
  • 减少 DOM 查询,对 DOM 查询做缓存,代码如下:

    // 只查询一个DOM,缓存在 pList 中了
    var pList = document.getElementsByTagName('p');
    for(var i = 0; i < pList.length; i++){
    }
    //每次循环,都会查询 DOM,耗费性能
    for(var i = 0; i < document.getElementsByTagName('p').length; i++){
    }
  • 减少 DOM 操作,多个操作尽量合并在一起执行 (DocumentFragment)

    • DOM 操作是非常耗费性能的,因此插入多个标签时,先插入 Fragment 然后再统一插入 DOM。因为 Fragment 文档片段存在于内存中,并不在 DOM 树中,所以将子元素插入到文档片段时不会引起页面回流。
  • 事件节流

    • i. 防抖
    • ii. 节流
  • 尽早执行操作

    window.addEventListener('load', function(){
      // 页面的全部资源加载完才会执行,包括图片、视频等
    })
    document.addEventListener('DOMContentLoaded', function(){
      // DOM 渲染完成即可执行,此时图片、视频等资源可能没有加载完成
    })
    $(document).ready(function(){
      // 同 DOMContentLoaded
    })
  • 使用 预渲染 或者 SSR服务端渲染,数据直接输出到 HTML中,减少浏览器使用 JS 模板渲染页面 HTML 的时间,同时也有利于网站的 SEO