diff --git a/Makefile b/Makefile index 46314ea990..4408e23031 100644 --- a/Makefile +++ b/Makefile @@ -97,12 +97,12 @@ dep_web: # Uses publicPath patching instead of a full second React build (~4-8 min savings). # # Idempotent: skips when `build/electron-app/app/index.html` already carries -# the patched `es6://static/js/main` marker. This mirrors the original +# the patched `es6://assets/` marker. This mirrors the original # Makefile's skip semantics so downstream targets that re-declare `dep` as a # prerequisite (e.g. `mac_x64`, `win_x64`) do not repeatedly re-copy the web # bundle. Set `FORCE_DEP_ELECTRON=1` to force a re-sync. dep_electron: dep_web - @if [ -f "./build/electron-app/app/index.html" ] && grep -q 'es6://static/js/main' ./build/electron-app/app/index.html && [ "$(FORCE_DEP_ELECTRON)" != "1" ]; then \ + @if [ -f "./build/electron-app/app/index.html" ] && grep -q 'es6://assets/' ./build/electron-app/app/index.html && [ "$(FORCE_DEP_ELECTRON)" != "1" ]; then \ printf "$(YELLOW)Electron app already prepared, skipping$(NC)\n"; \ else \ if [ ! -d "./build/electron-app" ]; then \ @@ -110,14 +110,14 @@ dep_electron: dep_web cp -r electron-app/* build/electron-app/; \ cp electron-app/.npmrc build/electron-app/; \ pnpm i --prefix ./build/electron-app --ignore-workspace; \ - fi; \ - rm -rf build/electron-app/app build/electron-app/resources build/electron-app/manifest; \ - cp -Rp build/web build/electron-app/app; \ - cp -Rp build/web/resources build/electron-app; \ - cp -Rp build/web/manifest build/electron-app; \ - node scripts/patch-electron-publicpath.js build/electron-app/app; \ - mkdir -p ./build/electron-app/app/wsproxy; \ - cp ./src/wsproxy/dist/wsproxy.js ./build/electron-app/app/wsproxy/wsproxy.js; \ + fi && \ + rm -rf build/electron-app/app build/electron-app/resources build/electron-app/manifest && \ + cp -Rp build/web build/electron-app/app && \ + cp -Rp build/web/resources build/electron-app && \ + cp -Rp build/web/manifest build/electron-app && \ + node scripts/patch-electron-publicpath.js build/electron-app/app && \ + mkdir -p ./build/electron-app/app/wsproxy && \ + cp ./src/wsproxy/dist/wsproxy.js ./build/electron-app/app/wsproxy/wsproxy.js && \ cp ./preload.js ./build/electron-app/preload.js; \ fi dep: dep_electron diff --git a/react/package.json b/react/package.json index e400727ad3..2162c4b40b 100644 --- a/react/package.json +++ b/react/package.json @@ -23,7 +23,6 @@ "@microsoft/fetch-event-source": "^2.0.1", "@monaco-editor/react": "^4.7.0", "@react-hook/resize-observer": "^2.0.2", - "@svgr/webpack": "^8.1.0", "@tanstack/react-query": "catalog:", "@testing-library/react": "catalog:", "@uiw/codemirror-extensions-langs": "^4.25.9", @@ -152,9 +151,7 @@ "jsdom": "^29.0.2", "nodemon": "^3.1.14", "prop-types": "^15.8.1", - "react-dev-utils": "^12.0.1", "react-grab": "^0.1.32", - "react-scripts": "5.0.1", "react-test-renderer": "^19.2.5", "relay-compiler": "catalog:", "relay-test-utils": "catalog:", diff --git a/react/vite.config.ts b/react/vite.config.ts index b7b740a756..8dd851a4ce 100644 --- a/react/vite.config.ts +++ b/react/vite.config.ts @@ -278,7 +278,7 @@ function monacoStaticPlugin(): Plugin { }; } -export default defineConfig(({ command, mode }) => { +export default defineConfig(({ mode }) => { const env = loadEnv(mode, projectRoot, ''); Object.assign(process.env, env); @@ -297,31 +297,11 @@ export default defineConfig(({ command, mode }) => { .filter(Boolean) : undefined; - // Electron target uses a custom `es6://` URL scheme; the main process - // registers a protocol handler via `protocol.handle('es6', ...)` in - // `electron-app/main.js` that resolves `es6://foo` to - // `/app/foo` on disk. This matches the craco-era - // `webpackConfig.output.publicPath = 'es6://'` override in - // `react/craco.config.cjs`. - // - // We cannot set `base: 'es6://'` directly: Vite's external-URL regex is - // `/^([a-z]+:)?\/\//`, and the `6` in `es6` breaks the `[a-z]+` group, - // so Vite treats `es6://` as a malformed absolute path and strips the - // scheme. The official escape hatch is `experimental.renderBuiltUrl`, - // which is called per built asset and whose return value replaces the - // default `base + filename` concatenation — no scheme validation. - const isElectronBuild = - command === 'build' && process.env.BUILD_TARGET === 'electron'; - + // The Electron target's `es6://` publicPath is applied by + // `scripts/patch-electron-publicpath.js` after the single web build + // (per FR-2612 policy: one build, post-patch — never a second `vite build`). return { base: '/', - experimental: isElectronBuild - ? { - renderBuiltUrl(filename) { - return `es6://${filename}`; - }, - } - : undefined, // Keep root at `react/` so pnpm's react/react-dom installed in // react/node_modules resolve correctly. Static assets from projectRoot // are handled by projectRootStaticPlugin above. diff --git a/scripts/patch-electron-publicpath.js b/scripts/patch-electron-publicpath.js index 4eff942a99..8a284a98e1 100755 --- a/scripts/patch-electron-publicpath.js +++ b/scripts/patch-electron-publicpath.js @@ -1,21 +1,26 @@ #!/usr/bin/env node /** - * Patch the web build output to use Electron's 'es6://' publicPath. + * Patch the Vite web build output to use Electron's 'es6://' publicPath. * - * When building for Electron, webpack's output.publicPath must be 'es6://' - * instead of the default '/'. Previously this required a full second React - * build (~4-8 min). This script achieves the same result by patching the - * already-built files, saving significant CI time. + * When building for Electron, asset URLs must use the custom 'es6://' scheme + * (handled by electron-app/main.js) instead of the default '/'. Doing this + * with a second `vite build` (BUILD_TARGET=electron + experimental.renderBuiltUrl) + * doubles release CI time, which FR-2612 explicitly eliminated. This script + * keeps the single-build model by patching the already-built files. * * Usage: node scripts/patch-electron-publicpath.js * - * The script patches: - * 1. index.html — static asset references (/static/... → es6://static/...) - * 2. asset-manifest.json — all asset paths - * 3. JS bundles — webpack runtime's publicPath assignment (e.g. n.p="/") - * 4. CSS files — url() references to /static/ assets - * 5. Service worker (sw.js) — precache manifest URLs + * Vite's output layout (post-FR-2606 migration): + * - index.html with `` and `