Skip to content

Commit 37736e4

Browse files
committed
2 parents aa6f63c + 4528598 commit 37736e4

30 files changed

+4758
-367
lines changed

docs/vite8-upgrade-status.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# Vite 8 + Rolldown Upgrade — Status & Testing Guide
2+
3+
**Branch:** `feat/AG-17612-vite-dynamic-imports-and-esm-externals`
4+
**Date:** 2026-02-24
5+
6+
---
7+
8+
## Current Status
9+
10+
All code changes are complete in octane. TypeScript compiles cleanly, lint passes, and all 71 tests pass. The changes have **not yet been tested** with a real MFE build — the local prod server was serving stale assets from a previous build.
11+
12+
---
13+
14+
## What Changed (Summary)
15+
16+
| File | Change |
17+
|------|--------|
18+
| `packages/gdu/package.json` | `vite` bumped from `^7.0.0` to `^8.0.0-beta.0`; added `peerDependencyMeta` for `@vanilla-extract/vite-plugin` |
19+
| `packages/gdu/config/vite/types.ts` | Renamed `Rollup*` types to `Rolldown*`; added `oxc` config type alongside existing `esbuild` type; `minify` type widened to `boolean \| string` |
20+
| `packages/gdu/config/vite/vite.config.ts` | `rollupOptions` renamed to `rolldownOptions`; `minify: 'esbuild'` changed to `minify: true` (OXC minifier); added `oxc` config block for JSX transform; kept `esbuild` config for `pure` + `legalComments` (deprecated but functional in Vite 8) |
21+
| `packages/gdu/commands/build/buildSPA-vite.ts` | `esmExternalRequirePlugin` imported from `'vite'` instead of `'rolldown/plugins'`; **fixed bug** where `external: undefined` was set when the plugin loaded (would have bundled all externals); simplified merge config |
22+
| `packages/gdu/commands/start/runSPA-vite.ts` | Added `oxc: base.oxc` for JSX in dev; `esbuild.pure` cleared for dev mode |
23+
| `.changeset/vite-dynamic-imports-esm-externals.md` | Updated to `minor` bump with Vite 8 upgrade description |
24+
25+
---
26+
27+
## Key Architectural Decisions
28+
29+
### OXC vs esbuild coexistence
30+
31+
Vite 8 introduces `oxc` as the new transform engine and deprecates `esbuild`. However, both can coexist:
32+
33+
- **`oxc`** handles JSX/TS transforms (the `jsx: { runtime: 'automatic', importSource: 'react' }` config)
34+
- **`esbuild`** (deprecated but functional) handles the renderChunk pass for `pure` (console stripping) and `legalComments: 'none'`
35+
36+
There is no direct OXC equivalent of esbuild's `pure: ['console.log', ...]` option. Rolldown's minifier has `dropConsole: boolean` in `CompressOptions`, but that drops **all** console methods including `console.error`. Our config selectively strips `log`, `info`, `debug`, and `warn` while preserving `error`.
37+
38+
**Note:** With `minify: true` (OXC minifier), the esbuild renderChunk plugin runs for target downlevelling but with `treeShaking: false`, so the `pure` annotations may not actually strip console calls in the final output. If console stripping is critical, consider either:
39+
1. Changing `minify` to `'esbuild'` (keeps esbuild as the minifier)
40+
2. Using `define` to replace console methods with no-ops: `'console.log': '(()=>{})'`
41+
42+
### The external removal bug fix
43+
44+
The previous code had:
45+
```ts
46+
...(hasEsmExternalPlugin ? { external: undefined } : {})
47+
```
48+
This would set `external` to `undefined` when `esmExternalRequirePlugin` loaded successfully — effectively removing all externals from the Rolldown config and causing them to be bundled into the output. The `esmExternalRequirePlugin` is designed to **coexist** with `external`, not replace it. The plugin handles CJS `require()` shims while `external` keeps the modules out of the bundle.
49+
50+
---
51+
52+
## How to Test with fmo-booking
53+
54+
### Step 1: Build gdu in octane
55+
56+
```bash
57+
cd ~/Documents/GitHub/octane
58+
yarn workspace gdu build
59+
```
60+
61+
### Step 2: Copy gdu build to MFE
62+
63+
```bash
64+
cd ~/Documents/GitHub/mfe
65+
yarn gdu:local
66+
```
67+
68+
This runs `.scripts/copy-gdu.js` which:
69+
1. Builds gdu in the sibling `octane` repo (`yarn workspace gdu build`)
70+
2. Copies `octane/packages/gdu/dist/` to `mfe/node_modules/gdu/dist/`
71+
3. Copies `octane/packages/gdu/entry/` to `mfe/node_modules/gdu/entry/`
72+
4. Copies `octane/packages/babel-preset/` to `mfe/node_modules/@autoguru/babel-preset/`
73+
74+
**Important:** The `copy-gdu.js` script runs its own `yarn workspace gdu build` internally, so you don't strictly need Step 1 separately. However, running it first lets you catch TypeScript errors before copying.
75+
76+
### Step 3: Ensure Vite 8 is installed in MFE
77+
78+
The MFE's `node_modules/gdu/node_modules/vite` (or the hoisted `node_modules/vite`) must be Vite 8. Since `gdu:local` only copies the `dist/` and `entry/` directories, it does **not** update `node_modules/vite`.
79+
80+
You need to ensure the MFE has Vite 8 available. The simplest approach:
81+
82+
```bash
83+
cd ~/Documents/GitHub/mfe
84+
85+
# Check current vite version
86+
node -e "console.log(require('vite/package.json').version)"
87+
88+
# If it's still 7.x, you may need to manually update or add a resolutions override
89+
# in the MFE root package.json:
90+
# "resolutions": { "vite": "8.0.0-beta.15" }
91+
# Then run:
92+
yarn install
93+
```
94+
95+
### Step 4: Build fmo-booking
96+
97+
```bash
98+
cd ~/Documents/GitHub/mfe
99+
APP_ENV=dev_au yarn workspace @autoguru/fmo-booking build:mfe
100+
```
101+
102+
### Step 5: Verify the build output
103+
104+
```bash
105+
# Check build manifest exists
106+
cat apps/fmo-booking/dist/dev_au/build-manifest.json | jq .
107+
108+
# Check the main JS bundle imports externals from esm.sh (not bundled inline)
109+
head -5 apps/fmo-booking/dist/dev_au/main-*.js
110+
111+
# Check for external import specifiers in the bundle
112+
grep -c 'esm.sh' apps/fmo-booking/dist/dev_au/main-*.js
113+
114+
# Check bundle size (should be significantly smaller than 2.6 MB)
115+
du -sh apps/fmo-booking/dist/dev_au/main-*.js
116+
```
117+
118+
**What to look for:**
119+
- The main JS should have `import` statements pointing to `esm.sh` URLs for react, react-dom, @datadog/*, etc.
120+
- These modules should NOT be bundled inline
121+
- Bundle size should be significantly smaller than 2.6 MB
122+
123+
### Step 6: Test with the local prod server
124+
125+
```bash
126+
# Kill any existing server on port 8080
127+
lsof -ti :8080 | xargs kill -9 2>/dev/null
128+
129+
# Start fresh server (reads build manifest at startup)
130+
node .scripts/mfe-local-prod-server.js fmo-booking dev au 8080
131+
```
132+
133+
Then open: http://localhost:8080/au/custom-fleet/booking
134+
135+
**Important:** The local prod server caches `build-manifest.json` at startup. If you rebuild, you **must** restart the server to pick up the new asset hashes.
136+
137+
---
138+
139+
## What Was Tried During Investigation
140+
141+
### Browser debugging session
142+
143+
Navigated to `http://localhost:8080/au/custom-fleet/booking?status=COMPLETED&...` and found:
144+
145+
1. **Page was blank** — only the environment banner and empty `<div id="__app__">` rendered
146+
2. **Network tab showed 4 requests**, all returning HTTP 200:
147+
- The HTML document
148+
- `main-DZvqnZTf.css` (200)
149+
- `main-Cm3RdaoF.js` (200)
150+
- `favicon.ico` (200)
151+
3. **The JS file was returning HTML**`curl http://localhost:8080/main-Cm3RdaoF.js` returned the SPA fallback HTML, not JavaScript
152+
4. **Root cause:** The build manifest on disk contained `main-B8JrHicf.js` but the server was serving HTML referencing `main-Cm3RdaoF.js` — the server had been started with an older build and the manifest was cached at startup. The hash mismatch meant `express.static` couldn't find the file, so the catch-all `app.get('*')` returned HTML instead
153+
154+
### Verification completed
155+
156+
- `tsc --noEmit` — passes (no type errors)
157+
- `yarn lint` — passes
158+
- `yarn test` — all 71 tests pass (11 suites)
159+
- `yarn install` — resolved Vite 8.0.0-beta.15 + Rolldown 1.0.0-rc.5 successfully
160+
- `esmExternalRequirePlugin` — confirmed exported from `vite` in v8 (`typeof vite.esmExternalRequirePlugin === 'function'`)
161+
- Rolldown `OutputOptions.paths` — confirmed supported (for external URL rewriting)
162+
163+
---
164+
165+
## Known Risks
166+
167+
1. **Vite 8 is beta** (`8.0.0-beta.15`) — may have undiscovered bugs
168+
2. **`@vanilla-extract/vite-plugin`** doesn't list `vite@8` in peer deps — added `peerDependencyMeta` override to suppress warnings. Rolldown supports Rollup plugins so it should work, but untested with this specific combination
169+
3. **`esbuild.pure` may not strip console calls** with `minify: true` (OXC) — the esbuild renderChunk plugin runs for target downlevelling but with `treeShaking: false`. Verify by checking if `console.log` appears in production bundles
170+
4. **Rolldown output format differences** — subtle differences between Rollup and Rolldown ES module output could cause runtime issues. Verify by checking import/export shapes in the bundle

packages/browserslist-config/__snapshots__/test.spec.js.snap

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ Array [
1212
"chrome 136",
1313
"chrome 135",
1414
"chrome 134",
15-
"chrome 133",
16-
"chrome 132",
1715
"edge 140",
1816
"edge 139",
1917
"edge 138",
@@ -22,24 +20,20 @@ Array [
2220
"edge 135",
2321
"edge 134",
2422
"edge 133",
25-
"edge 132",
2623
"firefox 142",
2724
"firefox 141",
2825
"firefox 140",
2926
"firefox 139",
3027
"firefox 138",
3128
"firefox 137",
3229
"firefox 136",
33-
"firefox 135",
3430
"ios_saf 26.0",
3531
"ios_saf 18.5-18.6",
3632
"ios_saf 18.4",
37-
"ios_saf 18.3",
3833
"opera 121",
3934
"opera 120",
4035
"opera 119",
4136
"opera 118",
42-
"opera 117",
4337
"safari 26.0",
4438
"safari 18.5-18.6",
4539
"safari 18.4",

0 commit comments

Comments
 (0)