taruya
taruya

Reputation: 21

How to get gzip compressed response of static files which is loaded in HTML script tag

I'm developing web application on App Engine(nodejs10 as runtime, Node as server, and React as frontend).

For better performance indicated by Lighthouse, I am trying to make every response compressed in gzip. Currently gzip compression worked for API response, but does not for script tag.

In server.js, I've introduced compression module, and that worked. Every internal api call response is gzipped.

import compression from 'compression';

.
.

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

.
.

Gzip file is locally generated and located in same place as raw Javascript files. Here's in webpack.config.js.

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

In html, I'm trying to load frontend files. I suppose App Engine handles the rest if content can be encoded or not according to accepting-encoding and user-agent.

Here's the problem. Every static files remain unzipped.

<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>

Request headers

: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

Response headers

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

Is there any way to make static files gzipped? If my any assumption are wrong, please point them out.

I appreciate your helps in advance, Thanks.

**********Additional information**********

static file's served via 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

Upvotes: 1

Views: 2807

Answers (2)

Alex
Alex

Reputation: 5276

Try serving your static assets via GAE's static_dir handler in app.yaml

handlers:
- url: /assets
  static_dir: path/to/assets/folder
- url: /.*
  script: auto

and google should automatically gzip it based on the request headers it receives

Upvotes: 0

ryanm
ryanm

Reputation: 724

Try in your Express application something like (I haven't tested):

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 is GZipping your assets but not setting the correct response header. You also only want to apply that header for the actual assets that Webpack Gzipped, in case there are other non-compressed assets in your assets folder (which there might not be).

It looks like App Engine will automatically GZip static assets for you. So you could also remove the GZip in the Webpack config and just serve the files using App Engine.

Upvotes: 1

Related Questions