Files
volar-docs/docs/monaco-playground.md
2025-11-09 22:22:52 -06:00

95 lines
2.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Building a Volar-Powered Monaco Playground
> [Docs Index](README.md) • [Repo README](../README.md) • [Volar Kit & Editor](volar-kit-and-editor.md) • [Live Examples](live-examples.md)
This guide walks through wiring Volars language service into a browser-based playground (Vue SFC REPL, documentation site, or sandbox) using `@volar/monaco`.
## Architecture
```
Monaco Editor (main thread)
├─ Worker (language service)
│ ├─ TypeScript runtime
│ ├─ Volar language service
│ └─ Virtual file system (in-memory / IndexedDB)
└─ UI (tabs, preview)
```
## Step 1: Install Dependencies
```bash
npm install monaco-editor @volar/monaco typescript
```
## Step 2: Worker Setup
```ts
// volar.worker.ts
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import { setupLanguageServiceForMonaco } from '@volar/monaco';
setupLanguageServiceForMonaco(monaco, {
loadTypescript: () => import('typescript/lib/typescript.js'),
loadLanguageService: () => import('./volar-service-entry'),
});
```
`volar-service-entry` exports `createLanguageService(env)` that mirrors your servers factory.
## Step 3: Main Thread Wiring
```ts
import * as monaco from 'monaco-editor';
monaco.languages.register({ id: 'vue' });
monaco.languages.onLanguage('vue', () => {
new Worker(new URL('./volar.worker.ts', import.meta.url), { type: 'module' });
});
const model = monaco.editor.createModel('<template>hi</template>', 'vue', monaco.Uri.parse('file:///App.vue'));
monaco.editor.create(document.getElementById('editor')!, { model });
```
## Step 4: Virtual File System
Track files and sync them with the language service host:
```ts
const files = new Map<string, string>();
function syncModel(model: monaco.editor.ITextModel) {
const uri = model.uri.toString();
files.set(uri, model.getValue());
languageServiceHost.writeFile(uri, model.getValue());
}
monaco.editor.onDidCreateModel((model) => {
syncModel(model);
model.onDidChangeContent(() => syncModel(model));
});
```
Persist files using `localStorage`, IndexedDB, or encoded URLs so sessions can be shared.
## Step 5: Preview / Output Integration
- Render an iframe or use the Vue runtime to preview components.
- Listen for diagnostics via Monaco markers and show a summary list.
- Capture console output from the preview iframe for debugging.
## Performance Tips
1. Lazy-load worker bundle when a Vue file is opened.
2. Debounce file sync to avoid flooding the worker.
3. Reuse the same TypeScript module across workers (via CDN) to reduce bundle size.
4. For large projects, load files on demand instead of preloading entire repos.
## Example Projects
- [Vue SFC Playground](https://github.com/vuejs/repl)
- [StackBlitz Vue starter](https://stackblitz.com/edit/vue)
- [CodeSandbox Projects](https://codesandbox.io/p/dashboard)
By reusing your existing Volar language-service factory in the browser, you guarantee parity between editor IntelliSense and playground experiences.