Skip to content

Allow sirv to looks for precompiled gzip and brotli files by default - #1672

Merged
benmccann merged 2 commits into
sveltejs:masterfrom
realadvisor:master
Jun 11, 2021
Merged

Allow sirv to looks for precompiled gzip and brotli files by default#1672
benmccann merged 2 commits into
sveltejs:masterfrom
realadvisor:master

Conversation

@istarkov

@istarkov istarkov commented Jun 11, 2021

Copy link
Copy Markdown
Contributor

This should not change anyting for users who doesnt use brotli or gzip precompiled asset files. But brotli gives real advantages over gzip in compression size.

In absense of sirv config, probably it can be a good default.

For compressing we use following script.

import * as zlib from 'zlib';
import { pipeline } from 'stream';
import { promisify } from 'util';

import * as fs from 'fs';
import { totalist } from 'totalist/sync/index.js';
import yargs from 'yargs';

const supportedAlgs = ['gz', 'br'];

const argv = yargs(process.argv.slice(2))
  .describe('alg', 'Compression algorithm gz or br')
  .choices('alg', supportedAlgs)
  .describe('dir', 'Directory to compress files')
  .string('dir')
  .array('ext')
  .default('ext', ['js', 'css', 'json', 'svg'])
  .demandOption(['alg', 'dir'], 'alg and dir must be provided')
  .check(argv => {
    if (!fs.statSync(argv.dir).isDirectory()) {
      throw new Error(`"${argv.dir}" is not directory`);
    }

    return true; // tell Yargs that the arguments passed the check
  })
  .example([
    ['$0 --alg br --dir .build/assets', 'Use brotli compression'],
    ['$0 --alg gz --dir .build/assets', 'Use gz compression'],
    [
      '$0 --alg gz --dir .build/assets --ext css json',
      'Use gz compression for files with css and json extensions',
    ],
  ]).argv;

const files: string[] = [];

if (!('dir' in argv)) {
  throw new Error('argv is a promise');
}

totalist(argv.dir, (_, abs) => {
  files.push(abs);
});

const pipe = promisify(pipeline);

const compress = async () => {
  const sizes = [];
  for (const file of files) {
    if (
      argv.ext.some(ext => file.endsWith(`.${ext}`)) &&
      !supportedAlgs.some(alg => file.endsWith(`.${alg}`))
    ) {
      const destFile = `${file}.${argv.alg}`;
      const compressionMethod =
        argv.alg === 'gz' ? zlib.createGzip() : zlib.createBrotliCompress();
      const source = fs.createReadStream(file);
      const destination = fs.createWriteStream(destFile);
      await pipe(source, compressionMethod, destination);
      const inSize = Math.round((100 * fs.statSync(file).size) / 1024) / 100;
      const outSize =
        Math.round((100 * fs.statSync(destFile).size) / 1024) / 100;

      sizes.push({ inSize, outSize, file });
    }
  }

  console.table(sizes);
};

compress().then(() => null);

@benmccann
benmccann requested a review from lukeed June 11, 2021 15:24

@lukeed lukeed left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically this means sirv is doing more checks on every request (< 1ms) but that's totally fine 😆 If this part of the app were ever to be exposed to the config layer, it'd be a good thing to expose (with some forced SK overrides)

@benmccann

Copy link
Copy Markdown
Member

@istarkov can you add a patch changeset so that this PR can be merged and released? (pnpx changeset)

@benmccann

benmccann commented Jun 11, 2021

Copy link
Copy Markdown
Member

I'm curious if there's any Vite or Rollup plugin that you could use rather than a custom script

@istarkov

Copy link
Copy Markdown
Contributor Author

I'm curious if there's any Vite or Rollup plugin that you could use rather than a custom script

Yes some plugins exists https://www.npmjs.com/package/rollup-plugin-brotli and same for gzip,
custom script just allows to use it not only for build assets and for other things too.

@benmccann
benmccann merged commit 9a7195b into sveltejs:master Jun 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants