@tomnieuwland/sls-bundle-analyser 1.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/LICENSE.md +21 -0
- package/README.md +126 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +54 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/compare.d.ts +10 -0
- package/dist/commands/compare.d.ts.map +1 -0
- package/dist/commands/compare.js +82 -0
- package/dist/commands/compare.js.map +1 -0
- package/dist/commands/shared-modules.d.ts +6 -0
- package/dist/commands/shared-modules.d.ts.map +1 -0
- package/dist/commands/shared-modules.js +27 -0
- package/dist/commands/shared-modules.js.map +1 -0
- package/dist/commands/sizes.d.ts +6 -0
- package/dist/commands/sizes.d.ts.map +1 -0
- package/dist/commands/sizes.js +70 -0
- package/dist/commands/sizes.js.map +1 -0
- package/dist/commands/visualize.d.ts +11 -0
- package/dist/commands/visualize.d.ts.map +1 -0
- package/dist/commands/visualize.js +29 -0
- package/dist/commands/visualize.js.map +1 -0
- package/dist/compare.d.ts +47 -0
- package/dist/compare.d.ts.map +1 -0
- package/dist/compare.js +181 -0
- package/dist/compare.js.map +1 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +35 -0
- package/dist/config.js.map +1 -0
- package/dist/dependency-graph.d.ts +29 -0
- package/dist/dependency-graph.d.ts.map +1 -0
- package/dist/dependency-graph.js +87 -0
- package/dist/dependency-graph.js.map +1 -0
- package/dist/esbuild-config.d.ts +4 -0
- package/dist/esbuild-config.d.ts.map +1 -0
- package/dist/esbuild-config.js +20 -0
- package/dist/esbuild-config.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/parse-serverless.d.ts +53 -0
- package/dist/parse-serverless.d.ts.map +1 -0
- package/dist/parse-serverless.js +195 -0
- package/dist/parse-serverless.js.map +1 -0
- package/dist/report.d.ts +36 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +154 -0
- package/dist/report.js.map +1 -0
- package/dist/shared-modules.d.ts +17 -0
- package/dist/shared-modules.d.ts.map +1 -0
- package/dist/shared-modules.js +104 -0
- package/dist/shared-modules.js.map +1 -0
- package/dist/visualize.d.ts +20 -0
- package/dist/visualize.d.ts.map +1 -0
- package/dist/visualize.js +139 -0
- package/dist/visualize.js.map +1 -0
- package/package.json +53 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Thomas Nieuwland
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# sls-bundle-analyser
|
|
2
|
+
|
|
3
|
+
CLI tool for analysing Lambda bundle sizes in Serverless Framework projects. It parses `serverless*.yml` files to discover handler entry points, bundles them with esbuild, and reports on size changes between branches.
|
|
4
|
+
|
|
5
|
+
To get started, run `npx @tomnieuwland/sls-bundle-analyser sizes` in the root of your project.
|
|
6
|
+
|
|
7
|
+
## Commands
|
|
8
|
+
|
|
9
|
+
### `sls-bundle-analyser compare`
|
|
10
|
+
|
|
11
|
+
Compares bundle sizes between the current branch and a base branch. Builds a dependency graph to determine which functions are affected by code changes, then reports size deltas.
|
|
12
|
+
|
|
13
|
+
| Flag | Description |
|
|
14
|
+
| ---------------------- | ------------------------------------------------------------------------------- |
|
|
15
|
+
| `--base <branch>` | Base branch to compare against (default: from config or `main`) |
|
|
16
|
+
| `--all` | Analyze all functions, not just those affected by changes |
|
|
17
|
+
| `--verbose` | Show per-module breakdown for each function |
|
|
18
|
+
| `--json` | Output raw JSON instead of a text table |
|
|
19
|
+
| `--threshold <bytes>` | Only show functions with delta above this threshold |
|
|
20
|
+
| `--fail-above <bytes>` | Exit with code 1 if any function grew more than this many bytes (useful for CI) |
|
|
21
|
+
|
|
22
|
+
### `sls-bundle-analyser sizes`
|
|
23
|
+
|
|
24
|
+
Bundles all discovered functions and reports their sizes. No branch comparison — just a snapshot of current bundle sizes.
|
|
25
|
+
|
|
26
|
+
| Flag | Description |
|
|
27
|
+
| ---------------- | ----------------------------------------------------- |
|
|
28
|
+
| `--json` | Output raw JSON |
|
|
29
|
+
| `--sort <field>` | Sort order: `size` (default, largest first) or `name` |
|
|
30
|
+
|
|
31
|
+
### `sls-bundle-analyser visualize <entry-point>`
|
|
32
|
+
|
|
33
|
+
Generates an interactive treemap (or sunburst/network diagram) for a single handler's bundle and opens it in the browser.
|
|
34
|
+
|
|
35
|
+
| Flag | Description |
|
|
36
|
+
| ------------------- | ---------------------------------------------------------------------------- |
|
|
37
|
+
| `--template <type>` | Visualization type: `treemap`, `sunburst`, or `network` (default: `treemap`) |
|
|
38
|
+
| `--no-third-party` | Exclude `node_modules` from the visualization |
|
|
39
|
+
| `--no-open` | Generate the file without opening it in the browser |
|
|
40
|
+
| `--top <n>` | Show only the N largest modules |
|
|
41
|
+
| `--output <path>` | Write HTML to this path instead of opening in the browser |
|
|
42
|
+
| `--diff` | Generate side-by-side visualizations comparing current branch against base |
|
|
43
|
+
| `--base <branch>` | Base branch for `--diff` (default: from config or `main`) |
|
|
44
|
+
|
|
45
|
+
### `sls-bundle-analyser shared-modules`
|
|
46
|
+
|
|
47
|
+
Analyses which `node_modules` packages are bundled across multiple Lambda functions, helping identify candidates for a shared layer.
|
|
48
|
+
|
|
49
|
+
| Flag | Description |
|
|
50
|
+
| ----------- | ------------------------------------------- |
|
|
51
|
+
| `--json` | Output raw JSON instead of a text table |
|
|
52
|
+
| `--top <n>` | Show only the top N modules (default: `20`) |
|
|
53
|
+
|
|
54
|
+
## Configuration
|
|
55
|
+
|
|
56
|
+
Configuration is loaded from the service directory (the directory you run the tool from). The tool checks two locations in order:
|
|
57
|
+
|
|
58
|
+
1. **`.bundle-analyser.json`** — a standalone config file in the service directory
|
|
59
|
+
2. **`package.json`** — a `"bundle-analyser"` key at the top level
|
|
60
|
+
|
|
61
|
+
If neither is found, defaults are used. All fields are optional.
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"exclude": ["serverless.local-*.yml"],
|
|
66
|
+
"base": "main",
|
|
67
|
+
"esbuild": {}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Fields
|
|
72
|
+
|
|
73
|
+
| Field | Type | Default | Description |
|
|
74
|
+
| --------- | ---------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
75
|
+
| `exclude` | `string[]` | `["serverless.local-*.yml"]` | Glob patterns for `serverless*.yml` files to skip. Useful for ignoring local dev overrides. |
|
|
76
|
+
| `base` | `string` | `"main"` | Default base branch for the `compare` and `visualize --diff` commands. Can be overridden per-invocation with `--base`. |
|
|
77
|
+
| `esbuild` | `object` | `{}` | esbuild [BuildOptions](https://esbuild.github.io/api/#build) overrides merged on top of the built-in defaults (`bundle`, `minify`, `platform: "node"`, `target: "node20"`, `cjs`). |
|
|
78
|
+
|
|
79
|
+
### Example in `package.json`
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"name": "my-service",
|
|
84
|
+
"bundle-analyser": {
|
|
85
|
+
"base": "develop",
|
|
86
|
+
"exclude": ["serverless.local-*.yml", "serverless.test.yml"],
|
|
87
|
+
"esbuild": {
|
|
88
|
+
"external": ["aws-sdk"]
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Examples
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# Compare affected functions against main
|
|
98
|
+
sls-bundle-analyser compare
|
|
99
|
+
|
|
100
|
+
# Compare all functions against a specific branch
|
|
101
|
+
sls-bundle-analyser compare --all --base feature-branch
|
|
102
|
+
|
|
103
|
+
# CI gate: fail if any function grew by more than 50KB
|
|
104
|
+
sls-bundle-analyser compare --all --fail-above 51200
|
|
105
|
+
|
|
106
|
+
# JSON output for scripting
|
|
107
|
+
sls-bundle-analyser compare --all --json
|
|
108
|
+
|
|
109
|
+
# Report all bundle sizes (no comparison)
|
|
110
|
+
sls-bundle-analyser sizes
|
|
111
|
+
|
|
112
|
+
# Bundle sizes sorted alphabetically, as JSON
|
|
113
|
+
sls-bundle-analyser sizes --sort name --json
|
|
114
|
+
|
|
115
|
+
# Visualize a single handler
|
|
116
|
+
sls-bundle-analyser visualize src/handlers/someHandler.ts
|
|
117
|
+
|
|
118
|
+
# Visualize only first-party code, top 10 modules, save to file
|
|
119
|
+
sls-bundle-analyser visualize src/handlers/someHandler.ts --no-third-party --top 10 --output report.html
|
|
120
|
+
|
|
121
|
+
# Side-by-side diff visualization against main
|
|
122
|
+
sls-bundle-analyser visualize src/handlers/someHandler.ts --diff
|
|
123
|
+
|
|
124
|
+
# Find most widely shared node_modules packages
|
|
125
|
+
sls-bundle-analyser shared-modules --top 10
|
|
126
|
+
```
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const compare_js_1 = require("./commands/compare.js");
|
|
6
|
+
const shared_modules_js_1 = require("./commands/shared-modules.js");
|
|
7
|
+
const sizes_js_1 = require("./commands/sizes.js");
|
|
8
|
+
const visualize_js_1 = require("./commands/visualize.js");
|
|
9
|
+
const program = new commander_1.Command()
|
|
10
|
+
.name("sls-bundle-analyser")
|
|
11
|
+
.description("Analyze bundle size changes for Serverless Framework Lambda functions.");
|
|
12
|
+
program
|
|
13
|
+
.command("compare")
|
|
14
|
+
.description("compare bundle sizes between current branch and a base branch")
|
|
15
|
+
.option("--base <branch>", "base branch to compare against")
|
|
16
|
+
.option("--all", "analyze all functions, not just those affected by changes")
|
|
17
|
+
.option("--verbose", "show per-module breakdown for each function")
|
|
18
|
+
.option("--json", "output raw JSON instead of text")
|
|
19
|
+
.option("--threshold <bytes>", "only show functions with delta above threshold (in bytes)", "0")
|
|
20
|
+
.option("--fail-above <bytes>", "exit with code 1 if any function grew more than this many bytes")
|
|
21
|
+
.action(compare_js_1.compareAction);
|
|
22
|
+
program
|
|
23
|
+
.command("sizes")
|
|
24
|
+
.description("report bundle sizes for all functions (no branch comparison)")
|
|
25
|
+
.option("--json", "output raw JSON")
|
|
26
|
+
.addOption(new commander_1.Option("--sort <field>", "sort order")
|
|
27
|
+
.choices(["size", "name"])
|
|
28
|
+
.default("size"))
|
|
29
|
+
.action(sizes_js_1.sizesAction);
|
|
30
|
+
program
|
|
31
|
+
.command("visualize")
|
|
32
|
+
.description("generate an interactive bundle treemap for a single entry point")
|
|
33
|
+
.argument("<entry-point>", "handler file to visualize")
|
|
34
|
+
.addOption(new commander_1.Option("--template <type>", "visualization type")
|
|
35
|
+
.choices(["treemap", "sunburst", "network"])
|
|
36
|
+
.default("treemap"))
|
|
37
|
+
.option("--no-third-party", "exclude node_modules from the visualization")
|
|
38
|
+
.option("--no-open", "generate the file without opening it in the browser")
|
|
39
|
+
.option("--output <path>", "write HTML to this path instead of opening in browser")
|
|
40
|
+
.option("--top <n>", "show only the N largest modules")
|
|
41
|
+
.option("--diff", "compare visualization against base branch")
|
|
42
|
+
.option("--base <branch>", "base branch for --diff (default: from config)")
|
|
43
|
+
.action(visualize_js_1.visualizeAction);
|
|
44
|
+
program
|
|
45
|
+
.command("shared-modules")
|
|
46
|
+
.description("find node_modules packages bundled across multiple Lambda functions")
|
|
47
|
+
.option("--json", "output raw JSON")
|
|
48
|
+
.option("--top <n>", "show only the top N modules", "20")
|
|
49
|
+
.action(shared_modules_js_1.sharedModulesAction);
|
|
50
|
+
program.parseAsync().catch((err) => {
|
|
51
|
+
console.error("Error:", err instanceof Error ? err.message : err);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAEA,yCAA2C;AAC3C,sDAAqD;AACrD,oEAAkE;AAClE,kDAAiD;AACjD,0DAAyD;AAEzD,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE;KAC3B,IAAI,CAAC,qBAAqB,CAAC;KAC3B,WAAW,CACX,wEAAwE,CACxE,CAAA;AAEF,OAAO;KACL,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,+DAA+D,CAAC;KAC5E,MAAM,CAAC,iBAAiB,EAAE,gCAAgC,CAAC;KAC3D,MAAM,CAAC,OAAO,EAAE,2DAA2D,CAAC;KAC5E,MAAM,CAAC,WAAW,EAAE,6CAA6C,CAAC;KAClE,MAAM,CAAC,QAAQ,EAAE,iCAAiC,CAAC;KACnD,MAAM,CACN,qBAAqB,EACrB,2DAA2D,EAC3D,GAAG,CACH;KACA,MAAM,CACN,sBAAsB,EACtB,iEAAiE,CACjE;KACA,MAAM,CAAC,0BAAa,CAAC,CAAA;AAEvB,OAAO;KACL,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC;KACnC,SAAS,CACT,IAAI,kBAAM,CAAC,gBAAgB,EAAE,YAAY,CAAC;KACxC,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,CAAU,CAAC;KAClC,OAAO,CAAC,MAAM,CAAC,CACjB;KACA,MAAM,CAAC,sBAAW,CAAC,CAAA;AAErB,OAAO;KACL,OAAO,CAAC,WAAW,CAAC;KACpB,WAAW,CACX,iEAAiE,CACjE;KACA,QAAQ,CAAC,eAAe,EAAE,2BAA2B,CAAC;KACtD,SAAS,CACT,IAAI,kBAAM,CAAC,mBAAmB,EAAE,oBAAoB,CAAC;KACnD,OAAO,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,CAAU,CAAC;KACpD,OAAO,CAAC,SAAS,CAAC,CACpB;KACA,MAAM,CAAC,kBAAkB,EAAE,6CAA6C,CAAC;KACzE,MAAM,CAAC,WAAW,EAAE,qDAAqD,CAAC;KAC1E,MAAM,CACN,iBAAiB,EACjB,uDAAuD,CACvD;KACA,MAAM,CAAC,WAAW,EAAE,iCAAiC,CAAC;KACtD,MAAM,CAAC,QAAQ,EAAE,2CAA2C,CAAC;KAC7D,MAAM,CAAC,iBAAiB,EAAE,+CAA+C,CAAC;KAC1E,MAAM,CAAC,8BAAe,CAAC,CAAA;AAEzB,OAAO;KACL,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CACX,qEAAqE,CACrE;KACA,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC;KACnC,MAAM,CAAC,WAAW,EAAE,6BAA6B,EAAE,IAAI,CAAC;KACxD,MAAM,CAAC,uCAAmB,CAAC,CAAA;AAE7B,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC3C,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAChB,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface CompareOpts {
|
|
2
|
+
base?: string;
|
|
3
|
+
all?: boolean;
|
|
4
|
+
verbose?: boolean;
|
|
5
|
+
json?: boolean;
|
|
6
|
+
threshold: string;
|
|
7
|
+
failAbove?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function compareAction(opts: CompareOpts): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=compare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../src/commands/compare.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,WAAW;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAyGpE"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.compareAction = compareAction;
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
const compare_js_1 = require("../compare.js");
|
|
6
|
+
const config_js_1 = require("../config.js");
|
|
7
|
+
const dependency_graph_js_1 = require("../dependency-graph.js");
|
|
8
|
+
const parse_serverless_js_1 = require("../parse-serverless.js");
|
|
9
|
+
const report_js_1 = require("../report.js");
|
|
10
|
+
async function compareAction(opts) {
|
|
11
|
+
const cwd = process.cwd();
|
|
12
|
+
const config = (0, config_js_1.loadConfig)(cwd);
|
|
13
|
+
const base = opts.base ?? config.base;
|
|
14
|
+
const all = opts.all === true;
|
|
15
|
+
const verbose = opts.verbose === true;
|
|
16
|
+
const json = opts.json === true;
|
|
17
|
+
const threshold = parseInt(opts.threshold, 10);
|
|
18
|
+
const failAbove = opts.failAbove ? parseInt(opts.failAbove, 10) : undefined;
|
|
19
|
+
// Step 1: Parse serverless files
|
|
20
|
+
process.stderr.write("Parsing serverless files...\n");
|
|
21
|
+
const parseResult = (0, parse_serverless_js_1.parseServerlessHandlers)(cwd, config.exclude);
|
|
22
|
+
if (parseResult.entries.size === 0) {
|
|
23
|
+
console.log("No serverless handler entry points found.");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
process.stderr.write(`Found ${parseResult.totalFunctions} functions (${parseResult.entries.size} unique entry points)\n`);
|
|
27
|
+
// Step 2: Build dependency graph
|
|
28
|
+
process.stderr.write("Building dependency graph...\n");
|
|
29
|
+
const graph = await (0, dependency_graph_js_1.buildDependencyGraph)(parseResult, config, cwd);
|
|
30
|
+
// Step 3: Determine affected entry points
|
|
31
|
+
const repoRoot = (0, compare_js_1.getRepoRoot)(cwd);
|
|
32
|
+
const changedFiles = (0, compare_js_1.getChangedFiles)(base, repoRoot);
|
|
33
|
+
const cwdRelative = (0, node_path_1.relative)(repoRoot, cwd);
|
|
34
|
+
// Filter changed files to those relevant to this service directory
|
|
35
|
+
const relevantChangedFiles = changedFiles.filter((f) => f.startsWith(`${cwdRelative}/`) || !cwdRelative);
|
|
36
|
+
let affectedEntryPoints;
|
|
37
|
+
if (all) {
|
|
38
|
+
affectedEntryPoints = new Set(Array.from(parseResult.entries.keys()).map((fp) => (0, node_path_1.relative)(cwd, fp)));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// Changed files in the dependency graph are relative to cwd (how esbuild reports them)
|
|
42
|
+
// But git diff returns paths relative to repo root
|
|
43
|
+
// We need to match them — the reverse map keys are relative to cwd (esbuild's absWorkingDir)
|
|
44
|
+
affectedEntryPoints = (0, dependency_graph_js_1.getAffectedEntryPoints)(changedFiles, graph.reverseMap);
|
|
45
|
+
// Also check with paths relative to cwd
|
|
46
|
+
const cwdRelativeChangedFiles = relevantChangedFiles.map((f) => (0, node_path_1.relative)(cwdRelative, f));
|
|
47
|
+
const moreAffected = (0, dependency_graph_js_1.getAffectedEntryPoints)(cwdRelativeChangedFiles, graph.reverseMap);
|
|
48
|
+
for (const ep of moreAffected) {
|
|
49
|
+
affectedEntryPoints.add(ep);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (affectedEntryPoints.size === 0) {
|
|
53
|
+
console.log("No affected functions — bundle sizes unchanged.");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
process.stderr.write(`${affectedEntryPoints.size} affected entry points, comparing against ${base}...\n`);
|
|
57
|
+
// Step 4: Compare bundles
|
|
58
|
+
const comparison = await (0, compare_js_1.compareBundles)(affectedEntryPoints, config, cwd);
|
|
59
|
+
// Step 5: Report
|
|
60
|
+
const reportData = (0, report_js_1.buildReportData)(comparison, relevantChangedFiles.length, parseResult.totalFunctions, cwd);
|
|
61
|
+
const reportOptions = {
|
|
62
|
+
verbose,
|
|
63
|
+
json,
|
|
64
|
+
threshold,
|
|
65
|
+
cwd,
|
|
66
|
+
};
|
|
67
|
+
if (json) {
|
|
68
|
+
console.log((0, report_js_1.formatJsonReport)(reportData));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
console.log((0, report_js_1.formatTextReport)(reportData, reportOptions));
|
|
72
|
+
}
|
|
73
|
+
// Step 6: Fail if any function grew more than the limit
|
|
74
|
+
if (failAbove != null) {
|
|
75
|
+
const exceeded = reportData.functions.some((f) => f.deltaBytes > failAbove);
|
|
76
|
+
if (exceeded) {
|
|
77
|
+
process.stderr.write(`One or more functions grew by more than ${failAbove} bytes.\n`);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=compare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare.js","sourceRoot":"","sources":["../../src/commands/compare.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-modules.d.ts","sourceRoot":"","sources":["../../src/commands/shared-modules.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,iBAAiB;IACjC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;CACX;AAED,wBAAsB,mBAAmB,CACxC,IAAI,EAAE,iBAAiB,GACrB,OAAO,CAAC,IAAI,CAAC,CA0Bf"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sharedModulesAction = sharedModulesAction;
|
|
4
|
+
const config_js_1 = require("../config.js");
|
|
5
|
+
const parse_serverless_js_1 = require("../parse-serverless.js");
|
|
6
|
+
const shared_modules_js_1 = require("../shared-modules.js");
|
|
7
|
+
async function sharedModulesAction(opts) {
|
|
8
|
+
const cwd = process.cwd();
|
|
9
|
+
const config = (0, config_js_1.loadConfig)(cwd);
|
|
10
|
+
process.stderr.write("Parsing serverless files...\n");
|
|
11
|
+
const parseResult = (0, parse_serverless_js_1.parseServerlessHandlers)(cwd, config.exclude);
|
|
12
|
+
if (parseResult.entries.size === 0) {
|
|
13
|
+
console.log("No serverless handler entry points found.");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
process.stderr.write(`Found ${parseResult.totalFunctions} functions (${parseResult.entries.size} unique entry points)\n`);
|
|
17
|
+
process.stderr.write("Analysing shared modules...\n");
|
|
18
|
+
const result = await (0, shared_modules_js_1.analyzeSharedModules)(parseResult, config, cwd);
|
|
19
|
+
const top = parseInt(opts.top, 10);
|
|
20
|
+
if (opts.json) {
|
|
21
|
+
console.log((0, shared_modules_js_1.formatSharedModulesJson)(result, top));
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
console.log((0, shared_modules_js_1.formatSharedModulesText)(result, top));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=shared-modules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-modules.js","sourceRoot":"","sources":["../../src/commands/shared-modules.ts"],"names":[],"mappings":";;AAaA,kDA4BC;AAzCD,4CAAyC;AACzC,gEAAgE;AAChE,4DAI6B;AAOtB,KAAK,UAAU,mBAAmB,CACxC,IAAuB;IAEvB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IACzB,MAAM,MAAM,GAAG,IAAA,sBAAU,EAAC,GAAG,CAAC,CAAA;IAE9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAA;IACrD,MAAM,WAAW,GAAG,IAAA,6CAAuB,EAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;IAEhE,IAAI,WAAW,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAA;QACxD,OAAM;IACP,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CACnB,SAAS,WAAW,CAAC,cAAc,eAAe,WAAW,CAAC,OAAO,CAAC,IAAI,yBAAyB,CACnG,CAAA;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAA;IACrD,MAAM,MAAM,GAAG,MAAM,IAAA,wCAAoB,EAAC,WAAW,EAAE,MAAM,EAAE,GAAG,CAAC,CAAA;IAEnE,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAElC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,IAAA,2CAAuB,EAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;IAClD,CAAC;SAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,IAAA,2CAAuB,EAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;IAClD,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sizes.d.ts","sourceRoot":"","sources":["../../src/commands/sizes.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,SAAS;IACzB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACZ;AA6CD,wBAAsB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA4ChE"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sizesAction = sizesAction;
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
const compare_js_1 = require("../compare.js");
|
|
6
|
+
const config_js_1 = require("../config.js");
|
|
7
|
+
const parse_serverless_js_1 = require("../parse-serverless.js");
|
|
8
|
+
const bold = (s) => `\x1b[1m${s}\x1b[0m`;
|
|
9
|
+
function formatBytes(bytes) {
|
|
10
|
+
if (bytes < 1024)
|
|
11
|
+
return `${bytes} B`;
|
|
12
|
+
if (bytes < 1024 * 1024)
|
|
13
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
14
|
+
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
15
|
+
}
|
|
16
|
+
function formatSizesText(functions, total) {
|
|
17
|
+
const lines = [];
|
|
18
|
+
lines.push(bold(`Bundle sizes — ${functions.length} of ${total} functions`));
|
|
19
|
+
lines.push("=".repeat(60));
|
|
20
|
+
if (functions.length === 0) {
|
|
21
|
+
lines.push("No functions found.");
|
|
22
|
+
return lines.join("\n");
|
|
23
|
+
}
|
|
24
|
+
const nameWidth = Math.max(30, ...functions.map((f) => f.entryPoint.length));
|
|
25
|
+
lines.push(` ${"Function".padEnd(nameWidth)} ${"Size".padStart(10)}`);
|
|
26
|
+
lines.push(` ${"─".repeat(nameWidth)} ${"─".repeat(10)}`);
|
|
27
|
+
for (const fn of functions) {
|
|
28
|
+
lines.push(` ${fn.entryPoint.padEnd(nameWidth)} ${formatBytes(fn.bytes).padStart(10)}`);
|
|
29
|
+
}
|
|
30
|
+
const totalBytes = functions.reduce((sum, f) => sum + f.bytes, 0);
|
|
31
|
+
lines.push("");
|
|
32
|
+
lines.push(` ${"Total".padEnd(nameWidth)} ${formatBytes(totalBytes).padStart(10)}`);
|
|
33
|
+
return lines.join("\n");
|
|
34
|
+
}
|
|
35
|
+
async function sizesAction(opts) {
|
|
36
|
+
const cwd = process.cwd();
|
|
37
|
+
const config = (0, config_js_1.loadConfig)(cwd);
|
|
38
|
+
process.stderr.write("Parsing serverless files...\n");
|
|
39
|
+
const parseResult = (0, parse_serverless_js_1.parseServerlessHandlers)(cwd, config.exclude);
|
|
40
|
+
if (parseResult.entries.size === 0) {
|
|
41
|
+
console.log("No serverless handler entry points found.");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
process.stderr.write(`Found ${parseResult.totalFunctions} functions (${parseResult.entries.size} unique entry points)\n`);
|
|
45
|
+
// Build entry points map
|
|
46
|
+
const entryPoints = {};
|
|
47
|
+
for (const [absPath] of parseResult.entries) {
|
|
48
|
+
const rel = (0, node_path_1.relative)(cwd, absPath);
|
|
49
|
+
entryPoints[rel] = (0, node_path_1.join)(cwd, rel);
|
|
50
|
+
}
|
|
51
|
+
process.stderr.write("Bundling...\n");
|
|
52
|
+
const sizes = await (0, compare_js_1.bundleAndMeasure)(entryPoints, config, cwd);
|
|
53
|
+
const functions = Array.from(sizes.entries()).map(([ep, size]) => ({
|
|
54
|
+
entryPoint: ep,
|
|
55
|
+
bytes: size.bytes,
|
|
56
|
+
}));
|
|
57
|
+
if (opts.sort === "name") {
|
|
58
|
+
functions.sort((a, b) => a.entryPoint.localeCompare(b.entryPoint));
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
functions.sort((a, b) => b.bytes - a.bytes);
|
|
62
|
+
}
|
|
63
|
+
if (opts.json) {
|
|
64
|
+
console.log(JSON.stringify({ functions }, null, 2));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
console.log(formatSizesText(functions, parseResult.totalFunctions));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=sizes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sizes.js","sourceRoot":"","sources":["../../src/commands/sizes.ts"],"names":[],"mappings":";;AAqDA,kCA4CC;AAjGD,yCAA0C;AAC1C,8CAAgD;AAChD,4CAAyC;AACzC,gEAAgE;AAYhE,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,UAAU,CAAC,SAAS,CAAA;AAExD,SAAS,WAAW,CAAC,KAAa;IACjC,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,IAAI,CAAA;IACrC,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;IACjE,OAAO,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;AAClD,CAAC;AAED,SAAS,eAAe,CAAC,SAAyB,EAAE,KAAa;IAChE,MAAM,KAAK,GAAa,EAAE,CAAA;IAE1B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,SAAS,CAAC,MAAM,OAAO,KAAK,YAAY,CAAC,CAAC,CAAA;IAC5E,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;IAE1B,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;QACjC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACxB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAA;IAC5E,KAAK,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IACvE,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IAE3D,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CACT,KAAK,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,WAAW,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAC7E,CAAA;IACF,CAAC;IAED,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IACjE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CACT,KAAK,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,WAAW,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CACzE,CAAA;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACxB,CAAC;AAEM,KAAK,UAAU,WAAW,CAAC,IAAe;IAChD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IACzB,MAAM,MAAM,GAAG,IAAA,sBAAU,EAAC,GAAG,CAAC,CAAA;IAE9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAA;IACrD,MAAM,WAAW,GAAG,IAAA,6CAAuB,EAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;IAEhE,IAAI,WAAW,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAA;QACxD,OAAM;IACP,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CACnB,SAAS,WAAW,CAAC,cAAc,eAAe,WAAW,CAAC,OAAO,CAAC,IAAI,yBAAyB,CACnG,CAAA;IAED,yBAAyB;IACzB,MAAM,WAAW,GAA2B,EAAE,CAAA;IAC9C,KAAK,MAAM,CAAC,OAAO,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;QAC7C,MAAM,GAAG,GAAG,IAAA,oBAAQ,EAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QAClC,WAAW,CAAC,GAAG,CAAC,GAAG,IAAA,gBAAI,EAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IAClC,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;IACrC,MAAM,KAAK,GAAG,MAAM,IAAA,6BAAgB,EAAC,WAAW,EAAE,MAAM,EAAE,GAAG,CAAC,CAAA;IAE9D,MAAM,SAAS,GAAmB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAChE,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAChB,UAAU,EAAE,EAAE;QACd,KAAK,EAAE,IAAI,CAAC,KAAK;KACjB,CAAC,CACF,CAAA;IAED,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC1B,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;IACnE,CAAC;SAAM,CAAC;QACP,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAA;IAC5C,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IACpD,CAAC;SAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,SAAS,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC,CAAA;IACpE,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface VisualizeOpts {
|
|
2
|
+
template: string;
|
|
3
|
+
thirdParty: boolean;
|
|
4
|
+
open: boolean;
|
|
5
|
+
output?: string;
|
|
6
|
+
top?: string;
|
|
7
|
+
diff?: boolean;
|
|
8
|
+
base?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function visualizeAction(entryPoint: string, opts: VisualizeOpts): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=visualize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visualize.d.ts","sourceRoot":"","sources":["../../src/commands/visualize.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,OAAO,CAAA;IACnB,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;CACb;AAED,wBAAsB,eAAe,CACpC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,aAAa,GACjB,OAAO,CAAC,IAAI,CAAC,CAkCf"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.visualizeAction = visualizeAction;
|
|
4
|
+
const config_js_1 = require("../config.js");
|
|
5
|
+
const visualize_js_1 = require("../visualize.js");
|
|
6
|
+
async function visualizeAction(entryPoint, opts) {
|
|
7
|
+
const cwd = process.cwd();
|
|
8
|
+
const config = (0, config_js_1.loadConfig)(cwd);
|
|
9
|
+
const vizOptions = {
|
|
10
|
+
template: opts.template,
|
|
11
|
+
excludeThirdParty: !opts.thirdParty,
|
|
12
|
+
top: opts.top ? parseInt(opts.top, 10) : undefined,
|
|
13
|
+
outputPath: opts.output,
|
|
14
|
+
open: opts.open,
|
|
15
|
+
};
|
|
16
|
+
if (opts.diff) {
|
|
17
|
+
const base = opts.base ?? config.base;
|
|
18
|
+
process.stderr.write(`Bundling ${entryPoint} (current vs ${base})...\n`);
|
|
19
|
+
const { currentPath, basePath } = await (0, visualize_js_1.visualizeDiff)(entryPoint, config, cwd, base, vizOptions);
|
|
20
|
+
process.stderr.write(`Current: ${currentPath}\n`);
|
|
21
|
+
process.stderr.write(`Base: ${basePath}\n`);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
process.stderr.write(`Bundling ${entryPoint}...\n`);
|
|
25
|
+
const outPath = await (0, visualize_js_1.visualizeEntryPoint)(entryPoint, config, cwd, vizOptions);
|
|
26
|
+
process.stderr.write(`Written to ${outPath}\n`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=visualize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visualize.js","sourceRoot":"","sources":["../../src/commands/visualize.ts"],"names":[],"mappings":";;AAiBA,0CAqCC;AAtDD,4CAAyC;AACzC,kDAIwB;AAYjB,KAAK,UAAU,eAAe,CACpC,UAAkB,EAClB,IAAmB;IAEnB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IACzB,MAAM,MAAM,GAAG,IAAA,sBAAU,EAAC,GAAG,CAAC,CAAA;IAE9B,MAAM,UAAU,GAAqB;QACpC,QAAQ,EAAE,IAAI,CAAC,QAA8C;QAC7D,iBAAiB,EAAE,CAAC,IAAI,CAAC,UAAU;QACnC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;QAClD,UAAU,EAAE,IAAI,CAAC,MAAM;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI;KACf,CAAA;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAA;QACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,UAAU,gBAAgB,IAAI,QAAQ,CAAC,CAAA;QACxE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAA,4BAAa,EACpD,UAAU,EACV,MAAM,EACN,GAAG,EACH,IAAI,EACJ,UAAU,CACV,CAAA;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,WAAW,IAAI,CAAC,CAAA;QACjD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,QAAQ,IAAI,CAAC,CAAA;IAC/C,CAAC;SAAM,CAAC;QACP,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,UAAU,OAAO,CAAC,CAAA;QACnD,MAAM,OAAO,GAAG,MAAM,IAAA,kCAAmB,EACxC,UAAU,EACV,MAAM,EACN,GAAG,EACH,UAAU,CACV,CAAA;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,OAAO,IAAI,CAAC,CAAA;IAChD,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type Metafile } from "esbuild";
|
|
2
|
+
import type { BundleAnalyserConfig } from "./config.js";
|
|
3
|
+
export interface BundleSize {
|
|
4
|
+
/** Total output bytes for this entry point */
|
|
5
|
+
bytes: number;
|
|
6
|
+
/** Per-input-module sizes */
|
|
7
|
+
modules: Map<string, number>;
|
|
8
|
+
}
|
|
9
|
+
export interface ComparisonResult {
|
|
10
|
+
/** Entry point key (relative path) -> sizes on current branch */
|
|
11
|
+
current: Map<string, BundleSize>;
|
|
12
|
+
/** Entry point key (relative path) -> sizes on base branch (missing = new function) */
|
|
13
|
+
base: Map<string, BundleSize>;
|
|
14
|
+
/** Entry points that exist on branch but not on base */
|
|
15
|
+
newEntryPoints: Set<string>;
|
|
16
|
+
/** Entry points that exist on base but not on branch */
|
|
17
|
+
removedEntryPoints: Set<string>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get files changed between the base branch and HEAD.
|
|
21
|
+
* Returns paths relative to the repo root.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getChangedFiles(base: string, repoRoot: string): string[];
|
|
24
|
+
/**
|
|
25
|
+
* Find the root of the git repository.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getRepoRoot(cwd: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Bundle the specified entry points and return their sizes from the metafile.
|
|
30
|
+
* Batches entry points to avoid overwhelming esbuild's IPC.
|
|
31
|
+
*/
|
|
32
|
+
export declare function bundleAndMeasure(entryPoints: Record<string, string>, config: BundleAnalyserConfig, cwd: string): Promise<Map<string, BundleSize>>;
|
|
33
|
+
export declare function extractSizes(metafile: Metafile): Map<string, BundleSize>;
|
|
34
|
+
/**
|
|
35
|
+
* Compare bundle sizes between the current branch and the base branch.
|
|
36
|
+
*
|
|
37
|
+
* Uses git worktree to checkout the base branch without disturbing the working directory.
|
|
38
|
+
*/
|
|
39
|
+
export declare function compareBundles(affectedEntryPoints: Set<string>, config: BundleAnalyserConfig, cwd: string): Promise<ComparisonResult>;
|
|
40
|
+
/**
|
|
41
|
+
* Run a function against a git worktree checked out at the given branch.
|
|
42
|
+
*
|
|
43
|
+
* Creates a temporary worktree, symlinks node_modules, calls `fn` with the
|
|
44
|
+
* worktree-equivalent of `cwd`, and cleans up afterwards.
|
|
45
|
+
*/
|
|
46
|
+
export declare function withWorktree<T>(branch: string, cwd: string, fn: (worktreeCwd: string) => Promise<T>): Promise<T>;
|
|
47
|
+
//# sourceMappingURL=compare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../src/compare.ts"],"names":[],"mappings":"AAIA,OAAO,EAAS,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAC9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAGvD,MAAM,WAAW,UAAU;IAC1B,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAA;IACb,6BAA6B;IAC7B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAChC,iEAAiE;IACjE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IAChC,uFAAuF;IACvF,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IAC7B,wDAAwD;IACxD,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC3B,wDAAwD;IACxD,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAC/B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAcxE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK/C;AAID;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,MAAM,EAAE,oBAAoB,EAC5B,GAAG,EAAE,MAAM,GACT,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CA4BlC;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAgBxE;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CACnC,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,EAChC,MAAM,EAAE,oBAAoB,EAC5B,GAAG,EAAE,MAAM,GACT,OAAO,CAAC,gBAAgB,CAAC,CAyB3B;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,CAAC,EACnC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GACrC,OAAO,CAAC,CAAC,CAAC,CA4BZ"}
|