1
0
forked from baron/baron-sso
Files
baron-sso/userfront/scripts/optimize-web-build.mjs

82 lines
2.3 KiB
JavaScript

import { brotliCompressSync, constants } from 'node:zlib';
import { createHash } from 'node:crypto';
import { existsSync, readFileSync, readdirSync, renameSync, writeFileSync } from 'node:fs';
import { basename, extname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const buildDir = process.argv[2] ?? join(__dirname, '..', 'build', 'web');
const bootstrapPath = join(buildDir, 'flutter_bootstrap.js');
const hashableEntrypoints = ['main.dart.js', 'main.dart.mjs', 'main.dart.wasm'];
const compressibleExtensions = new Set([
'.css',
'.html',
'.js',
'.json',
'.mjs',
'.svg',
'.toml',
'.wasm',
]);
if (!existsSync(bootstrapPath)) {
throw new Error(`Missing Flutter bootstrap file: ${bootstrapPath}`);
}
let bootstrap = readFileSync(bootstrapPath, 'utf8');
for (const entrypoint of hashableEntrypoints) {
const sourcePath = join(buildDir, entrypoint);
if (!existsSync(sourcePath)) {
continue;
}
const content = readFileSync(sourcePath);
const hash = createHash('sha256').update(content).digest('hex').slice(0, 12);
const extension = extname(entrypoint);
const stem = entrypoint.slice(0, -extension.length);
const hashedName = `${stem}.${hash}${extension}`;
const targetPath = join(buildDir, hashedName);
renameSync(sourcePath, targetPath);
bootstrap = bootstrap.replaceAll(entrypoint, hashedName);
}
writeFileSync(bootstrapPath, bootstrap);
for (const filePath of walk(buildDir)) {
if (filePath.endsWith('.br')) {
continue;
}
if (!compressibleExtensions.has(extname(filePath))) {
continue;
}
const content = readFileSync(filePath);
writeFileSync(
`${filePath}.br`,
brotliCompressSync(content, {
params: {
[constants.BROTLI_PARAM_QUALITY]: 11,
},
}),
);
}
function* walk(directory) {
for (const entry of readdirSync(directory, { withFileTypes: true })) {
const entryPath = join(directory, entry.name);
if (entry.isDirectory()) {
yield* walk(entryPath);
continue;
}
if (entry.isFile()) {
yield entryPath;
}
}
}
console.log(`[userfront] optimized ${basename(buildDir)} with hashed entrypoints and brotli assets`);