性能优化

浏览器 lighthouse

  1. 打包优化
    • webpack-loader,dll,happypack,压缩代码,tree shaking,scope hoisting,code splitting
    • 图片basee64,cdn
  2. 网络优化
    • DNS,CDN,缓存,preload/prefetch/懒加载,ssr
  3. 代码优化
    • loading/骨架屏,web worker,虚拟列表,懒加载,dom/style批量更新。。。

初始阶段 -> 加载优化

  1. 首页加载慢的优化
    • 对于图片可以懒加载,减少首屏图片加载量。以及对于小图标和小图片分别使用 iconfont 和雪碧图来解决,最大程度减少首屏图片数量,从而提升首页渲染性能
    • 对于其他资源可以通过打包(nginx combo 或者 webpack 打包)来合并资源,并可以通过懒加载路由的方式来减少首页 JS 的加载量
    • 减小资源的方式可以通过压缩和混淆加密来减小文件体积,图片则可以使用工具压缩或者使用 webp 格式
    • 同时可在服务器端开启 gzip 压缩来最大化减少所有文件体积
  2. 优化图片的做法
    • 可以通过懒加载减少图片的请求,或者通过雪碧图来合并图片,以及将小图片转化成 base64 的格式,来解决多的问题
    • 图片大的问题,可以通过自动化压缩工具来压缩图片,或者使用 webp 格式的图片
  3. 实现 webpack 打包优化
    • 可以通过设置 mode=production 来默认实现 webpack 对代码的混淆和压缩,从而最大程度的减少代码体积
    • 使用 webpack + dynamic import 并结合路由的入口文件做拆包处理
    • 并且可以设定一些打包策略,并配合网络缓存做最终的加载性能优化
  4. 实现 CDN 加速
    • CDN 服务器主要是用来放静态资源的服务器,可以用来加速静态资源的下载
    • CDN 之所以能够加速,是因为会在很多地方都部署 CDN 服务器,如果用户需要下载静态资源,会自动选择最近的节点下载
    • 同时由于 CDN 服务器的地址一般都跟主服务器的地址不同,所以可以破除浏览器对同一个域名发送请求的限制

运行阶段 -> 渲染优化

  1. 渲染十万条数据如何不卡顿
    • 可以使用 document.createDocumentFragment 创建虚拟节点,从而避免引起没有必要的渲染
    • 当所有的 li 都创建完毕后,一次性把虚拟节点里的 li 标签全部渲染出来
    • 可以采取分段渲染的方式,比如一次只渲染一屏的数据
    • 最后使用 window.requestAnimationFrame 来逐帧渲染

网站性能优化可以从按几个维度或者方面进行优化?

  1. 减少HTTP请求的数量:因为三次握手,浏览器请求资源文件的限制
  2. 控制资源文件的加载优先级:css放在头部,js放在尾部
  3. 利用浏览器缓存:

打包依赖图

插件 webpack-bundle-analyzer

如何计算白屏时间和首屏渲染时间?如何优化

如果页面出现白屏如何排查

CDN 的原理,CDN 选择最近的缓存服务器是怎么实现

nginx 对前端的性能优化

当面试问前端性能优化的时候,大多数是 nginx 优化,而 nginx 又不属于前端的东西,面试官想要你说开启 gzip、开启 etag,却又说他们不考后台的知识

一、开启 gzip

查看有哪些大文件:

  • 方式一:可以在控制台网络 network 文件列显示大小查看
  • 方式二:npm 自带分析工具,可以查看打包依赖大小
npm run analyze
  • stat: 转换前的体积
  • Parsed: 最终打包体积
  • Gzipped: 使用gzip压缩后的体积

开启 gzip

开启gzip需要前端和服务器同时配合开启才会生效。

查看是否开启 gzip

  • 服务器: 打开控制台查看响应头 Content-Encoding: gzip 即为开启
  • 前端: build 打包后的文件是否有 .gz 文件

