@prairielearn/compiled-assets 4.0.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/package.json +7 -7
- package/src/cli.ts +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @prairielearn/compiled-assets
|
|
2
2
|
|
|
3
|
+
## 4.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- a6b3d9d: Emit `sizes.json` with per-entry-point bundle sizes during build
|
|
8
|
+
|
|
9
|
+
## 4.0.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 8bdf6ea: Upgrade all JavaScript dependencies
|
|
14
|
+
- Updated dependencies [8bdf6ea]
|
|
15
|
+
- @prairielearn/html@5.0.1
|
|
16
|
+
|
|
3
17
|
## 4.0.0
|
|
4
18
|
|
|
5
19
|
### Major Changes
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\nimport path from 'path';\nimport { promisify } from 'util';\nimport zlib from 'zlib';\n\nimport { program } from 'commander';\nimport fs from 'fs-extra';\nimport prettyBytes from 'pretty-bytes';\n\nimport { type AssetsManifest, build } from './index.js';\n\nconst gzip = promisify(zlib.gzip);\nconst brotli = promisify(zlib.brotliCompress);\n\ninterface AssetSizes {\n raw: number;\n gzip: number;\n brotli: number;\n}\n\ntype CompressedSizes = Record<string, AssetSizes>;\n\n/**\n * Collects all unique asset paths from the manifest, including entry points and their preloads.\n */\nfunction getAllAssetPaths(manifest: AssetsManifest): Set<string> {\n const allPaths = new Set<string>();\n for (const asset of Object.values(manifest)) {\n allPaths.add(asset.assetPath);\n for (const preload of asset.preloads) {\n allPaths.add(preload);\n }\n }\n return allPaths;\n}\n\n/**\n * Writes gzip and brotli compressed versions of the assets in the specified directory.\n * It reads each asset file, compresses it using gzip and brotli algorithms, and writes the compressed files\n * with appropriate extensions (.gz and .br) in the same directory.\n *\n * @param destination Directory where the compressed assets will be written.\n * @param manifest The assets manifest containing information about the assets.\n * @returns A promise that resolves to an object containing the sizes of the original, gzip, and brotli compressed assets.\n */\nasync function writeCompressedAssets(\n destination: string,\n manifest: AssetsManifest,\n): Promise<CompressedSizes> {\n const compressedSizes: CompressedSizes = {};\n const allAssetPaths = getAllAssetPaths(manifest);\n\n await Promise.all(\n [...allAssetPaths].map(async (assetPath) => {\n const destinationFilePath = path.resolve(destination, assetPath);\n const contents = await fs.readFile(destinationFilePath);\n const gzipCompressed = await gzip(contents);\n const brotliCompressed = await brotli(contents);\n await fs.writeFile(`${destinationFilePath}.gz`, gzipCompressed);\n await fs.writeFile(`${destinationFilePath}.br`, brotliCompressed);\n compressedSizes[assetPath] = {\n raw: contents.length,\n gzip: gzipCompressed.length,\n brotli: brotliCompressed.length,\n };\n }),\n );\n return compressedSizes;\n}\n\n/**\n * Calculates the total size of an entry point including all its preloaded chunks.\n */\nfunction calculateTotalSizes(\n asset: AssetsManifest[string],\n compressedSizes: CompressedSizes,\n): AssetSizes {\n const entrySizes = compressedSizes[asset.assetPath];\n const total: AssetSizes = {\n raw: entrySizes.raw,\n gzip: entrySizes.gzip,\n brotli: entrySizes.brotli,\n };\n\n for (const preload of asset.preloads) {\n const preloadSizes = compressedSizes[preload];\n if (preloadSizes) {\n total.raw += preloadSizes.raw;\n total.gzip += preloadSizes.gzip;\n total.brotli += preloadSizes.brotli;\n }\n }\n\n return total;\n}\n\nprogram.command('build <source> <destination>').action(async (source, destination) => {\n const manifest = await build(source, destination);\n\n // Write gzip and brotli versions of the output files. Record size information\n // so we can show it to the user.\n const compressedSizes = await writeCompressedAssets(destination, manifest);\n\n // Format the output into an object that we can pass to `console.table`.\n const results: Record<string, any> = {};\n Object.entries(manifest).forEach(([entryPoint, asset]) => {\n const totalSizes = calculateTotalSizes(asset, compressedSizes);\n\n results[entryPoint] = {\n 'Output file': asset.assetPath,\n Size: prettyBytes(totalSizes.raw),\n 'Size (gzip)': prettyBytes(totalSizes.gzip),\n 'Size (brotli)': prettyBytes(totalSizes.brotli),\n };\n });\n console.table(results);\n});\n\nprogram.parseAsync(process.argv).catch((err) => {\n console.error(err);\n process.exit(1);\n});\n"]}
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\nimport path from 'path';\nimport { promisify } from 'util';\nimport zlib from 'zlib';\n\nimport { program } from 'commander';\nimport fs from 'fs-extra';\nimport prettyBytes from 'pretty-bytes';\n\nimport { type AssetsManifest, build } from './index.js';\n\nconst gzip = promisify(zlib.gzip);\nconst brotli = promisify(zlib.brotliCompress);\n\ninterface AssetSizes {\n raw: number;\n gzip: number;\n brotli: number;\n}\n\ntype CompressedSizes = Record<string, AssetSizes>;\n\n/**\n * Collects all unique asset paths from the manifest, including entry points and their preloads.\n */\nfunction getAllAssetPaths(manifest: AssetsManifest): Set<string> {\n const allPaths = new Set<string>();\n for (const asset of Object.values(manifest)) {\n allPaths.add(asset.assetPath);\n for (const preload of asset.preloads) {\n allPaths.add(preload);\n }\n }\n return allPaths;\n}\n\n/**\n * Writes gzip and brotli compressed versions of the assets in the specified directory.\n * It reads each asset file, compresses it using gzip and brotli algorithms, and writes the compressed files\n * with appropriate extensions (.gz and .br) in the same directory.\n *\n * @param destination Directory where the compressed assets will be written.\n * @param manifest The assets manifest containing information about the assets.\n * @returns A promise that resolves to an object containing the sizes of the original, gzip, and brotli compressed assets.\n */\nasync function writeCompressedAssets(\n destination: string,\n manifest: AssetsManifest,\n): Promise<CompressedSizes> {\n const compressedSizes: CompressedSizes = {};\n const allAssetPaths = getAllAssetPaths(manifest);\n\n await Promise.all(\n [...allAssetPaths].map(async (assetPath) => {\n const destinationFilePath = path.resolve(destination, assetPath);\n const contents = await fs.readFile(destinationFilePath);\n const gzipCompressed = await gzip(contents);\n const brotliCompressed = await brotli(contents);\n await fs.writeFile(`${destinationFilePath}.gz`, gzipCompressed);\n await fs.writeFile(`${destinationFilePath}.br`, brotliCompressed);\n compressedSizes[assetPath] = {\n raw: contents.length,\n gzip: gzipCompressed.length,\n brotli: brotliCompressed.length,\n };\n }),\n );\n return compressedSizes;\n}\n\n/**\n * Calculates the total size of an entry point including all its preloaded chunks.\n */\nfunction calculateTotalSizes(\n asset: AssetsManifest[string],\n compressedSizes: CompressedSizes,\n): AssetSizes {\n const entrySizes = compressedSizes[asset.assetPath];\n const total: AssetSizes = {\n raw: entrySizes.raw,\n gzip: entrySizes.gzip,\n brotli: entrySizes.brotli,\n };\n\n for (const preload of asset.preloads) {\n const preloadSizes = compressedSizes[preload];\n if (preloadSizes) {\n total.raw += preloadSizes.raw;\n total.gzip += preloadSizes.gzip;\n total.brotli += preloadSizes.brotli;\n }\n }\n\n return total;\n}\n\nprogram.command('build <source> <destination>').action(async (source, destination) => {\n const manifest = await build(source, destination);\n\n // Write gzip and brotli versions of the output files. Record size information\n // so we can show it to the user.\n const compressedSizes = await writeCompressedAssets(destination, manifest);\n\n // Format the output into an object that we can pass to `console.table`.\n const results: Record<string, any> = {};\n const sizesJson: Record<string, AssetSizes> = {};\n Object.entries(manifest).forEach(([entryPoint, asset]) => {\n const totalSizes = calculateTotalSizes(asset, compressedSizes);\n\n results[entryPoint] = {\n 'Output file': asset.assetPath,\n Size: prettyBytes(totalSizes.raw),\n 'Size (gzip)': prettyBytes(totalSizes.gzip),\n 'Size (brotli)': prettyBytes(totalSizes.brotli),\n };\n\n sizesJson[entryPoint] = totalSizes;\n });\n console.table(results);\n\n // Write the result for processing by other tools (e.g. our bundle size reporting action).\n await fs.writeJSON(path.resolve(destination, 'sizes.json'), sizesJson, { spaces: 2 });\n});\n\nprogram.parseAsync(process.argv).catch((err) => {\n console.error(err);\n process.exit(1);\n});\n"]}
|
package/dist/cli.js
CHANGED
|
@@ -75,6 +75,7 @@ program.command('build <source> <destination>').action(async (source, destinatio
|
|
|
75
75
|
const compressedSizes = await writeCompressedAssets(destination, manifest);
|
|
76
76
|
// Format the output into an object that we can pass to `console.table`.
|
|
77
77
|
const results = {};
|
|
78
|
+
const sizesJson = {};
|
|
78
79
|
Object.entries(manifest).forEach(([entryPoint, asset]) => {
|
|
79
80
|
const totalSizes = calculateTotalSizes(asset, compressedSizes);
|
|
80
81
|
results[entryPoint] = {
|
|
@@ -83,8 +84,11 @@ program.command('build <source> <destination>').action(async (source, destinatio
|
|
|
83
84
|
'Size (gzip)': prettyBytes(totalSizes.gzip),
|
|
84
85
|
'Size (brotli)': prettyBytes(totalSizes.brotli),
|
|
85
86
|
};
|
|
87
|
+
sizesJson[entryPoint] = totalSizes;
|
|
86
88
|
});
|
|
87
89
|
console.table(results);
|
|
90
|
+
// Write the result for processing by other tools (e.g. our bundle size reporting action).
|
|
91
|
+
await fs.writeJSON(path.resolve(destination, 'sizes.json'), sizesJson, { spaces: 2 });
|
|
88
92
|
});
|
|
89
93
|
program.parseAsync(process.argv).catch((err) => {
|
|
90
94
|
console.error(err);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,WAAW,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAuB,KAAK,EAAE,MAAM,YAAY,CAAC;AAExD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClC,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAU9C;;GAEG;AACH,SAAS,gBAAgB,CAAC,QAAwB,EAAe;IAC/D,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC9B,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACrC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAAA,CACjB;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,qBAAqB,CAClC,WAAmB,EACnB,QAAwB,EACE;IAC1B,MAAM,eAAe,GAAoB,EAAE,CAAC;IAC5C,MAAM,aAAa,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAEjD,MAAM,OAAO,CAAC,GAAG,CACf,CAAC,GAAG,aAAa,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC;QAC1C,MAAM,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QACjE,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;QACxD,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,gBAAgB,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,mBAAmB,KAAK,EAAE,cAAc,CAAC,CAAC;QAChE,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,mBAAmB,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAClE,eAAe,CAAC,SAAS,CAAC,GAAG;YAC3B,GAAG,EAAE,QAAQ,CAAC,MAAM;YACpB,IAAI,EAAE,cAAc,CAAC,MAAM;YAC3B,MAAM,EAAE,gBAAgB,CAAC,MAAM;SAChC,CAAC;IAAA,CACH,CAAC,CACH,CAAC;IACF,OAAO,eAAe,CAAC;AAAA,CACxB;AAED;;GAEG;AACH,SAAS,mBAAmB,CAC1B,KAA6B,EAC7B,eAAgC,EACpB;IACZ,MAAM,UAAU,GAAG,eAAe,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,KAAK,GAAe;QACxB,GAAG,EAAE,UAAU,CAAC,GAAG;QACnB,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,MAAM,EAAE,UAAU,CAAC,MAAM;KAC1B,CAAC;IAEF,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACrC,MAAM,YAAY,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,YAAY,EAAE,CAAC;YACjB,KAAK,CAAC,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC;YAC9B,KAAK,CAAC,IAAI,IAAI,YAAY,CAAC,IAAI,CAAC;YAChC,KAAK,CAAC,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC;QACtC,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AAAA,CACd;AAED,OAAO,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC;IACpF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAElD,8EAA8E;IAC9E,iCAAiC;IACjC,MAAM,eAAe,GAAG,MAAM,qBAAqB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAE3E,wEAAwE;IACxE,MAAM,OAAO,GAAwB,EAAE,CAAC;IACxC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC;QACxD,MAAM,UAAU,GAAG,mBAAmB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QAE/D,OAAO,CAAC,UAAU,CAAC,GAAG;YACpB,aAAa,EAAE,KAAK,CAAC,SAAS;YAC9B,IAAI,EAAE,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC;YACjC,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC;YAC3C,eAAe,EAAE,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC;SAChD,CAAC;IAAA,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\nimport path from 'path';\nimport { promisify } from 'util';\nimport zlib from 'zlib';\n\nimport { program } from 'commander';\nimport fs from 'fs-extra';\nimport prettyBytes from 'pretty-bytes';\n\nimport { type AssetsManifest, build } from './index.js';\n\nconst gzip = promisify(zlib.gzip);\nconst brotli = promisify(zlib.brotliCompress);\n\ninterface AssetSizes {\n raw: number;\n gzip: number;\n brotli: number;\n}\n\ntype CompressedSizes = Record<string, AssetSizes>;\n\n/**\n * Collects all unique asset paths from the manifest, including entry points and their preloads.\n */\nfunction getAllAssetPaths(manifest: AssetsManifest): Set<string> {\n const allPaths = new Set<string>();\n for (const asset of Object.values(manifest)) {\n allPaths.add(asset.assetPath);\n for (const preload of asset.preloads) {\n allPaths.add(preload);\n }\n }\n return allPaths;\n}\n\n/**\n * Writes gzip and brotli compressed versions of the assets in the specified directory.\n * It reads each asset file, compresses it using gzip and brotli algorithms, and writes the compressed files\n * with appropriate extensions (.gz and .br) in the same directory.\n *\n * @param destination Directory where the compressed assets will be written.\n * @param manifest The assets manifest containing information about the assets.\n * @returns A promise that resolves to an object containing the sizes of the original, gzip, and brotli compressed assets.\n */\nasync function writeCompressedAssets(\n destination: string,\n manifest: AssetsManifest,\n): Promise<CompressedSizes> {\n const compressedSizes: CompressedSizes = {};\n const allAssetPaths = getAllAssetPaths(manifest);\n\n await Promise.all(\n [...allAssetPaths].map(async (assetPath) => {\n const destinationFilePath = path.resolve(destination, assetPath);\n const contents = await fs.readFile(destinationFilePath);\n const gzipCompressed = await gzip(contents);\n const brotliCompressed = await brotli(contents);\n await fs.writeFile(`${destinationFilePath}.gz`, gzipCompressed);\n await fs.writeFile(`${destinationFilePath}.br`, brotliCompressed);\n compressedSizes[assetPath] = {\n raw: contents.length,\n gzip: gzipCompressed.length,\n brotli: brotliCompressed.length,\n };\n }),\n );\n return compressedSizes;\n}\n\n/**\n * Calculates the total size of an entry point including all its preloaded chunks.\n */\nfunction calculateTotalSizes(\n asset: AssetsManifest[string],\n compressedSizes: CompressedSizes,\n): AssetSizes {\n const entrySizes = compressedSizes[asset.assetPath];\n const total: AssetSizes = {\n raw: entrySizes.raw,\n gzip: entrySizes.gzip,\n brotli: entrySizes.brotli,\n };\n\n for (const preload of asset.preloads) {\n const preloadSizes = compressedSizes[preload];\n if (preloadSizes) {\n total.raw += preloadSizes.raw;\n total.gzip += preloadSizes.gzip;\n total.brotli += preloadSizes.brotli;\n }\n }\n\n return total;\n}\n\nprogram.command('build <source> <destination>').action(async (source, destination) => {\n const manifest = await build(source, destination);\n\n // Write gzip and brotli versions of the output files. Record size information\n // so we can show it to the user.\n const compressedSizes = await writeCompressedAssets(destination, manifest);\n\n // Format the output into an object that we can pass to `console.table`.\n const results: Record<string, any> = {};\n const sizesJson: Record<string, AssetSizes> = {};\n Object.entries(manifest).forEach(([entryPoint, asset]) => {\n const totalSizes = calculateTotalSizes(asset, compressedSizes);\n\n results[entryPoint] = {\n 'Output file': asset.assetPath,\n Size: prettyBytes(totalSizes.raw),\n 'Size (gzip)': prettyBytes(totalSizes.gzip),\n 'Size (brotli)': prettyBytes(totalSizes.brotli),\n };\n\n sizesJson[entryPoint] = totalSizes;\n });\n console.table(results);\n\n // Write the result for processing by other tools (e.g. our bundle size reporting action).\n await fs.writeJSON(path.resolve(destination, 'sizes.json'), sizesJson, { spaces: 2 });\n});\n\nprogram.parseAsync(process.argv).catch((err) => {\n console.error(err);\n process.exit(1);\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prairielearn/compiled-assets",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"test": "vitest run --coverage"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@prairielearn/html": "^5.0.
|
|
22
|
-
"commander": "^14.0.
|
|
21
|
+
"@prairielearn/html": "^5.0.1",
|
|
22
|
+
"commander": "^14.0.3",
|
|
23
23
|
"esbuild": "^0.27.2",
|
|
24
24
|
"express-static-gzip": "^2.2.0",
|
|
25
25
|
"fs-extra": "^11.3.3",
|
|
@@ -28,15 +28,15 @@
|
|
|
28
28
|
"tmp-promise": "^3.0.3"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@prairielearn/tsconfig": "^
|
|
31
|
+
"@prairielearn/tsconfig": "^2.0.0",
|
|
32
32
|
"@types/node": "^24.10.9",
|
|
33
|
-
"@typescript/native-preview": "^7.0.0-dev.
|
|
34
|
-
"@vitest/coverage-v8": "^4.0.
|
|
33
|
+
"@typescript/native-preview": "^7.0.0-dev.20260203.1",
|
|
34
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
35
35
|
"express": "^4.22.1",
|
|
36
36
|
"get-port": "^7.1.0",
|
|
37
37
|
"node-fetch": "^3.3.2",
|
|
38
38
|
"tsx": "^4.21.0",
|
|
39
39
|
"typescript": "^5.9.3",
|
|
40
|
-
"vitest": "^4.0.
|
|
40
|
+
"vitest": "^4.0.18"
|
|
41
41
|
}
|
|
42
42
|
}
|
package/src/cli.ts
CHANGED
|
@@ -103,6 +103,7 @@ program.command('build <source> <destination>').action(async (source, destinatio
|
|
|
103
103
|
|
|
104
104
|
// Format the output into an object that we can pass to `console.table`.
|
|
105
105
|
const results: Record<string, any> = {};
|
|
106
|
+
const sizesJson: Record<string, AssetSizes> = {};
|
|
106
107
|
Object.entries(manifest).forEach(([entryPoint, asset]) => {
|
|
107
108
|
const totalSizes = calculateTotalSizes(asset, compressedSizes);
|
|
108
109
|
|
|
@@ -112,8 +113,13 @@ program.command('build <source> <destination>').action(async (source, destinatio
|
|
|
112
113
|
'Size (gzip)': prettyBytes(totalSizes.gzip),
|
|
113
114
|
'Size (brotli)': prettyBytes(totalSizes.brotli),
|
|
114
115
|
};
|
|
116
|
+
|
|
117
|
+
sizesJson[entryPoint] = totalSizes;
|
|
115
118
|
});
|
|
116
119
|
console.table(results);
|
|
120
|
+
|
|
121
|
+
// Write the result for processing by other tools (e.g. our bundle size reporting action).
|
|
122
|
+
await fs.writeJSON(path.resolve(destination, 'sizes.json'), sizesJson, { spaces: 2 });
|
|
117
123
|
});
|
|
118
124
|
|
|
119
125
|
program.parseAsync(process.argv).catch((err) => {
|