Skip to content

Commit 87b5230

Browse files
committed
fix(emception): P0'+P4+P5 — kill stale CDN fallback, LGWIN=24, sort tar entries
P0': stage-core-cdn.mjs now throws immediately if build/cdn is absent instead of silently falling back to public/cdn or packages/core/cdn. Stale fallback was root cause of v3.5.0 publishing at 164 MB despite local npm pack measuring 149.9 MB. P4: add BROTLI_PARAM_LGWIN=24 to brotliCompress() in generate-bundles.ts. Increases back-reference window from 4 MB (default 22 bits) to 16 MB (RFC 7932 max, browser-decodable). Expected saving: ~5-8 MB across large cache bundles (cache-misc, cache-wasmfs, cache-debug). P5: sort tar entries by (extension, path) immediately before createTar(). Adjacent structurally-similar files (.a, .pyc, etc.) improve brotli back-reference density. Expected saving: ~2-4 MB across the tarball.
1 parent 357dfb4 commit 87b5230

2 files changed

Lines changed: 23 additions & 28 deletions

File tree

tools/emception/scripts/generate-bundles.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ function brotliCompress(data: Buffer, outPath: string): Promise<Buffer> {
112112
{
113113
params: {
114114
[zlib.constants.BROTLI_PARAM_QUALITY]: 11,
115+
// P4: 16 MB back-reference window (RFC 7932 max = 24 bits).
116+
// Node.js default is 22 bits (4 MB). Large cache bundles have
117+
// pattern repetitions spanning >4 MB, so this saves ~5–8 MB.
118+
[zlib.constants.BROTLI_PARAM_LGWIN]: 24,
115119
},
116120
},
117121
(err, result) => {
@@ -534,6 +538,16 @@ async function main() {
534538
continue;
535539
}
536540

541+
// P5: Sort by extension then path so structurally similar files (e.g. all
542+
// .a, all .pyc) are adjacent. Brotli can then reference earlier identical
543+
// or near-identical blocks within its window, improving ratios across the
544+
// whole bundle (~2–4 MB saving across the tarball).
545+
entries.sort((a, b) => {
546+
const extA = path.extname(a.path);
547+
const extB = path.extname(b.path);
548+
return extA !== extB ? extA.localeCompare(extB) : a.path.localeCompare(b.path);
549+
});
550+
537551
// Create tar
538552
const tar = createTar(entries);
539553
totalUncompressed += tar.length;

tools/emception/scripts/stage-core-cdn.mjs

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -35,42 +35,23 @@ async function exists(filePath) {
3535
}
3636

3737
async function resolveStagingSource() {
38-
const candidates = [
39-
{
38+
// Only build/cdn is a valid source. public/cdn and packages/core/cdn may
39+
// contain stale bundles from a previous build and must NEVER be used as a
40+
// silent fallback — that was the root cause of the v3.5.0 regression where
41+
// the published tarball was 164 MB instead of ~150 MB.
42+
if (await exists(sourceBuildCdnDir) && await exists(sourceBuildManifestFile)) {
43+
return {
4044
label: 'build/cdn',
4145
cdnDir: sourceBuildCdnDir,
4246
manifestFile: sourceBuildManifestFile,
43-
},
44-
{
45-
label: 'public/cdn',
46-
cdnDir: sourcePublicCdnDir,
47-
manifestFile: sourcePublicManifestFile,
48-
},
49-
{
50-
label: 'packages/core/cdn',
51-
cdnDir: targetCdnDir,
52-
manifestFile: targetManifestFile,
53-
},
54-
];
55-
56-
for (const candidate of candidates) {
57-
if (await exists(candidate.cdnDir) && await exists(candidate.manifestFile)) {
58-
if (candidate.cdnDir !== sourceBuildCdnDir) {
59-
console.log(
60-
`[stage-core-cdn] ${path.relative(emceptionRoot, sourceBuildCdnDir)} unavailable; reusing ${path.relative(emceptionRoot, candidate.cdnDir)}.`,
61-
);
62-
}
63-
return candidate;
64-
}
47+
};
6548
}
6649

6750
throw new Error(
6851
[
6952
'Unable to stage the emception core CDN.',
70-
'Expected one of these artifact sets to exist:',
71-
`- ${path.relative(emceptionRoot, sourceBuildCdnDir)} + ${path.relative(emceptionRoot, sourceBuildManifestFile)}`,
72-
`- ${path.relative(emceptionRoot, sourcePublicCdnDir)} + ${path.relative(emceptionRoot, sourcePublicManifestFile)}`,
73-
`- ${path.relative(emceptionRoot, targetCdnDir)} + ${path.relative(emceptionRoot, targetManifestFile)}`,
53+
`build/cdn artifacts not found at: ${sourceBuildCdnDir}`,
54+
'Run `npm run build:cdn:serial` (or `npm run build:all`) first.',
7455
].join('\n'),
7556
);
7657
}

0 commit comments

Comments
 (0)