Files
agent-skills/skills/vite/references/core-plugin-api.md
Jason Woltje f5792c40be feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories:
- anthropics/skills: 16 (docs, design, MCP, testing)
- obra/superpowers: 14 (TDD, debugging, agents, planning)
- coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth)
- better-auth/skills: 5 (auth patterns)
- vercel-labs/agent-skills: 5 (React, design, Vercel)
- antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo)
- Plus 13 individual skills from various repos

Mosaic Stack is not limited to coding — the Orchestrator and
subagents serve coding, business, design, marketing, writing,
logistics, analysis, and more.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:27:42 -06:00

236 lines
3.8 KiB
Markdown

---
name: vite-plugin-api
description: Vite plugin authoring with Vite-specific hooks
---
# Vite Plugin API
Vite plugins extend Rolldown's plugin interface with Vite-specific hooks.
## Basic Structure
```ts
function myPlugin(): Plugin {
return {
name: 'my-plugin',
// hooks...
}
}
```
## Vite-Specific Hooks
### config
Modify config before resolution:
```ts
const plugin = () => ({
name: 'add-alias',
config: () => ({
resolve: {
alias: { foo: 'bar' },
},
}),
})
```
### configResolved
Access final resolved config:
```ts
const plugin = () => {
let config: ResolvedConfig
return {
name: 'read-config',
configResolved(resolvedConfig) {
config = resolvedConfig
},
transform(code, id) {
if (config.command === 'serve') { /* dev */ }
},
}
}
```
### configureServer
Add custom middleware to dev server:
```ts
const plugin = () => ({
name: 'custom-middleware',
configureServer(server) {
server.middlewares.use((req, res, next) => {
// handle request
next()
})
},
})
```
Return function to run **after** internal middlewares:
```ts
configureServer(server) {
return () => {
server.middlewares.use((req, res, next) => {
// runs after Vite's middlewares
})
}
}
```
### transformIndexHtml
Transform HTML entry files:
```ts
const plugin = () => ({
name: 'html-transform',
transformIndexHtml(html) {
return html.replace(/<title>(.*?)<\/title>/, '<title>New Title</title>')
},
})
```
Inject tags:
```ts
transformIndexHtml() {
return [
{ tag: 'script', attrs: { src: '/inject.js' }, injectTo: 'body' },
]
}
```
### handleHotUpdate
Custom HMR handling:
```ts
handleHotUpdate({ server, modules, timestamp }) {
server.ws.send({ type: 'custom', event: 'special-update', data: {} })
return [] // empty = skip default HMR
}
```
## Virtual Modules
Serve virtual content without files on disk:
```ts
const plugin = () => {
const virtualModuleId = 'virtual:my-module'
const resolvedId = '\0' + virtualModuleId
return {
name: 'virtual-module',
resolveId(id) {
if (id === virtualModuleId) return resolvedId
},
load(id) {
if (id === resolvedId) {
return `export const msg = "from virtual module"`
}
},
}
}
```
Usage:
```ts
import { msg } from 'virtual:my-module'
```
Convention: prefix user-facing path with `virtual:`, prefix resolved id with `\0`.
## Plugin Ordering
Use `enforce` to control execution order:
```ts
{
name: 'pre-plugin',
enforce: 'pre', // runs before core plugins
}
{
name: 'post-plugin',
enforce: 'post', // runs after build plugins
}
```
Order: Alias → `enforce: 'pre'` → Core → User (no enforce) → Build → `enforce: 'post'` → Post-build
## Conditional Application
```ts
{
name: 'build-only',
apply: 'build', // or 'serve'
}
// Function form:
{
apply(config, { command }) {
return command === 'build' && !config.build.ssr
}
}
```
## Universal Hooks (from Rolldown)
These work in both dev and build:
- `resolveId(id, importer)` - Resolve import paths
- `load(id)` - Load module content
- `transform(code, id)` - Transform module code
```ts
transform(code, id) {
if (id.endsWith('.custom')) {
return { code: compile(code), map: null }
}
}
```
## Client-Server Communication
Server to client:
```ts
configureServer(server) {
server.ws.send('my:event', { msg: 'hello' })
}
```
Client side:
```ts
if (import.meta.hot) {
import.meta.hot.on('my:event', (data) => {
console.log(data.msg)
})
}
```
Client to server:
```ts
// Client
import.meta.hot.send('my:from-client', { msg: 'Hey!' })
// Server
server.ws.on('my:from-client', (data, client) => {
client.send('my:ack', { msg: 'Got it!' })
})
```
<!--
Source references:
- https://vite.dev/guide/api-plugin
-->