前端性能优化
分为以下类别
页面资源加载
- 源代码压缩,图片视频等等资源压缩,减小传输体积
- 小图片用base64,虽然会增加体积,但是易于维护。CSS Sprites不利于维护。
- 构建的时候同时生成一份gzip过的文件。
- 减少cookie的大小。
- 开启dns预解析<link rel='dns-prefetch href='//your.cdn.com'>
- 除html外的静态资源可以上传到cdn,html不放到cdn的原因是便于发版后快速看到效果。
- 浏览器一般会限制每个域的并行线程(一般为 6 个,甚至更少),使用不同的域名可以最大化下载线程。
- 
    利用浏览器缓存。 8.1 强缓存,在 web服务器返回的响应中添加Expires和Cache-ControlHeader。8.2 协商缓存,通过 Last-Modified,If-Modified-Since和ETag、If-None-Match这两对Header分别管理。
资源预加载
- 
    Preload <link rel="preload">,用来指定页面加载后很快会被用到的资源,所以在页面加载的过程中,我们希望在浏览器开始主体渲染之前尽早加载这些资源,针对当前界面。<!-- css 预加载--> <link href="xxx.css" rel="preload" as="style" /> <!-- js 预加载--> <link href="xxx.js" rel="preload" as="script" />
- 
    Prefetch <link rel="prefetch">,用来告诉浏览器在页面加载完成后,利用空闲时间提前获取用户未来可能会访问的内容,针对后一个界面。<!-- css 预加载--> <link href="xxx.css" rel="prefetch" as="style" /> <!-- js 预加载--> <link href="xxx.js" rel="prefetch" as="script" />
首屏渲染
- css放头部,- js放- body最后面。
- 只加载首屏渲染所用到静态资源,使用webpack的情况下就是code-splitting。
- 图片懒加载,监听滚动事件或者Intersection Observer
- 通过webpack构建生成两个版本:- 一个现代版的包(更小更快),面向支持 ES modules的现代浏览器。
- 另一个旧版的包,面向不支持的旧浏览器。
 
- 一个现代版的包(更小更快),面向支持 
- 使用prerender-spa-plugin来预渲染生成部分静态资源。
- 如有必要,采用服务器端渲染。
运行时优化
- 尽量不使用table布局。
- 减少 DOM操作次数。
- 避免空的src和href。
- 对高频触发的事件进行节流或防抖。
- 使用 transform和opacity来完成动画。
针对 vue 项目
- 尽量使用vue单文件组件开发。
- 不使用全局mixin。
- 引入的第三方插件,在组件destroy的时候记得插件也要相应destroy。
- 手动添加的事件等等同上。
- v-if和- v-show区分使用场景。
- v-for遍历避免同时使用- v-if。
- 数据不会发现变化,但是在模板又需要用到的时候,使用Object.freeze冻结,跳过vue响应式系统代理。
- 路由多的时候使用路由懒加载。
- 第三方插件的按需引入。
针对 React 项目
- 合理使用shouldComponentUpdate。
- 
    优化 props传递jsx harmony // bad function App() { return <Child data= />; } // good function App() { const data = useState({ xxx: [] }); return <Child data={data} />; }
- 优化bind,或者使用箭头函数声明方法
jsx harmony
// bad
class App extends React.Component {
  handClick() {}
  render() {
    return (
      <>
        <div onClick={this.handClick.bind(this)}></div>
        <div onClick={() => this.handClick()}></div>
      </>
    );
  }
}
// good
class App extends React.Component {
  constructor(props) {
    super(props);
    this.handClick = this.handClick.bind(this);
  }
  handClick() {}
  render() {
    return (
      <>
        <div onClick={this.handClick}></div>
      </>
    );
  }
}