首页 > 解决方案 > 如何获取加载在 HTML 脚本标签中的静态文件的 gzip 压缩响应

问题描述

我正在 App Engine 上开发 Web 应用程序(nodejs10 作为运行时,Node 作为服务器,React 作为前端)。

为了让 Lighthouse 获得更好的性能,我尝试将每个响应压缩到 gzip 中。目前 gzip 压缩适用于 API 响应,但不适用于脚本标签。

在 server.js 中,我引入了压缩模块,并且有效。每个内部 api 调用响应都被压缩。

import compression from 'compression';

.
.

app.use(
  compression({
    threshold: 1,
    level: 9,
    memLevel: 1,
  }),
);

.
.

Gzip 文件是本地生成的,与原始 Javascript 文件位于同一位置。这是在 webpack.config.js 中。

new CompressionPlugin({
  test: /\.(css)|(js)$/,
  compressionOptions: {
    level: 9,
  },
}),

在 html 中,我正在尝试加载前端文件。我想 App Engine 会处理剩下的内容,如果内容可以根据accepting-encodingand编码或不编码user-agent

这就是问题所在。每个静态文件都保持解压缩状态。

<body>
  <script type="text/javascript" src="/assets/client.js" charSet="utf-8" />
  <script type="text/javascript" src="/assets/vendors.chunk.js" charSet="utf-8" />
</body>

请求标头

:authority: myApplicaation
:method: GET
:path: /assets/client.js
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: ja,en-US;q=0.9,en;q=0.8
cache-control: no-cache
cookie: _ga=GA1.2.1338918906.1558605919; __stripe_mid=1091f2c2-d01d-4386-871b-ee420a840bd5; _gcl_au=1.1.2059850586.1566453250; _gid=GA1.2.969451871.1566667214; connect.sid=s%3AIINmpsd-30ad8TF5z7oCBDo4h1jIxgRQ.XxT3L7%2F8H2tVcS4COIrpy7SxCp746FnIKNjthLW1P8Q; __stripe_sid=edda0dd4-1fbf-4da9-bcdc-9dccab9bdf4e; _gat_UA-125249076-1=1
pragma: no-cache
referer: https://tripper.world/
sec-fetch-mode: no-cors
sec-fetch-site: same-origin
user-agent: Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1

响应标头

accept-ranges: bytes
age: 371502
cache-control: public, max-age=5184000
content-length: 1417405
content-type: application/javascript; charset=UTF-8
date: Sat, 24 Aug 2019 03:47:28 GMT
etag: W/"15a0bd-16cb7e22578"
last-modified: Thu, 22 Aug 2019 05:52:27 GMT
server: Google Frontend
status: 200
x-cloud-trace-context: 6304083a50ed3fa42285e3e229af07a8
x-powered-by: Express

有什么方法可以压缩静态文件吗?如果我的任何假设是错误的,请指出。

我提前感谢您的帮助,谢谢。

**********附加信息**********

静态文件通过 express static 提供。

app.use(
  express.static(path.resolve(__dirname, 'public'), {
    maxAge: '60d',
  }),
);

app.standard.yaml

runtime: nodejs10
instance_class: F2
automatic_scaling:
  target_cpu_utilization: 0.65
  min_instances: 0
  max_instances: 1
beta_settings:
 cloud_sql_instances: 'xxxxxx-xxxxxx:asia-northeast1:xxxxxx-postgres'
handlers:
- url: /.*
  script: auto

标签: google-app-enginebrowsergzip

解决方案


在您的 Express 应用程序中尝试类似(我尚未测试):

const path = require('path')

const setStaticHeaders = (res, assetPath) => {
  const assetExtension = path.extname(assetPath);
  // Only apply to assets Webpack compressed
  if (['.js', '.css'].includes(assetExtension)) {
    res.setHeader('Content-Encoding', 'gzip');
  }
}
app.use(
  express.static(path.resolve(__dirname, 'public'), {
    maxAge: '60d',
    setHeaders: setStaticHeaders
  }),
);

Webpack 正在压缩您的资产,但未设置正确的响应标头。您还只想将该标头应用于 Webpack Gzip 压缩的实际资产,以防资产文件夹中有其他未压缩的资产(可能没有)。

看起来 App Engine 会自动为您 GZip 静态资产。因此,您还可以删除 Webpack 配置中的 GZip 并仅使用 App Engine 提供文件


推荐阅读