Skip to content

fix(FR-2606): restore Monaco self-hosting in Vite dev server#7104

Merged
graphite-app[bot] merged 1 commit intomainfrom
04-27-fix_fr-2606_restore_monaco_self-hosting_in_vite_dev_server
Apr 30, 2026
Merged

fix(FR-2606): restore Monaco self-hosting in Vite dev server#7104
graphite-app[bot] merged 1 commit intomainfrom
04-27-fix_fr-2606_restore_monaco_self-hosting_in_vite_dev_server

Conversation

@nowgnuesLee
Copy link
Copy Markdown
Contributor

@nowgnuesLee nowgnuesLee commented Apr 27, 2026

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:

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

  • 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).

Copy link
Copy Markdown
Contributor Author

nowgnuesLee commented Apr 27, 2026


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • flow:merge-queue - adds this PR to the back of the merge queue
  • flow:hotfix - for urgent changes, fast-track this PR to the front of the merge queue

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has required the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread react/vite.config.ts
Comment thread react/vite.config.ts
@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch from 0ef6b62 to 8981c28 Compare April 28, 2026 05:02
@nowgnuesLee nowgnuesLee force-pushed the 04-27-fix_fr-2606_restore_monaco_self-hosting_in_vite_dev_server branch 2 times, most recently from 245b162 to fa43a8c Compare April 28, 2026 05:15
@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch from 8981c28 to a55f50b Compare April 28, 2026 05:15
@nowgnuesLee nowgnuesLee force-pushed the 04-27-fix_fr-2606_restore_monaco_self-hosting_in_vite_dev_server branch from fa43a8c to 9ab3c7b Compare April 28, 2026 05:19
@nowgnuesLee nowgnuesLee force-pushed the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch 2 times, most recently from 1acb275 to 7437b6e Compare April 28, 2026 05:25
@nowgnuesLee nowgnuesLee force-pushed the 04-27-fix_fr-2606_restore_monaco_self-hosting_in_vite_dev_server branch from 9ab3c7b to 5dd3d34 Compare April 28, 2026 05:25
@nowgnuesLee nowgnuesLee force-pushed the 04-27-fix_fr-2606_restore_monaco_self-hosting_in_vite_dev_server branch from 5dd3d34 to c55de1c Compare April 28, 2026 05:28
@yomybaby yomybaby force-pushed the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch from 0353467 to 5f30412 Compare April 30, 2026 12:08
@yomybaby yomybaby force-pushed the 04-27-fix_fr-2606_restore_monaco_self-hosting_in_vite_dev_server branch from c55de1c to 026732d Compare April 30, 2026 12:08
@graphite-app
Copy link
Copy Markdown

graphite-app Bot commented 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).
@graphite-app graphite-app Bot force-pushed the 04-27-feat_fr-2748_fully_migrate_test_files_from_jest._to_vi._and_align_ts_globals branch from 5f30412 to 9fa887b Compare April 30, 2026 12:20
@graphite-app graphite-app Bot force-pushed the 04-27-fix_fr-2606_restore_monaco_self-hosting_in_vite_dev_server branch from 026732d to be64c51 Compare April 30, 2026 12:20
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
@graphite-app graphite-app Bot merged commit be64c51 into main Apr 30, 2026
4 checks passed
@graphite-app graphite-app Bot deleted the 04-27-fix_fr-2606_restore_monaco_self-hosting_in_vite_dev_server branch April 30, 2026 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30~100 LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Vite PoC Phase 1: dev server + HMR parity for react/ and backend.ai-ui

2 participants