Getting Started with Monaco
Prerequisites
Before continuing, make sure you're familiar with: SignalX Core basics, Components
@sigx/monaco-editor is a pluggable wrapper around the Monaco editor (the engine behind VS Code) built for SignalX apps. It gives you:
- A reactive
<MonacoEditor />SignalX component plus a low-level imperativecreateEditor()API. - A loader that lazy-loads Monaco on demand using one of two strategies —
prebundled(assets committed to the package) orcdn. - Composable language packs for TypeScript/JSX, HTML, CSS, and JSON, each wiring the correct Monaco worker and IntelliSense.
- Optional Shiki highlighting via a dedicated subpath.
- A Vite plugin that keeps Monaco out of your application bundle and serves the prebundled assets.
Install
pnpm add @sigx/monaco-editor monaco-editor
monaco-editor is a peer dependency. See Installation for peer deps, Vite wiring, and the required configuration.
Minimal example
Wiring up Monaco is three steps: add the Vite plugin, register the language packs you need once at module load, then render the component.
// vite.config.ts
import { defineConfig } from 'vite';
import { sigxPlugin } from '@sigx/vite';
import { monacoPrebundledPlugin } from '@sigx/monaco-editor/vite';
export default defineConfig({
plugins: [
sigxPlugin(),
monacoPrebundledPlugin({ strategy: 'prebundled', publicPath: '/monaco-bundle' }),
],
oxc: { jsx: { runtime: 'automatic', importSource: 'sigx' } },
});
// App.tsx
import { component, render } from 'sigx';
import {
MonacoEditor,
configureMonaco,
typescriptLanguagePack,
cssLanguagePack,
jsonLanguagePack,
htmlLanguagePack,
} from '@sigx/monaco-editor';
// Register language packs once, before the editor first mounts.
configureMonaco({
languages: [
typescriptLanguagePack({ jsxImportSource: 'sigx' }),
cssLanguagePack(),
jsonLanguagePack(),
htmlLanguagePack(),
],
});
const App = component(({ signal }) => {
const state = signal({
language: 'typescript',
theme: 'vs-dark',
code: 'const greeting: string = "Hello, Monaco";\n',
});
return () => (
<MonacoEditor
value={state.code}
language={state.language}
theme={state.theme}
onChange={(v) => (state.code = v)}
/>
);
});
render(<App />, document.getElementById('app')!);
The component lazy-loads Monaco on mount, applies the registered language packs, and disposes the editor automatically on unmount. The container fills its parent by default (width: 100%; height: 100%;), so give it a sized parent element.
How loading works
You never import monaco-editor directly in client code. The Vite plugin replaces every monaco-editor import with a throwing stub and keeps it out of optimizeDeps. Instead, Monaco is fetched at runtime by loadMonaco() — which the <MonacoEditor /> component and createEditor() call for you. The plugin and the runtime loader agree on a strategy through a window.__MONACO_LOADER_CONFIG__ snippet the plugin injects into your HTML.
Next steps
- Installation — peer deps, Vite wiring, and the prebundled vs CDN asset strategies.
- Language packs and IntelliSense — registering TS/JSX, HTML, CSS, and JSON, plus themes and extra type definitions.
- Imperative editors and Shiki highlighting —
createEditor()and the optional Shiki integration. - API Reference — every export with signatures.
