11 KiB
VolarJS Getting Started
Docs Index • Repo README • Plugin Authoring • Source Map & Code Gen • Configuration & Projects
VolarJS is the reference implementation of Vue Language Server tooling. Its packages are intentionally small so you can wire only what you need—whether that is a full LSP server, a web-based editor integration, or a bespoke CLI that runs Vue-aware transforms. This guide explains the moving pieces, how they relate, and the quickest path to seeing language features light up.
Mental Model
Vue source files ──▶ @volar/language-core ──▶ @volar/language-service plugins ──▶ Host adapters (LSP, VS Code, Monaco, custom)
- File understanding happens in
@volar/language-core. It parses Vue SFCs, tracks virtual files, and creates source maps between template/script/style sections. - Language features live in
@volar/language-service(hover, completion, diagnostics, etc.) and are provided by plugins. Vue’s default feature set is one plugin; you can add more. - Adapters such as
@volar/language-serveror@volar/monacoconnect the language service to an IDE, editor, or any host that speaks a protocol.
Package Overview
Core Building Blocks
| Package | What it does | When to depend on it |
|---|---|---|
@volar/source-map |
Bidirectional source-map abstraction used everywhere Volar needs to point back into the user’s Vue/TS files. Supports stacked maps (template <-> TS <-> emitted JS). | Useful whenever you create custom virtual files or remap diagnostics. |
@volar/code-gen |
Utility for generating virtual TypeScript text plus accompanying source maps in lockstep. The Vue plugin uses it to describe script/template output. | Authoring custom language-core plugins or transforms. |
@volar/language-core |
Creates the document graph, manages embedded files, and wires source-map + code-gen so features understand Vue SFC structure. |
Always required; everything else builds on the core. |
@volar/typescript |
Wraps the TS compiler API, exposing helpers to build/refresh programs, track script snapshots, and share language service hosts. | Needed whenever you want TS-powered diagnostics or IntelliSense (nearly all workflows). |
Service Layer
| Package | What it does | When to depend on it |
|---|---|---|
@volar/language-service |
Orchestrates feature plugins (hover, completion, code actions, etc.) and exposes the API a host will call. | Required for any integration responding to language requests. |
@volar/vue-language-core |
Vue-specific implementation of language-core plugins (parses .vue blocks, tracks template regions, emits TS code). |
Needed if you want first-party Vue behavior without reinventing parsing. |
@volar/vue-language-service |
Bundled set of language-service plugins delivering Vue-aware completions, diagnostics, refactors, formatting, etc. | Drop-in when you just need the standard Vue feature set. |
@volar/vue-typescript |
Provides a TypeScript plugin so TS itself understands .vue files (Take Over Mode, vue-tsc). |
Required if you let TypeScript drive the project graph or run vue-tsc. |
volar-service-* plugins |
Feature add-ons (Prettier formatting, CSS frameworks, component libraries). Each exposes hooks for both core and language-service layers. | Opt-in when the default Vue plugin is not enough. |
Common volar-service-* Add-ons
| Plugin | Capability | Notes |
|---|---|---|
volar-service-prettier |
Formatting for templates + scripts via Prettier. | Configure formatter options via initializationOptions.plugins.prettier. |
volar-service-css |
CSS/SCSS completions, diagnostics, folding. | Injects style virtual documents; customizable with css.languages. |
volar-service-html |
HTML attribute hints, tag completions for template sections. | Useful for custom component libs that mirror HTML behavior. |
volar-service-typescript-twoslash-queries |
Inline // ^? query evaluation for debugging type state. |
Great for docs/playground experiences. |
volar-service-emmet |
Emmet abbreviations inside Vue templates. | Enable selectively per workspace to avoid conflicts. |
All services share the same LanguageServicePlugin interface, so you can inspect these packages as reference implementations when building your own feature modules.
Adapter / Host Packages
| Package | What it does | When to depend on it |
|---|---|---|
@volar/language-server |
Wraps the language service with an LSP transport (3.17), file watching, and JSON-RPC plumbing. | Editors that speak LSP (VS Code, Neovim, Sublime LSP, etc.). |
@volar/kit |
Convenience bootstrapper for CLIs and custom hosts; bundles configs, file watching, and plugin wiring helpers. | Rapidly wiring a bespoke integration or experimentation harness. |
@volar/editor |
Provides thin abstractions around text documents, connections, and workspace edits so non-LSP hosts can embed Volar with less boilerplate. | Custom IDEs or web editors that do not rely on Monaco. |
@volar/monaco |
Binds the language service to Monaco Editor APIs (workers, markers, completion providers). | Browser-based playgrounds, docs sandboxes, or VS Code Web-style apps. |
Tip: “VolarJS” refers to the overall toolkit. Individual packages keep the
@volar/scope, core/service helpers focus on composition, and feature plugins often start withvolar-service-.
Installation Cheatsheet
npm install --save-dev @volar/language-core @volar/language-service @volar/typescript
Add the adapter you need:
- LSP host:
npm install --save-dev @volar/language-server - Web editor:
npm install --save @volar/monaco - Extra features:
npm install --save-dev volar-service-<name>
Bootstrapping the Core + Service
// tooling/createVolarService.ts
import { createLanguageCore } from '@volar/language-core';
import { createLanguageService } from '@volar/language-service';
import { createTypeScriptProject } from '@volar/typescript';
import vuePlugin from '@volar/vue-language-service'; // ships inside the main repo
export function createVolarService(tsconfigPath: string) {
const tsProject = createTypeScriptProject(tsconfigPath);
const core = createLanguageCore({
plugins: [vuePlugin.tsPlugin],
ts: tsProject.typescript,
getScriptContent: tsProject.host.readFile,
});
return createLanguageService(core, {
plugins: [vuePlugin.languageService],
});
}
- Core setup wires TypeScript and Vue-specific transforms.
- Language service registers plugins. Each plugin may expose both a TypeScript layer (virtual files) and an LSP layer (features).
- Under the hood, the Vue plugin relies on
@volar/code-gen+@volar/source-mapto keep every generated byte mapped back to the user’s SFC so diagnostics and quick fixes land in the right spot.
Common Integration Paths
1. Shipping an LSP Server (VS Code, Neovim, Sublime)
- Install
@volar/language-server. - Create an
entry.tsthat callscreateLanguageServer(or use@volar/kit’s CLI helpers) and forwards stdio (or node IPC) to the editor. - Provide configuration hooks so users can adjust
tsconfig, Take Over Mode, and plugin toggles.
import { startLanguageServer } from '@volar/language-server/node';
import { createVolarService } from './tooling/createVolarService';
startLanguageServer(async (params) => ({
languageService: createVolarService(params.initializationOptions.tsconfig),
}));
2. Embedding in a Browser Playground (Monaco)
- Install
@volar/monaco. - Register workers and configure virtual file resolution (fetch files over HTTP, from memory, etc.).
- Attach the Volar language service to Monaco’s
languages.registerAPI. - For fully custom editors, use
@volar/editorto avoid wiring the text-buffer plumbing from scratch.
3. Running Volar Inside a CLI
- Build the service as shown earlier (or bootstrap via
@volar/kitwhich wires file watching + reloads). - Call methods like
doValidation,findReferences, orformaton demand. - Perfect for codemods, lint rules, or CI checks that require Vue awareness without firing up an editor.
How the Pieces Fit
@volar/language-coreowns document truth (what files exist, how they map).@volar/code-genand@volar/source-mapmake sure generated TS/JS stays tied to the user’s original locations.@volar/typescriptkeeps Volar in sync with TS’s program graph.@volar/language-serviceexposes capabilities and loads plugins.- Vue-specific packages (
@volar/vue-language-core,@volar/vue-language-service,@volar/vue-typescript) ship the batteries-included feature set. - Adapter packages (LSP, Monaco, Editor, Kit) connect those capabilities to a host protocol or runtime.
- Plugin packages (prefixed
volar-service-) extend capabilities for CSS frameworks, formatting, component libraries, etc.
Think of it as layers: Core → Service → Adapter. When you extend Volar, you usually write a plugin for the service layer; when you embed it, you pick or author an adapter.
Next Steps
- Decide which host you are targeting (LSP editor vs browser vs CLI).
- Scaffold a
createVolarServicehelper shared across adapters. - Add the plugins you need (Prettier, Tailwind, custom diagnostics).
- Document your initialization options so teams know how to tune Volar for their monorepo or tooling stack.
With these pieces in place you have a repeatable recipe for integrating any Vue-aware experience with the VolarJS ecosystem.
Troubleshooting Cheatsheet
- Take Over Mode conflicts (
@volar/vue-typescriptvs plain TS LS): ensure only one TS server runs by disabling the built-in TypeScript extension (VS Code) or pointing Neovim/Sublime to the Volar TS plugin. Mixed servers lead to duplicate diagnostics. vue-tscmisses project references: pass the sametsconfig.jsonand--projectpath you hand tocreateTypeScriptProject; Volar piggybacks on TS incremental builds, so mismatched configs spawn duplicate programs.- Custom plugins not firing: confirm they’re registered in both
language-core(for embedded files) andlanguage-service(for features). Manyvolar-service-*examples exporttsPluginandlanguageServiceto show both halves. - Broken source maps after transforms: verify that every
codeGen.addTextcall is paired withcodeGen.addMapping. Leverage@volar/source-map’stoGeneratedPositionshelpers to debug where a diagnostic lands. - High CPU in monorepos: reach for
@volar/kit’s file-watching filters (globs,ignored,maxFileSize) so unnecessary assets do not create snapshots. When embedding manually, reuse the same TSDocumentRegistry.