Skip to content

Latest commit

 

History

History
90 lines (81 loc) · 5.22 KB

前端性能优化.md

File metadata and controls

90 lines (81 loc) · 5.22 KB

前端性能优化

前端性能优化主要有如下几块

  • 代码执行效率的优化,极致追求js执行效率意义不大,重点注意下内存泄漏等问题,此块不展开
  • 界面渲染的优化,一般后端不会一次返回大量的数据给到前端渲染,都会有分批分页加载,此块不展开
  • 网络请求优化,本文主要讨论这一块,主要有如下手段:
    • 减少http请求
      • icon等多个小图片加载用雪碧图只用请求一次,不过现在一般用webpack打包,这些小图片都通过url-loader工具打包成了base64在代码里,所以此处不再展开
      • js css等静态资源合并打包,现在webpack打包都是这样做的,所以此处不再展开
      • 合并后端接口,由于后端接口一般要遵循单一职责原则(一个接口做一件事),所以不能随便合并,所以此处不再展开
    • 减少每个http请求的大小
      • 减少图片的体积,此处主要是和UI沟通,此处不再展开
      • js css等静态资源的压缩,例如用webpack插件new webpack.optimize.UglifyJsPlugin({ minimize: true })
      • 开启gizp压缩,linux服务器上打开nginx配置文件/usr/local/nginx/conf/nginx.conf,写入gzip on;
      • js中用体积小的库替代同样功能的体积大的库,例如用只有几k的dayjs库替换有几百k的moment库完成日期处理功能,可以用webpack插件new BundleAnalyzerPlugin({ analyzerPort: 3011 })查看每个库占用的体积。
      • webpack打包优化,如下展开讨论
      • 静态资源的缓存,如下展开讨论
    • 进入页面前加loading降低加载感知,此处不展开
    • 需要的才加载比如路由懒加载,参考xxx

webpack打包优化

entry配置vendor包

// webpack.base.config.js
entry: {
  // 很少变化的大体积库打包成vendor.js
  vendor: ['react', 'react-dom', 'antd', 'babel-polyfill'],
  ...
},

plugins配置CommonsChunkPlugin

// webpack.base.config.js
plugins: [
  ...
  // 抽取chunk vendor.js
  new webpack.optimize.CommonsChunkPlugin({
    names: ['vendor']
  }),
  // 每次打包 vendor.js中变化的部分抽取为manifest.js
  new webpack.optimize.CommonsChunkPlugin({
    name: 'manifest',
    chunks: ['vendor']
  })
  ...
]

打包的filename必须用chunkhash

// webpack.base.prod.js
output: {
  // 必须用chunkhash 否则vendor每次打包后hash都会变化就无法缓存了
  filename: '[name].[chunkhash].js',
  ...
},

这样每次打包机会出现三个文件

  • main.hashxxx.js: 主文件,一般几百K
  • vendor.hashxxx.js: 一般1-2M,output filename用的chunkhash,所以这个文件的hashxxx永远不会变化,然后设置一个长的max-age缓存,之后就都是缓存加载了
  • mainfest.hashxxx.js: 一般几K,每次打包vendor中变化的部分抽取到这里来

这样每次打包完只请求几百K的main.hashxxx.js和几K的mainfest.hashxxx.js,而几M的vendor.hashxxx.js都走的是缓存。 关于CommonsChunkPlugin需要用chunkhash具体参考https://www.jb51.net/article/131865.htm

静态资源的缓存

详情参考https://www.jianshu.com/p/54cc04190252 主要有如下四类缓存,优先级从高到低。

  • Service Worker:PWD的内容,还不普及暂不讨论
  • Memory Cache:内存缓存,返回200 OK (from memory cache),浏览器会自动设置并自动处理是否失效,一般不用设置
  • Disk Cache:硬盘缓存,主要通过设置http头实现,分为强缓存和协商缓存两种,如下展开讨论
  • Push Cache:HTTP2的内容,还不普及暂不讨论

强缓存

不会向服务器发送请求,直接从缓存中读取资源,返回200(from memory cache)或者200(from disk cache)
如果强缓存失效再进行下一步的协商缓存。
强缓存可以通过设置两种HTTP Header实现:HTTP/1的Expires,HTTP/1.1的Cache-Control,现在一般用Cache-Control。
Cache-Control部分字段如下:

  • max-age:max-age=xxx 表示缓存内容将在xxx秒后失效。
  • no-cache 跳过强缓存,直接进入协商缓存。
  • no-store 所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存。

Cache-Control的具体设置自行搜索nginx Cache-Control设置

协商缓存

强缓存失效后进入协商缓存,发起http请求,如果生效返回304(Not Modified)(304只返回请求头不返回body,body从缓存读取)。
协商缓存可以通过设置两种HTTP Header实现:HTTP/1的Last-Modified,HTTP/1.1的ETag,现在一般用ETag。
Etag机制:服务器响应请求时,response header返回当前资源Etag(由服务器生成的一个唯一标识,如果资源有变化,Etag就会重新生成)。浏览器在下一次请求资源的时候会将此资源上一次返回的Etag放到request header里的If-None-Match里。服务器比较客户端传来的If-None-Match跟服务器上该资源的ETag是否一致,从而判断该资源相对客户端而言是否被修改过了。如果服务器发现ETag匹配不上,那么返回200将新的资源(当然也包括了新的ETag)发给客户端。如果ETag是一致的,则直接返回304(Not Modified)
Etag的具体设置自行搜索nginx Etag设置