Skip to content

Commit 16e22db

Browse files
committed
Add bundle size optimization plan
1 parent d954a19 commit 16e22db

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed

BUNDLE_SIZE_PLAN.md

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# Bundle Size Optimization Plan
2+
3+
## Goal
4+
5+
Reduce `@actions/languageservice` package size from **7.9 MB** to **~1.5 MB** (80% reduction).
6+
7+
## Summary
8+
9+
| Phase | Change | Savings | Effort |
10+
|-------|--------|---------|--------|
11+
| 1a | Minify all JSON | 60% | Low |
12+
| 1b | Strip unused fields | 10% | Low |
13+
| 1c | Drop unused events | 19% | Low |
14+
| 2 | Lazy-load webhooks.json (optional) | Faster initial load | Medium |
15+
16+
## Phase 1: Optimize JSON files
17+
18+
### What each JSON file is used for
19+
20+
| File | Package | Purpose |
21+
|------|---------|---------|
22+
| `webhooks.json` | languageservice | Autocomplete/validation for `github.event.*` expressions. Contains event payload schemas from GitHub's REST API. |
23+
| `objects.json` | languageservice | Deduplicated parameter definitions shared across webhooks (reduces duplication in webhooks.json). |
24+
| `workflow-v1.0.json` | workflow-parser | Workflow schema defining valid YAML structure (`jobs`, `steps`, `runs-on`, event triggers, etc.). |
25+
| `descriptions.json` | languageservice | Hover descriptions for contexts (`github`, `env`, `secrets`) and built-in functions (`format`, `contains`, etc.). |
26+
| `schedule.json` | languageservice | Sample `github.event` payload for `on: schedule` trigger (not a real webhook, manually authored). |
27+
| `workflow_call.json` | languageservice | Sample `github.event` payload for `on: workflow_call` trigger (not a real webhook, manually authored). |
28+
29+
### Impact table
30+
31+
| File | Original | Strip | Drop | Minify | Gzip | All (no Gzip) | All (w/ Gzip) |
32+
|------|----------|-------|------|--------|------|---------------|---------------|
33+
| `webhooks.json` | 6.2 MB | 5.6 MB | 5.0 MB | 2.4 MB | 188 KB | **1.0 MB** | **50 KB** |
34+
| `objects.json` | 948 KB | N/A | 770 KB | 460 KB | 36 KB | **180 KB** | **18 KB** |
35+
| `workflow-v1.0.json` | 112 KB | N/A | N/A | 70 KB | 13 KB | **70 KB** | **12 KB** |
36+
| `descriptions.json` | 18 KB | N/A | N/A | 17 KB | 3 KB | **17 KB** | **3 KB** |
37+
| `schedule.json` | 5.7 KB | N/A | N/A | 5.1 KB | 1 KB | **5.1 KB** | **1 KB** |
38+
| `workflow_call.json` | 7.3 KB | N/A | N/A | 6.5 KB | 1 KB | **6.5 KB** | **1 KB** |
39+
| **Total** | **7.3 MB** | | | | **~240 KB** | **~1.3 MB** | **~85 KB** |
40+
41+
- **Strip** = Remove unused fields (`summary`, `availability`, `category`, `action`)
42+
- **Drop** = Remove 31 non-trigger events (`installation`, `star`, `team`, etc.)
43+
- **Minify** = Remove whitespace (`JSON.stringify(data)` instead of `JSON.stringify(data, null, 2)`)
44+
- **Gzip** = Network transfer size (free - handled automatically by browser/server)
45+
46+
### 1a. Minify all JSON files
47+
48+
**Generated files** (`webhooks.json`, `objects.json`):
49+
- Update `languageservice/script/webhooks/index.ts`
50+
- These are generated via `npm run update-webhooks` from GitHub's REST API spec
51+
- Use `JSON.stringify(data)` instead of `JSON.stringify(data, null, 2)`
52+
53+
**Hand-authored files** (`workflow-v1.0.json`, `descriptions.json`, `schedule.json`, `workflow_call.json`):
54+
- Add minification step to build scripts
55+
56+
### 1b. Strip unused fields from webhooks.json
57+
58+
Remove before writing:
59+
- `summary`
60+
- `availability`
61+
- `category`
62+
- `action`
63+
64+
### 1c. Drop non-trigger events from webhooks.json
65+
66+
Keep only events that can trigger workflows ([docs](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows)). Drop 31 events:
67+
68+
```
69+
code_scanning_alert, commit_comment, dependabot_alert, deploy_key,
70+
github_app_authorization, installation, installation_repositories,
71+
installation_target, marketplace_purchase, member, membership, meta,
72+
org_block, organization, package, ping, projects_v2, projects_v2_item,
73+
pull_request_review_thread, repository, repository_import,
74+
repository_vulnerability_alert, secret_scanning_alert,
75+
secret_scanning_alert_location, security_advisory, security_and_analysis,
76+
sponsorship, star, team, team_add, workflow_job
77+
```
78+
79+
**Expected result:** Total JSON 7.3 MB → ~1.3 MB (82% reduction)
80+
81+
---
82+
83+
## Phase 2: Lazy loading (optional)
84+
85+
Refactor `eventPayloads.ts` to load JSON on first use:
86+
87+
```typescript
88+
let webhooksData: Webhooks | null = null;
89+
90+
async function getWebhooks() {
91+
if (!webhooksData) {
92+
const { default: data } = await import("./webhooks.json");
93+
webhooksData = hydrate(data);
94+
}
95+
return webhooksData;
96+
}
97+
```
98+
99+
**Benefit:** Faster initial load when `github.event.*` isn't used.
100+
101+
---
102+
103+
## Current github-ui architecture
104+
105+
github-ui lazy-loads the language service via dynamic import:
106+
107+
```typescript
108+
// workflow-editor-next.ts
109+
let languageServicePromise: Promise<typeof import('./workflow-editor-language-service')> | null = null
110+
111+
async function getLanguageServiceModule() {
112+
if (!languageServicePromise) {
113+
languageServicePromise = import('./workflow-editor-language-service')
114+
}
115+
return languageServicePromise
116+
}
117+
```
118+
119+
**What this means:**
120+
- The language service is only loaded when the workflow editor needs autocomplete/hover/validation
121+
- Webpack code-splits it into a separate chunk
122+
- The ~7.9 MB package is NOT loaded on initial page load
123+
124+
**Why Phase 1 is the priority:**
125+
- When the language service chunk IS loaded, it still loads all 7.3 MB of JSON
126+
- Reducing JSON to ~1.3 MB directly reduces this chunk size
127+
- No changes needed in github-ui - the benefit is automatic
128+
129+
---
130+
131+
## Not doing
132+
133+
- **Tree-shaking / `sideEffects`** - github-ui imports `complete`, `hover`, and `validate` together, and all three depend on the same webhook JSON. Tree-shaking can't eliminate any of it.
134+
- **Replacing dependencies** - `yaml` and `cronstrue` are appropriately sized
135+
- **Multi-pass validation API** - Too complex for the benefit
136+
- **Further deduplication** - Current object deduplication is sufficient
137+
138+
---
139+
140+
## Future considerations
141+
142+
- **`workflow_call.json` may be incorrect** - For `on: workflow_call`, `github.event` is inherited from the calling workflow (could be push, pull_request, etc.). The current file shows generic properties which may be misleading for autocomplete. Consider returning `Null` for all modes or removing the file entirely.
143+
144+
---
145+
146+
## Success metrics
147+
148+
| Metric | Before | After |
149+
|--------|--------|-------|
150+
| `webhooks.json` | 6.2 MB | ~1.2 MB |
151+
| `objects.json` | 948 KB | ~225 KB |
152+
| Total package (disk) | 7.9 MB | ~1.5 MB |
153+
| npm tarball (gzipped) | 368 KB | ~80 KB |

0 commit comments

Comments
 (0)