静态资源开启强缓存和 gzip/br 压缩

3,893 阅读2分钟

本文讨论在私有化需求场景下, Node.js 服务如何压缩静态资源,并开启强缓存。CDN 场景需和 CDN 厂商沟通,不在本文范围内。

同时支持 gzip/br 压缩

因为 br 存在兼容性问题,具体可参考:Can I Use Brotli。如果项目的目标浏览器都支持 Brotli,则可以不支持 gzip 压缩。

静态压缩(推荐)

静态压缩是在构建时生成 gzip 和 br 文件。

优点是:

  1. 服务端运行时可快速响应压缩文件。
  2. 相比于动态压缩,可以配置更高的压缩级别。

缺点是:会增加构建时间和资源上传时间。

配置 webpack 构建时生成 gzip/br 文件

在 webpack 中增加两个插件,一个用于生成 gzip,一个用于生成 brotli。具体参数可参考 CompressionWebpackPlugin

new CompressionPlugin({
  filename: '[path][base].gz',
  algorithm: 'gzip',
  test: /\.js$|\.css$|\.html$/,
  threshold: 10240,
  minRatio: 0.8,
})

new CompressionPlugin({
  filename: '[path][base].br',
  algorithm: 'brotliCompress',
  test: /\.(js|css|html|svg)$/,
  compressionOptions: {
    params: {
      [zlib.constants.BROTLI_PARAM_QUALITY]: 11,
    },
  },
  threshold: 10240,
  minRatio: 0.8,
})

服务端 express-static-gzip 根据 Accept-Encoding 自动降级

由于 express-static-gzip 是基于 express.static() 开发的,所以支持 express.static() 的所有功能。但其增加的额外功能有两点:

  1. 可以根据 Accept-Encoding 请求头解析不同的压缩文件并响应。
  2. 解析压缩文件时有优先级顺序,brotli > gzip > raw,支持自动降级解析。

代码也很简单,如下所示。

expressStaticGzip(StaticDir, {
  enableBrotli: true,
  orderPreference: ['br'],
  serveStatic: {
    maxAge: '30 days', // 开启强缓存 30 天
  }
});

动态压缩(不推荐)

动态压缩是指服务在响应静态资源的时候,服务端对静态资源进行实时压缩返回。优缺点和静态压缩相反。

使用的三方包为 shrink-ray。使用也很简单,只需要一行代码,其内部已经对 Accept-Encoding 和 MIME 类型进行检查。

app.use(shrinkRay());

使用 brotli 压缩的前提条件

在 Chrome 中只有 https 的网站发起的请求头 Accept-Encoding 中才会加上 br 选项,此时服务端才会响应 brotli 压缩的资源。因此只有网站支持 https 时,开启 br 压缩才有价值。