fix(FR-2606): restore Monaco self-hosting in Vite dev server#7104
Merged
graphite-app[bot] merged 1 commit intomainfrom Apr 30, 2026
Merged
Conversation
This was referenced Apr 27, 2026
Merged
Contributor
Author
This was referenced Apr 27, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Restores Monaco self-hosting in the Vite dev server so /resources/monaco/vs/* resolves again and Monaco-mounted pages don’t fail at runtime after the Craco→Vite cutover.
Changes:
- Added a Vite dev-only middleware plugin to serve
react/node_modules/monaco-editor/min/vs/*at/resources/monaco/vs/*. - Ensured the Monaco middleware runs before the more general project-root static middleware.
0ef6b62 to
8981c28
Compare
245b162 to
fa43a8c
Compare
8981c28 to
a55f50b
Compare
fa43a8c to
9ab3c7b
Compare
1acb275 to
7437b6e
Compare
9ab3c7b to
5dd3d34
Compare
5dd3d34 to
c55de1c
Compare
0353467 to
5f30412
Compare
c55de1c to
026732d
Compare
This was referenced Apr 30, 2026
Merge activity
|
Resolves #6809(FR-2606) ## Summary Dev-server regression noticed after the Vite cutover: pages that mount a Monaco editor break at mount time because the `/resources/monaco/vs/*` URL prefix no longer resolves on the dev server. `@monaco-editor/react` loads the Monaco AMD runtime at runtime via: ```ts loader.config({ paths: { vs: '/resources/monaco/vs' } }); ``` (see `react/src/helper/monacoEditor.ts`). The self-hosted prefix exists so the editor works in offline / air-gapped deployments where jsDelivr is unreachable. Pre-Vite, the dev-server side of this contract was the `static` directory list in `react/craco.config.cjs` (lines 44–60 of the now-deleted file): it served `react/node_modules/monaco-editor/min/vs/*` at the `/resources/monaco/vs` URL prefix. Production builds copy the same tree to `build/web/resources/monaco/vs/` via the root `copymonaco` script (`package.json:32`). After #6876 (FR-2611) dropped `craco.config.cjs`, the production `copymonaco` step was preserved but the dev-server-side mapping was not ported to `vite.config.ts`. As a result, in `pnpm run dev`, requests to `/resources/monaco/vs/loader.js` 404 and any page that mounts a Monaco editor breaks. **Fix**: add `monacoStaticPlugin()` to `react/vite.config.ts` mirroring the deleted craco `static` entry. - Serves `/resources/monaco/vs/*` from `react/node_modules/monaco-editor/min/vs/*`. - `apply: 'serve'` — dev-only; production is unchanged because `copymonaco` already populates `build/web/resources/monaco/vs/`. - Path-traversal guard via `filePath.startsWith(monacoRoot)` after `join` normalization. - Registered in the `plugins` array before `projectRootStaticPlugin()` so the narrower Monaco prefix is matched first. ## Verification - [x] `bash scripts/verify.sh` — Relay / Lint / Format / TypeScript all PASS - [ ] `pnpm run dev`, navigate to a Monaco-mounting page (manifest editor on Environments page) — editor renders without console errors, no `cdn.jsdelivr.net` fetches - [ ] DevTools → Network: `/resources/monaco/vs/loader.js`, `/resources/monaco/vs/editor/editor.main.js` return 200 from the dev server ## Stack Top of the Vite migration follow-up stack. Sits on top of #7083 (FR-2748).
5f30412 to
9fa887b
Compare
026732d to
be64c51
Compare
graphite-app Bot
pushed a commit
that referenced
this pull request
Apr 30, 2026
…rective) (#7113) Resolves #6809(FR-2606) ## Summary Cleans up residual `pnpm run build` warnings introduced or surfaced by the Vite migration (FR-2611). All non-fatal in the original log (build was already exiting 0); cleared here as a follow-up to the FR-2606 series. Three classes of warnings are addressed: 1. **BUI dts emit type errors** (TS2742 + TS2591 + a follow-on TS2339) 2. **Module-level `'use memo'` directive** ignored by Rollup 3. **Components ↔ hooks circular dependency** in BUI, surfaced via `ResourceTypeIcon` re-export through the components barrel ## 1. BUI dts emit (`vite-plugin-dts`) — three TS diagnostics ### TS2742 — `i18n` inferred type (`packages/backend.ai-ui/src/locale/index.ts:92`) > The inferred type of 'i18n' cannot be named without a reference to '../../node_modules/i18next'. `createInstance(...)`'s inferred return type referenced `i18next` internal types, breaking portable `.d.ts` emit. Added explicit annotation: ```ts import { createInstance, type i18n as I18nInstance } from 'i18next'; export const i18n: I18nInstance = createInstance({ ... }); ``` ### TS2591 — `process` not defined (`packages/backend.ai-ui/src/hooks/useBAILogger.tsx:47`) BUI's `tsconfig.types` is intentionally `["vite-plugin-svgr/client"]` (no `node` types) because BUI is a browser-only library. The single `process.env.NODE_ENV` read violated that policy. Switched to Vite's first-class env API: ```ts private enabled: boolean = !import.meta.env.PROD; ``` ### TS2339 — `import.meta.env` not typed (follow-up to TS2591 fix) For `import.meta.env.PROD` to be typed in BUI's dts emit, `vite/client` ambient types had to be wired in. Three coordinated changes: - `packages/backend.ai-ui/vite-env.d.ts` — added `/// <reference types="vite/client" />`. The file already existed at the package root but was orphaned; included it so it actually gets picked up. - `packages/backend.ai-ui/tsconfig.json` — added `vite-env.d.ts` to `include`. - `packages/backend.ai-ui/vite.config.ts` — added `vite-env.d.ts` to the `dts` plugin's own `include` array (separate from `tsconfig.include`; this was the missing piece that made `import.meta.env.PROD` typed in dts emit context). - `react/src/ambient.d.ts` — added the same reference for the `react/` tsc check (verify.sh) which compiles BUI source through the path alias. ## 2. Module-level `'use memo'` (`react/src/components/SwitchToProjectButton.tsx:1`) > Module level directives cause errors when bundled, "use memo" in "..." was ignored. Moved the directive from module level to the inner function body (`SwitchToProjectButtonContent`), matching `.claude/rules/react-compiler-memoization.md` convention. The wrapper component (`SwitchToProjectButton`) renders only Suspense + child and does not need its own memo directive. ## 3. BUI components ↔ hooks circular dependency Rollup chunk-graph warning: > Export "ResourceTypeIcon" of module ".../BAIResourceNumberWithIcon.tsx" was reexported through module ".../components/index.ts" while both modules are dependencies of each other... The actual cycle traced: ``` components/index.ts (barrel) ↓ re-exports BAIResourceNumberWithIcon BAIResourceNumberWithIcon.tsx ↓ imports './provider' (provider barrel) provider barrel ↓ exports BAIMetaDataProvider, BAIClientProvider hooks BAIMetaDataProvider/hooks/useBAIDeviceMetaData.ts:1 BAIClientProvider/hooks/useAnonymousBAIClient.ts:1 BAIMetaDataProvider/types.ts:1 ↓ each imports from '../../../[..]/hooks' (hooks barrel) hooks/index.ts:1-5 ↓ imports value names from '../components' 🔴 cycle closes ``` The cycle was reachable through three back-edges from the `components/provider/...` subtree into the hooks barrel, plus the hooks barrel's own value imports back into the components barrel. Six coordinated edits broke it: - `BUI/src/hooks/index.ts:1-5` — barrel-to-barrel import replaced with three direct module imports + one `import type` (for the type-only `ResourceSlotName`). - `BUI/src/hooks/useBAISignedRequestWithPromise.ts:1` — same pattern; barrel → direct module path. - `BUI/src/components/provider/BAIMetaDataProvider/hooks/useBAIDeviceMetaData.ts:1` — barrel → direct module path on the hooks side. - `BUI/src/components/provider/BAIClientProvider/hooks/useAnonymousBAIClient.ts:1` — same pattern. - `BUI/src/components/provider/BAIMetaDataProvider/types.ts:1` — value-style import of a type promoted to `import type`. Net structural change: the BUI hooks barrel no longer imports anything from the components barrel, and the surviving `provider/* → hooks` edges all go through direct module paths whose target files have no further cycle exposure. Components-subtree files are still free to use the hooks barrel; the dependency arrow is now one-way only. ## Locale Prettier config — fixed parent override (in earlier amend) `packages/backend.ai-ui/src/locale/.prettierrc` was a per-directory override containing only the JSON-sort plugin, with no other options set. Prettier's config resolution picks the nearest config file and does NOT cascade from parents, so `singleQuote` defaulted to `false` for files in `src/locale/` — including `index.ts`, which kept getting double-quoted whenever lint-staged ran. Fix: deleted `src/locale/.prettierrc` and moved the JSON-sort options into the parent BUI `.prettierrc.json` as an `overrides` entry scoped to `src/locale/*.json`. The directory now inherits the rest of the BUI Prettier config (including `singleQuote: true`) while retaining the JSON-only sort behavior. ## Verification - [x] `bash scripts/verify.sh` — Relay / Lint / Format / TypeScript all PASS - [x] `pnpm run build` — exit 0; the following diagnostics are no longer present in the log: - TS2742 (`i18n` portable) - TS2591 (`process` not defined) - TS2339 (`import.meta.env.PROD` not typed) - "Module level directives cause errors" (`'use memo'`) - "reexported through ... while both modules are dependencies of each other" (`ResourceTypeIcon` cycle) Remaining build warnings (5 mixed dynamic+static imports, 2 chunks > 2 MB, several runtime-resolved CSS/manifest assets) are out of scope and tracked separately. ## Stack Sits on top of #7104 (FR-2606 Monaco self-hosting). Top of the Vite migration follow-up stack.
Base automatically changed from
04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals
to
main
April 30, 2026 12:37
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Resolves #6809(FR-2606)
Summary
Dev-server regression noticed after the Vite cutover: pages that mount a Monaco editor break at mount time because the
/resources/monaco/vs/*URL prefix no longer resolves on the dev server.@monaco-editor/reactloads the Monaco AMD runtime at runtime via:(see
react/src/helper/monacoEditor.ts). The self-hosted prefix exists so the editor works in offline / air-gapped deployments where jsDelivr is unreachable.Pre-Vite, the dev-server side of this contract was the
staticdirectory list inreact/craco.config.cjs(lines 44–60 of the now-deleted file): it servedreact/node_modules/monaco-editor/min/vs/*at the/resources/monaco/vsURL prefix. Production builds copy the same tree tobuild/web/resources/monaco/vs/via the rootcopymonacoscript (package.json:32).After #6876 (FR-2611) dropped
craco.config.cjs, the productioncopymonacostep was preserved but the dev-server-side mapping was not ported tovite.config.ts. As a result, inpnpm run dev, requests to/resources/monaco/vs/loader.js404 and any page that mounts a Monaco editor breaks.Fix: add
monacoStaticPlugin()toreact/vite.config.tsmirroring the deleted cracostaticentry./resources/monaco/vs/*fromreact/node_modules/monaco-editor/min/vs/*.apply: 'serve'— dev-only; production is unchanged becausecopymonacoalready populatesbuild/web/resources/monaco/vs/.filePath.startsWith(monacoRoot)afterjoinnormalization.pluginsarray beforeprojectRootStaticPlugin()so the narrower Monaco prefix is matched first.Verification
bash scripts/verify.sh— Relay / Lint / Format / TypeScript all PASSpnpm run dev, navigate to a Monaco-mounting page (manifest editor on Environments page) — editor renders without console errors, nocdn.jsdelivr.netfetches/resources/monaco/vs/loader.js,/resources/monaco/vs/editor/editor.main.jsreturn 200 from the dev serverStack
Top of the Vite migration follow-up stack. Sits on top of #7083 (FR-2748).