Est.
Rapid Development with Vite
Vite deserves its own jotting here. It is the default development server / builder for Vue 3 and – as one might guess – it works under the hood of VitePress, which powers this site.
Development & Build
Vite is at least two things:
- Vite is a development server that pre-bundles dependencies using esbuild and serves resources via efficient HMR.
- Vite can build static web sites using Rollup (with an extended plugin API) for bundling.
Its main advantage in development is its tremendous speed. Thanks to HMR support, the changes are visible in the browser as soon as you save your file in the IDE. And by file
I don't mean HTML or CSS files. This also works perfectly for Markdown and Vue components, whether written in JavaScript or TypeScript. Vite runs all the necessary plugins to convert the files to what the browser needs, and uses the result to update the version in the browser. Sometimes I'm tempted to tell VS Code to continuously auto-save, just to see how the page is changing in the browser as I type.
In addition, Vite has a very short startup time. Vite focuses its dynamic effort on the sources in the local project. These files change frequently during development. In contrast, the dependencies in node_modules do not change or at least not frequently. Vite serves all dependencies from a precompiled bundle and only has to take care of individual source files when they do change.
Plugins
Vite's plugin API has a large overlap with Rollup's API. Vite adds some Vite-specific hooks to the Rollup plugin API. It is possible, to write plugins that work for both Vite and Rollup. Vite applies the plugins in development mode and through bundling. Some existing Rollup plugins can be used directly with Vite, but not all Rollup plugins might make sense for Vite in development mode. The extensions that Vite adds to Rollup's API are mainly for configuration, server mode and HMR.
For this VitePress site, I installed some plugins for Vite. Some are node packages, some are part of this project.
Plugin | Description |
---|---|
vite-imagetools | JonasKruckenberg/imagetools, image processing with sharp . |
asOf | internal, see adding creation and last modification dates. |
check dead-links | internal, see automated consistency checks. |
defLinks | internal, see automatically adding links to glossary items. |
dot mermaid | internal, see Graphs with Mermaid & Dot. |
searchIndex | internal, see building the search index. |
topics | internal, see building the topic map. |
importFonts | internal. Fix for missing hoisting when vite bundles CSS with @import and states:warnings when minifying css: ▲ [WARNING] All "@import" rules must come first. Hopefully superfluous with future VitePress versions. |
API (excerpt)
A small plugin just defines a name
, a transform
function, and optionally an enforcement
. The enforcement
attribute states wether the plugin should run before the core plugins (pre
), after the build plugins (post
) or in between those two groups (no enforcement). The transform
function has two parameters: The content of the file (text
) and the path of the file (id
). In the simplest case the function might return a modified version of the input, like the defLinks
plugin that inserts links to the glossary. The transform
function might even return the unmodified content: e.g. my searchIndex
plugin is readonly and only records the words in the content for the search index.
enforce: "pre",
name: "defLinks",
transform: function (text: string, id: string) {...},
enforce: "pre",
name: "defLinks",
transform: function (text: string, id: string) {...},
At the end of the build the searchIndex
plugin wants to write a index.json
file as a cache for development mode. To do this, it defines closeBundle
and writes the index to file. The file is only used in development mode and is re-read in the configResolved
function when the plugin is started, and only if config.command !== 'build'
. When the plugin is invoked in build mode (config.command === 'build'
), the plugin starts with an empty index. The resolveId
function tells Vite, that index.json is a virtual resource that does not need to be loaded from disk. The load
function delivers it directly by returning JSON.stringify()
of the plugin's in-memory index. Therefore, the plugin defines the following functions:
enforce: "pre",
name: "searchIndex",
configResolved: function (config: { command: string }) {...},
resolveId: function (id: string): ResolveIdResult {...},
load: function (id: string) {...},
transform: function (text: string, id: string) {...},
closeBundle: function () {...},
enforce: "pre",
name: "searchIndex",
configResolved: function (config: { command: string }) {...},
resolveId: function (id: string): ResolveIdResult {...},
load: function (id: string) {...},
transform: function (text: string, id: string) {...},
closeBundle: function () {...},
In addition you can define all the Rollup functions and further Vite-specific functions, see the Vite plugin API.