1. 前端打包生成 gz 文件

// 安装插件 `compression-webpack-plugin`
npm i -D compression-webpack-plugin
// OR
yarn add -D compression-webpack-plugin
const CompressionPlugin = require("compression-webpack-plugin");

// 压缩项配置
const gzipConfig = new CompressionPlugin({
   algorithm: 'gzip', // 默认 gzip。压缩算法
   threshold: 10240, // 默认 0。10kb以上的文件才进行压缩
   test: /\.(js|css|json|txt|html|svg)(\?.*)?$/i, // 正则匹配的文件才压缩
   minRatio: 0.6, // 默认 0.8。最小压缩比,小于则不压缩
   // filename: '[path][query].gz', // 默认 "[path][base].gz"。压缩文件名
}),

// webpack.config.js
module.exports = {
  configureWebpack: (config) => {
    if (process.env.NODE_ENV === "production") {
      return {
        plugins: [gzipConfig],
      };
    }
  },
};

// config.js - antd pro
export default config({
  ...,
  chainWebpack: (config) => {
    if (process.env.NODE_ENV === 'production') {
      config.plugin('compression-webpack-plugin').use(gzipConfig);
    }
  },
})
遇到的问题

TypeError: Cannot read property 'tapPromise' of undefined

原因是版本问题。降低版本重新运行即可

默认安装的是最新版本:

  • compression-webpack-plugin: "^10.0.0"
  • webpack: "^5.72.1"

而项目中用umi创建的webpack版本号是4.43.0,在 Github 上查找匹配低版本的是 5.0.2,故安装此版本即可

yarn add -D compression-webpack-plugin@5.0.2

2. 服务器配置 nginx,支持 gzip

生成 gz 文件后,还需要 nginx 支持

location / {
   root e:\workgit\abc;
   error_page 405 =200 http://$host:8085/$request_uri;

   gzip on;
   gzip_static on;
   gzip_http_version 1.1;
   gzip_comp_level 3;
   gzip_types text/plain application/json application/x-javascript application/css application/xml application/xml+rss text/javascript application/x-httpd-php image/jpeg image/gif 
   
   image/png image/x-ms-bmp;
   index  index.html index.htm;
   try_files $uri $uri/ @rewrites;
}

location @rewrites {
   rewrite ^(.*)$ /index.html last;
}

Ant Design Pro V5 nginx.conf:

{
   # gzip config
   gzip on;
   gzip_min_length 1k;
   gzip_comp_level 9;
   gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;
   gzip_vary on;
   gzip_disable "MSIE [1-6]\.";
}

二、开启 Etag

Etag 全称 EntityTags

Etag

Expires(HTTP/1.0)/Cache-Control(HTTP/1.1) Header 是控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。

只是 Cache-Control 比 Expires 可以控制的多一些, 而且 Cache-Control 会重写 Expires 的规则。

Last-Modified/If-Modified-Since 和 ETag/If-None-Match 是浏览器发送请求到服务器后判断文件是否已经修改过,如果没有修改过就只发送一个 304 回给浏览器,告诉浏览器直接从自己本地的缓存取数据;如果修改过那就整个数据重新发给浏览器。

三、项目中使用到的icon是如何处理的?

  1. 本地图标(雪碧图): 放大失真、需要计算图标位置、只能做背景图
  2. iconfont 字体图标:矢量图放大不会失真、第三方支持丰富
  3. svg 图标:可以直接替代img使用

有个长列表上万行,怎么做优化?

懒加载或者虚拟滚动

图片资源怎么做优化?

压缩、雪碧图、svg、base64、iconfont

首屏图片优先加载,等首屏图片加载完全后再去加载非首屏图片。 对大部分图片,特别是轮播广告中的图片进行按设备尺寸裁剪,减少图片体积,减少网络开销,加快下载速率。

上次更新:
Contributors: jiangjingmin, jingmin.jiang, kyxiao