CodeVetter · Repo Unpack · Extension points
vitejs/vite
Vite's primary extension mechanism is the plugin object — a superset of Rolldown/Rollup's, adding `config`, `configEnvironment`, `configureServer`, `configurePreviewServer`, `transformIndexHtml`, `hotUpdate`, `buildApp`, and the environment-scoping fields `applyToEnvironment`/`sharedDuringBuild`. The ordered array returned by `resolvePlugins` is the canonical insertion-point table: user `pre`, `normal` and `post` plugins are spliced at three fixed positions between internal plugins. Beyond plugins, the extension surface includes the environment factory (`dev.createEnvironment`/`build.createEnvironment`), the hot-channel/transport abstraction, the CLI shortcut table, and the `create-vite` template directory convention.
- `resolvePlugins(config, prePlugins, normalPlugins, postPlugins)` is the ordering contract: user `pre` plugins land after the alias plugins, `normal` plugins after asset/CSS/worker handling but before `definePlugin`, and `post` plugins after the glob/dynamic-import plugins — with `clientInjectionsPlugin`, `cssAnalysisPlugin` and `importAnalysisPlugin` always last.
- `getSortedPluginsByHook(hookName, plugins)` implements the per-hook `order: 'pre' | 'post'` sorting with three running indices, and `createPluginHookUtils` memoises the result per hook name into `getSortedPlugins`/`getSortedPluginHooks` on the resolved config.
- `applyToEnvironment(environment)` lets a plugin opt in/out per environment or return a *replacement* plugin — as the built-in alias plugin does, swapping itself for Rolldown's native `nativeAliasPlugin` when `environment.config.isBundled` and no custom resolver is present.
- `perEnvironmentPlugin(name, applyToEnvironment)` is the public helper for building environment-scoped plugins, exported from the package root alongside `perEnvironmentState`.
- `buildApp` is the multi-environment build orchestration hook: `builder.buildApp()` walks `config.getSortedPlugins('buildApp')` and interleaves `configBuilder.buildApp(builder)` just before the first `order: 'post'` hook, letting frameworks control environment build order and interdependencies.
- `hotUpdate` is the environment-aware replacement for `handleHotUpdate`: `getSortedHotUpdatePlugins(environment)` selects the plugins and each hook receives a `HotUpdateOptions` with `{type, file, timestamp, read, server, modules}` and may return a filtered module list.
- Environments are created through configurable factories — `environmentOptions.dev.createEnvironment(name, config, { ws })` at server start and `config.build.createEnvironment(name, config)` in `createBuilder.setupEnvironment` — with `defaultCreateDevEnvironment`/`defaultCreateClientDevEnvironment` as the built-in defaults.
- The HMR transport is pluggable on both ends: server-side via `normalizeHotChannel` and `createServerHotChannel()` (exported publicly), client/runtime-side via `normalizeModuleRunnerTransport` and `createWebSocketModuleRunnerTransport` in `src/shared/moduleRunnerTransport.ts`.
- `bindCLIShortcuts({ print, customShortcuts })` accepts an array of `CLIShortcut<Server>` objects (`{ key, description, action }`) merged with the built-in table — the mechanism the CLI itself uses to add the `p` profiler toggle.
- Plugin hook filtering is an extension point with its own registry: `getCachedFilterForPlugin(plugin, hookName)` builds and WeakMap-caches `createIdFilter` / `createFilterForTransform` matchers from a hook's `filter: { id, code, moduleType }` object.
- `createIdResolver(config, options)` is exported as the supported way for plugins to reuse Vite's resolver, and `config.createResolver(options)` wraps it with per-environment `PartialEnvironment` instances for client and ssr.
- `create-vite` extends purely by directory convention — each entry in the `FRAMEWORKS` variants table maps to a sibling `template-<name>` directory (`template-react-ts`, `template-svelte`, `template-qwik-ts`, …), so adding a template means adding a directory plus a table entry.
- The dev-server middleware chain is extensible only through `configureServer` (pre and post phases) and `configurePreviewServer`; there is no separate middleware registry, so ordering is controlled by which phase a plugin uses.
- DevTools integration is a first-class optional extension: `loadDevToolsIntegrationPlugins(config, command, devtoolsOptions)` injects plugins during `resolveConfig`, and `resolveDevToolsConfig` / `isDevToolsOptionEnabled` gate it behind the optional `@vitejs/devtools` peer dependency.