Files
volar-docs/docs/getting-started.md
2025-11-09 22:22:52 -06:00

11 KiB
Raw Blame History

VolarJS Getting Started

Docs IndexRepo READMEPlugin AuthoringSource Map & Code GenConfiguration & 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)
  1. File understanding happens in @volar/language-core. It parses Vue SFCs, tracks virtual files, and creates source maps between template/script/style sections.
  2. Language features live in @volar/language-service (hover, completion, diagnostics, etc.) and are provided by plugins. Vues default feature set is one plugin; you can add more.
  3. Adapters such as @volar/language-server or @volar/monaco connect 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 users 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 with volar-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-map to keep every generated byte mapped back to the users SFC so diagnostics and quick fixes land in the right spot.

Common Integration Paths

1. Shipping an LSP Server (VS Code, Neovim, Sublime)

  1. Install @volar/language-server.
  2. Create an entry.ts that calls createLanguageServer (or use @volar/kits CLI helpers) and forwards stdio (or node IPC) to the editor.
  3. 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)

  1. Install @volar/monaco.
  2. Register workers and configure virtual file resolution (fetch files over HTTP, from memory, etc.).
  3. Attach the Volar language service to Monacos languages.register API.
  4. For fully custom editors, use @volar/editor to avoid wiring the text-buffer plumbing from scratch.

3. Running Volar Inside a CLI

  1. Build the service as shown earlier (or bootstrap via @volar/kit which wires file watching + reloads).
  2. Call methods like doValidation, findReferences, or format on demand.
  3. Perfect for codemods, lint rules, or CI checks that require Vue awareness without firing up an editor.

How the Pieces Fit

  • @volar/language-core owns document truth (what files exist, how they map).
  • @volar/code-gen and @volar/source-map make sure generated TS/JS stays tied to the users original locations.
  • @volar/typescript keeps Volar in sync with TSs program graph.
  • @volar/language-service exposes 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

  1. Decide which host you are targeting (LSP editor vs browser vs CLI).
  2. Scaffold a createVolarService helper shared across adapters.
  3. Add the plugins you need (Prettier, Tailwind, custom diagnostics).
  4. 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-typescript vs 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-tsc misses project references: pass the same tsconfig.json and --project path you hand to createTypeScriptProject; Volar piggybacks on TS incremental builds, so mismatched configs spawn duplicate programs.
  • Custom plugins not firing: confirm theyre registered in both language-core (for embedded files) and language-service (for features). Many volar-service-* examples export tsPlugin and languageService to show both halves.
  • Broken source maps after transforms: verify that every codeGen.addText call is paired with codeGen.addMapping. Leverage @volar/source-maps toGeneratedPositions helpers to debug where a diagnostic lands.
  • High CPU in monorepos: reach for @volar/kits file-watching filters (globs, ignored, maxFileSize) so unnecessary assets do not create snapshots. When embedding manually, reuse the same TS DocumentRegistry.