mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-15 15:52:21 +00:00
build: guard the initial chunks by module id; main-chunk check in CI
Review of Task 0: - build/initialChunkGuard.js, a Rollup plugin in the browser build, fails the build when an initial chunk (an entry and what it imports statically) holds a module from node_modules/three, @navaramap/* or postprocessing. Checked by forcing it on satellite.js, which the main chunk does hold: the build fails naming the chunk and module. navaraAssets.test now pins both build plugins. - scripts/check-main-chunk.mjs is one script for both main-chunk checks: the composition (text markers in the initial chunks, sizes) and, when scripts/main-chunk-baseline.json exists, the phase-4 branch's gzip-9 budget, with its exports (checkMainChunk, measureMainChunk) so the two branches merge into this file. The composition test moved to src/tooling/mainChunkComposition.test.mjs to leave phase 4's mainChunk.test.mjs its name. - CI runs npm run check:main-chunk after each npm run build (unit, browser-gate and Windows jobs).
This commit is contained in:
1 parent
f7f4e9a45c
commit
76851ee949
8 files changed
+289
-66
No files matched your search
@@ -0,0 +1,78 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
ENGINE_ONLY_MODULES,
|
||||
initialChunkGuard,
|
||||
initialChunkViolations,
|
||||
} from '../../build/initialChunkGuard.js';
|
||||
|
||||
const chunk = (fields) => ({
|
||||
type: 'chunk',
|
||||
isEntry: false,
|
||||
imports: [],
|
||||
moduleIds: [],
|
||||
...fields,
|
||||
});
|
||||
|
||||
const bundle = () => ({
|
||||
'assets/index-A.js': chunk({
|
||||
isEntry: true,
|
||||
imports: ['assets/vendor-B.js'],
|
||||
moduleIds: ['/repo/src/main.js', '/repo/node_modules/cesium/index.js'],
|
||||
}),
|
||||
'assets/vendor-B.js': chunk({
|
||||
moduleIds: ['/repo/node_modules/satellite.js/dist/index.js'],
|
||||
}),
|
||||
'assets/navara-engine-C.js': chunk({
|
||||
isDynamicEntry: true,
|
||||
moduleIds: [
|
||||
'/repo/node_modules/three/build/three.module.js',
|
||||
'/repo/node_modules/@navaramap/three/dist/index.js',
|
||||
],
|
||||
}),
|
||||
'assets/style.css': { type: 'asset' },
|
||||
});
|
||||
|
||||
test('lazy chunks may hold three and Navara; initial chunks are clean', () => {
|
||||
assert.deepEqual(initialChunkViolations(bundle()), []);
|
||||
assert.ok(ENGINE_ONLY_MODULES.test('/x/node_modules/three/src/a.js'));
|
||||
assert.ok(
|
||||
ENGINE_ONLY_MODULES.test('C:\\x\\node_modules\\@navaramap\\three\\a.js'),
|
||||
);
|
||||
assert.ok(!ENGINE_ONLY_MODULES.test('/x/node_modules/three-geojson/a.js'));
|
||||
assert.ok(!ENGINE_ONLY_MODULES.test('/x/src/layers/threeD.js'));
|
||||
});
|
||||
|
||||
test('three or Navara reached by a static import from the entry is reported', () => {
|
||||
const broken = bundle();
|
||||
broken['assets/vendor-B.js'].moduleIds.push(
|
||||
'/repo/node_modules/three/build/three.core.js',
|
||||
);
|
||||
broken['assets/index-A.js'].moduleIds.push(
|
||||
'/repo/node_modules/@navaramap/three-default-plugin/dist/index.js',
|
||||
);
|
||||
assert.deepEqual(initialChunkViolations(broken), [
|
||||
{
|
||||
chunk: 'assets/index-A.js',
|
||||
module:
|
||||
'/repo/node_modules/@navaramap/three-default-plugin/dist/index.js',
|
||||
},
|
||||
{
|
||||
chunk: 'assets/vendor-B.js',
|
||||
module: '/repo/node_modules/three/build/three.core.js',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('the plugin fails the build on a violation and passes a clean bundle', () => {
|
||||
const plugin = initialChunkGuard({ log: () => {} });
|
||||
const errors = [];
|
||||
const context = { error: (message) => errors.push(message) };
|
||||
plugin.generateBundle.call(context, {}, bundle());
|
||||
assert.deepEqual(errors, []);
|
||||
const broken = bundle();
|
||||
broken['assets/index-A.js'].moduleIds.push('/r/node_modules/three/a.js');
|
||||
plugin.generateBundle.call(context, {}, broken);
|
||||
assert.equal(errors.length, 1);
|
||||
assert.match(errors[0], /three.*index-A\.js/s);
|
||||
});
|
||||
@@ -84,3 +84,21 @@ test('three and Navara markers are reported, ordinary engine names are not', ()
|
||||
]);
|
||||
assert.ok(FORBIDDEN_MARKERS.length >= 2);
|
||||
});
|
||||
|
||||
test('the script exports the gzip budget check (phase 4 shape) next to the composition check', async () => {
|
||||
const { mkdirSync, mkdtempSync, writeFileSync } = await import('node:fs');
|
||||
const { tmpdir } = await import('node:os');
|
||||
const path = await import('node:path');
|
||||
const { checkMainChunk, measureMainChunk } =
|
||||
await import('../../scripts/check-main-chunk.mjs');
|
||||
const baseline = { gzipBytes: 1000, allowanceBytes: 100 };
|
||||
assert.equal(checkMainChunk(1100, baseline).ok, true);
|
||||
assert.equal(checkMainChunk(1101, baseline).ok, false);
|
||||
const dist = mkdtempSync(path.join(tmpdir(), 'gev-main-chunk-'));
|
||||
mkdirSync(path.join(dist, 'assets'));
|
||||
writeFileSync(path.join(dist, 'assets/index-small.js'), 'x');
|
||||
writeFileSync(path.join(dist, 'assets/index-main.js'), 'x'.repeat(5000));
|
||||
const measured = measureMainChunk(dist);
|
||||
assert.equal(measured.name, 'index-main.js');
|
||||
assert.ok(measured.gzipBytes > 0 && measured.gzipBytes < 5000);
|
||||
});
|
||||
@@ -46,11 +46,11 @@ test('a build without Navara gets no Navara wasm', (t) => {
|
||||
assert.deepEqual(emitted, []);
|
||||
});
|
||||
|
||||
test('the browser build runs the Navara asset copy as a Rollup plugin', () => {
|
||||
test('the browser build runs the Navara asset copy and the initial-chunk guard as Rollup plugins', () => {
|
||||
const { build } = createBrowserViteConfig({});
|
||||
assert.deepEqual(
|
||||
build.rollupOptions.plugins.map(({ name }) => name),
|
||||
['navara-worker-assets'],
|
||||
['navara-worker-assets', 'gev-initial-chunk-guard'],
|
||||
);
|
||||
assert.equal(build.chunkSizeWarningLimit, 1500);
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user