vite plugin #

The Vite plugin is the recommended path for SvelteKit and Vite projects. It runs analysis at build time and serves the result as 'virtual:svelte-docinfo'. In dev it watches your source files, plus non-source files they import like internal/ modules, and reloads the page when an edit changes the result.

Setup
#

Requires Vite 6 or later.

  1. Add the plugin to vite.config.ts:

    import {defineConfig} from 'vite'; import {sveltekit} from '@sveltejs/kit/vite'; import svelteDocinfo from 'svelte-docinfo/vite.js'; export default defineConfig({ plugins: [sveltekit(), svelteDocinfo()], });
  2. Add TypeScript support in your app.d.ts:

    /// <reference types="svelte-docinfo/virtual-svelte-docinfo.js" />
  3. Import the virtual module anywhere in your app:

    import {modules, diagnostics} from 'virtual:svelte-docinfo'; // or use the default export: import data from 'virtual:svelte-docinfo'; // data.modules and data.diagnostics are the same as the named exports

    The shape is AnalyzeResultJson, the same as the programmatic API. See diagnostics for diagnostics.

If TypeScript reports Cannot find module 'virtual:svelte-docinfo', check the /// <reference> line in app.d.ts.

Options
#

All options are optional; the minimal call discovers files from package.json exports, falling back to glob:

svelteDocinfo()

Every option, with its default:

import svelteDocinfo from 'svelte-docinfo/vite.js'; svelteDocinfo({ // Project root directory. Default: Vite's resolved config.root. projectRoot: process.cwd(), // Glob patterns for file discovery. Forces glob mode under discovery: 'auto'. // Default: undefined (use exports discovery). // Each pattern's static base joins sourceOptions.sourcePaths; a pattern // with no base makes the whole project root source and logs an info line. include: ['src/**/*.ts', 'src/**/*.svelte'], // Exclude globs. An array replaces the default // ['**/*.test.ts', '**/*.spec.ts', '**/internal/**']; a callback extends // it. Replaces sourceOptions.exclude when both are set. node_modules and // dot-directories are always excluded. exclude: (defaults) => [...defaults, '**/*.gen.ts'], // Discovery strategy: 'auto' | 'exports' | 'glob'. Default: 'auto'. // 'auto' → exports first, glob fallback // 'exports' → strict; throws if package.json exports is missing or resolves to no files // 'glob' → skip exports, use glob patterns discovery: 'auto', // Dist directory for exports discovery. Default: 'dist'. distDir: 'dist', // Resolve module dependency graph. Default: true. resolveDependencies: true, // Partial overrides for default source options (SvelteKit src/lib layout). // Merged into createSourceOptions(projectRoot, sourceOptions). sourceOptions: {sourcePaths: ['src/lib']}, // dev re-analysis debounce in ms. Default: 100. hmrDebounceMs: 100, // Opt-in check that names are unique across modules, for packages with a // flat export namespace. Default: undefined (off). // 'diagnostic' → emit duplicate_declaration diagnostics // 'warn' → also log them // 'throw' → also fail the build onDuplicates: undefined, })

The plugin runs the same pipeline as analyzeFromFiles: discover, resolve dependencies, analyze. In dev, imports resolve through Vite's resolveId, so Vite aliases apply; in builds, the TypeScript default resolver is used (it honors tsconfig paths). hmrDebounceMs only affects the dev watcher.

Paths and patterns resolve against projectRoot. Absolute paths and patterns inside the root are accepted; anything outside it throws at config time.

CLI vs Vite plugin
#

The CLI runs analyzeFromFiles once; use it for CI and one-off generation. The plugin keeps a persistent createAnalysisSession, so dev re-analysis reuses parsed ASTs and svelte2tsx output; use it when the analysis feeds your app bundle. To drive a session yourself (custom bundler, LSP), see the session guide.

How it works
#

The plugin hooks into these Vite lifecycle stages:

  1. configResolved: validates options, so bad configs (like discovery: 'exports' with include, or a path outside the project root) fail at startup
  2. configureServer: in dev, watches source files and the non-source files they import (e.g. internal/ modules), debounces re-analysis, and reloads the page only when the output changes. Unchanged files aren't re-parsed.
  3. buildStart: creates a session, discovers and ingests the source files, runs query, and caches the result
  4. resolveId / load: serves the cached result as virtual:svelte-docinfo, exporting modules, diagnostics, and a default {modules, diagnostics}
  5. buildEnd: disposes the session, in dev when the server closes or restarts and in a build once the bundle's modules have loaded

Any change to the docs data reloads the page, even one that only shifts a declaration's source line, instead of letting Svelte HMR update components in place. Importers build state from the data (like a layout building a library from modules), so re-running the module alone would leave them stale.