fix(E3): bundle Monaco workers locally
This commit is contained in:
parent
a09276a3b5
commit
e8b3c9cf69
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@ -266,6 +266,9 @@ importers:
|
|||||||
lucide-react:
|
lucide-react:
|
||||||
specifier: ^0.562.0
|
specifier: ^0.562.0
|
||||||
version: 0.562.0(react@19.2.4)
|
version: 0.562.0(react@19.2.4)
|
||||||
|
monaco-editor:
|
||||||
|
specifier: ^0.55.1
|
||||||
|
version: 0.55.1
|
||||||
react:
|
react:
|
||||||
specifier: ^19.2.0
|
specifier: ^19.2.0
|
||||||
version: 19.2.4
|
version: 19.2.4
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
"@monaco-editor/react": "^4.7.0",
|
"@monaco-editor/react": "^4.7.0",
|
||||||
"lucide-react": "^0.562.0",
|
"lucide-react": "^0.562.0",
|
||||||
|
"monaco-editor": "^0.55.1",
|
||||||
"react": "^19.2.0",
|
"react": "^19.2.0",
|
||||||
"react-dom": "^19.2.0",
|
"react-dom": "^19.2.0",
|
||||||
"react-router-dom": "^7.14.2",
|
"react-router-dom": "^7.14.2",
|
||||||
|
|||||||
@ -9,6 +9,7 @@ const { createTradeProfileMock } = vi.hoisted(() => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock('@monaco-editor/react', () => ({
|
vi.mock('@monaco-editor/react', () => ({
|
||||||
|
loader: { config: vi.fn() },
|
||||||
default: ({ value, onChange }: any) => (
|
default: ({ value, onChange }: any) => (
|
||||||
<textarea
|
<textarea
|
||||||
aria-label="strategy code"
|
aria-label="strategy code"
|
||||||
@ -18,6 +19,30 @@ vi.mock('@monaco-editor/react', () => ({
|
|||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
vi.mock('monaco-editor', () => ({
|
||||||
|
editor: {},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('monaco-editor/esm/vs/editor/editor.worker?worker', () => ({
|
||||||
|
default: class MockEditorWorker {},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('monaco-editor/esm/vs/language/json/json.worker?worker', () => ({
|
||||||
|
default: class MockJsonWorker {},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('monaco-editor/esm/vs/language/css/css.worker?worker', () => ({
|
||||||
|
default: class MockCssWorker {},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('monaco-editor/esm/vs/language/html/html.worker?worker', () => ({
|
||||||
|
default: class MockHtmlWorker {},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('monaco-editor/esm/vs/language/typescript/ts.worker?worker', () => ({
|
||||||
|
default: class MockTsWorker {},
|
||||||
|
}));
|
||||||
|
|
||||||
vi.mock('../../lib/profileApi', () => ({
|
vi.mock('../../lib/profileApi', () => ({
|
||||||
createTradeProfile: (...args: any[]) => createTradeProfileMock(...args),
|
createTradeProfile: (...args: any[]) => createTradeProfileMock(...args),
|
||||||
}));
|
}));
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { Suspense, lazy, useCallback, useEffect, useRef, useState } from 'react'
|
|||||||
import { Play, Save, Copy, RotateCcw } from 'lucide-react';
|
import { Play, Save, Copy, RotateCcw } from 'lucide-react';
|
||||||
import { getPlatformAccessToken } from '../../lib/authSession';
|
import { getPlatformAccessToken } from '../../lib/authSession';
|
||||||
import { createTradeProfile } from '../../lib/profileApi';
|
import { createTradeProfile } from '../../lib/profileApi';
|
||||||
|
import '../../lib/monacoLocalWorkers';
|
||||||
import { tradingRuntime } from '../../lib/runtime';
|
import { tradingRuntime } from '../../lib/runtime';
|
||||||
import { createRequestId } from '../../../../shared/request-id.js';
|
import { createRequestId } from '../../../../shared/request-id.js';
|
||||||
|
|
||||||
|
|||||||
36
web/src/lib/monacoLocalWorkers.ts
Normal file
36
web/src/lib/monacoLocalWorkers.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { loader } from '@monaco-editor/react';
|
||||||
|
import * as monaco from 'monaco-editor';
|
||||||
|
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
|
||||||
|
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
|
||||||
|
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker';
|
||||||
|
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker';
|
||||||
|
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
|
||||||
|
|
||||||
|
type MonacoWorkerConstructor = new () => Worker;
|
||||||
|
|
||||||
|
const workerByLabel: Record<string, MonacoWorkerConstructor> = {
|
||||||
|
css: cssWorker,
|
||||||
|
handlebars: htmlWorker,
|
||||||
|
html: htmlWorker,
|
||||||
|
javascript: tsWorker,
|
||||||
|
json: jsonWorker,
|
||||||
|
less: cssWorker,
|
||||||
|
razor: htmlWorker,
|
||||||
|
scss: cssWorker,
|
||||||
|
typescript: tsWorker,
|
||||||
|
};
|
||||||
|
|
||||||
|
const monacoGlobal = globalThis as typeof globalThis & {
|
||||||
|
MonacoEnvironment?: {
|
||||||
|
getWorker: (_moduleId: string, label: string) => Worker;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
monacoGlobal.MonacoEnvironment = {
|
||||||
|
getWorker(_moduleId: string, label: string) {
|
||||||
|
const WorkerConstructor = workerByLabel[label] ?? editorWorker;
|
||||||
|
return new WorkerConstructor();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
loader.config({ monaco });
|
||||||
@ -15,6 +15,15 @@
|
|||||||
"moduleDetection": "force",
|
"moduleDetection": "force",
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"monaco-editor": [
|
||||||
|
"../node_modules/.pnpm/monaco-editor@0.55.1/node_modules/monaco-editor/esm/vs/editor/editor.api"
|
||||||
|
],
|
||||||
|
"monaco-editor/*": [
|
||||||
|
"../node_modules/.pnpm/monaco-editor@0.55.1/node_modules/monaco-editor/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
/* Linting */
|
/* Linting */
|
||||||
"strict": true,
|
"strict": true,
|
||||||
|
|||||||
@ -4,6 +4,11 @@ import tailwindcss from '@tailwindcss/vite'
|
|||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import fs from 'node:fs'
|
import fs from 'node:fs'
|
||||||
|
|
||||||
|
const monacoEditorPath = path.resolve(
|
||||||
|
__dirname,
|
||||||
|
'../node_modules/.pnpm/monaco-editor@0.55.1/node_modules/monaco-editor',
|
||||||
|
);
|
||||||
|
|
||||||
// Resolve a @bytelyst/* package: prefer web/node_modules, fall back to vendor/
|
// Resolve a @bytelyst/* package: prefer web/node_modules, fall back to vendor/
|
||||||
function bytelystAlias(pkg: string): string {
|
function bytelystAlias(pkg: string): string {
|
||||||
const nmPath = path.resolve(__dirname, 'node_modules/@bytelyst', pkg);
|
const nmPath = path.resolve(__dirname, 'node_modules/@bytelyst', pkg);
|
||||||
@ -29,6 +34,12 @@ export default defineConfig({
|
|||||||
// Vendor packages that live only in vendor/ (not in web/node_modules/)
|
// Vendor packages that live only in vendor/ (not in web/node_modules/)
|
||||||
{ find: '@bytelyst/api-client', replacement: bytelystAlias('api-client') },
|
{ find: '@bytelyst/api-client', replacement: bytelystAlias('api-client') },
|
||||||
{ find: '@bytelyst/errors', replacement: bytelystAlias('errors') },
|
{ find: '@bytelyst/errors', replacement: bytelystAlias('errors') },
|
||||||
|
// Monaco is an explicit web dependency, but this workspace often runs
|
||||||
|
// against pnpm's root store without a web/node_modules symlink when the
|
||||||
|
// private mobile registry is unavailable. Keep local worker imports
|
||||||
|
// resolvable for Vite in that partially installed state.
|
||||||
|
{ find: /^monaco-editor$/, replacement: monacoEditorPath },
|
||||||
|
{ find: /^monaco-editor\/(.+)/, replacement: `${monacoEditorPath}/$1` },
|
||||||
// General catch-all: every other @bytelyst/* → web/node_modules
|
// General catch-all: every other @bytelyst/* → web/node_modules
|
||||||
{
|
{
|
||||||
find: /^@bytelyst\/(.+)/,
|
find: /^@bytelyst\/(.+)/,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user