性能优化实践

173 阅读3分钟

导读

网页性能优化建议:升级到 http2 协议、gizp 压缩、强缓存。

升级到 http2 协议

http2 相对 http1.1 有以下几个优势

  1. 多路复用:允许同时通过单一的 HTTP/2 连接发起多重的请求-响应消息,合并多个请求为一个的优化将不再适用。
  2. 首部压缩:移除了请求中的一些啰嗦首部,你可以通过很少的 IP package,承载数十个乃至上百个的请求,更符合最小数据量的理想化原则。
  3. 服务端推送:服务器可以向客户端推送所需要的资源,避免不必要的 Round Trips。
  4. 新的二进制格式(Binary Format),HTTP1.x 的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多。基于这种考虑 HTTP2.0 的协议解析决定在 应用层(HTTP/2)和传输层(TCP or UDP)之间采用二进制格式,实现方便且健壮。在 应用层(HTTP/2)和传输层(TCP or UDP)之间。
import spdy from "spdy";
spdy
  .createServer(
    {
      key: fs.readFileSync("./privkey.pem"),
      cert: fs.readFileSync("./fullchain.pem"),
      spdy: {
        protocols: ["h2"],
      },
    },
    app
  )
  .listen(3100);

http2 目前主流浏览器都需要 ssl 证书,推荐一个在线 https 证书申请网站

gzip 压缩

需要发送header中带Accept-Encoding: gzip,deflate的请求

客户端

webpack 配置

const CompressionPlugin = require('compression-webpack-plugin')
// config
plugins: [
   // gzip
   new CompressionPlugin({
     algorithm: 'gzip',
     threshold: 10240,
     minRatio: 0.8
   })
 ]

vite 配置

import viteCompression from "vite-plugin-compression";
// config
plugins: [

    viteCompression({
      verbose: true,
      disable: false,
      threshold: 10240,
      algorithm: "gzip",
      ext: ".gz",
    }),
  ],

服务端

tomcat 中修改${TOMCAT_HOME}/conf/server.xml

<Connector port="8080" protocol="HTTP/1.1"
   connectionTimeout="20000"
   redirectPort="8443"
   compression="on" //开启
   compressionMinSize="2048" // 进行压缩的最小值,低于该值的文件不进行压缩(单位B,默认2048,即默认2k)
   noCompressionUserAgents="gozilla,traviata"//不需要进行压缩的浏览器,当浏览器类型为指定的类型时,不进行压缩
   compressableMimeType="text/css" />// 需要压缩的文件类型(多个类型以逗号分隔)

node 中配置

const compression = require('compression')
// 在其他中间件前使用
app.use(compression())

http 强缓存

webpack + express 实现文件精确缓存

客户端

webpack 配置

output: {
	filename: '[name].[contenthash].js',
    chunkFilename: '[name].[contenthash].js',
    path: path.resolve(__dirname, '../dist'),
},

vite 默认配置就行

服务端

express 配置

app.use((req, res, next) => { // 将 index.html 设为 no-cache
     if(~req.url.indexOf('html')) {
         res.setHeader('Cache-control', 'no-cache')
     }

     next()
 })

 app.use(express.static('dist', {
     etag: false,
     maxAge: 1000 * 60 * 60 * 24 * 365, // 缓存一年
 })) // 将dist设为根目录

tomcat 配置

<filter>
 <filter-name>ExpiresFilter</filter-name>
 <filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>
 <init-param>
    <param-name>ExpiresByType image</param-name>
    <param-value>access plus 10 days</param-value>
 </init-param>
 <init-param>
    <param-name>ExpiresByType text/css</param-name>
    <param-value>access plus 10 days</param-value>
 </init-param>
 <init-param>
    <param-name>ExpiresByType application/javascript</param-name>
    <param-value>access plus 10 days</param-value>
 </init-param>
</filter>

<filter-mapping>
 <filter-name>ExpiresFilter</filter-name>
 <url-pattern>/*</url-pattern>
 <dispatcher>REQUEST</dispatcher>
</filter-mapping>

按需打包

各种第三方库只有用到的组件或函数才打包,vite 打包时 elements-plus 按需加载如下:

import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
//vite.config.ts
plugins: [
    vue(),
    vueJsx(),
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
    viteCompression({
      verbose: true,
      disable: false,
      threshold: 10240,
      algorithm: "gzip",
      ext: ".gz",
    }),
  ],

这样就不需要再 main.ts 中引用 elements-plus 了,在.vue 单文件组件中 template 中可以直接用 el-form 等标签,不过在 script 中还需 import

懒加载

异步路由懒加载:

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    name: "Detail",
    component: Detail,
  },
  {
    path: "/Verify",
    name: "Verify",
    component: () => import("@/components/Verify.vue"),//只有访问/Verify时才加载该组件
  },
  {
    path: "/Success",
    name: "Success",
    component: () => import("@/components/Success.vue"),
  },
];

图片懒加载 进入可视范围才加载

判断一个元素是否在可视区域,我们常用的有三种办法:

  • offsetTop、scrollTop

  • getBoundingClientRect

  • Intersection Observer

分包

根据实际项目情况,一个文件一般不超过 500k。 vite 配置

build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vue: ["vue", "pinia", "vue-router"],
          lodash:["lodash"],
          echart:["echart"]
        },
      },
    },
  },