4.1 KiB
4.1 KiB
name, description
| name | description |
|---|---|
| advanced-plugin-api | Creating Vite plugins, hooks, virtual modules, and client-server communication |
Plugin API
Vite plugins extend Rolldown's plugin interface with Vite-specific hooks.
Basic Plugin Structure
export default function myPlugin(options = {}) {
return {
name: 'vite-plugin-my-plugin',
// Hooks...
}
}
Naming Conventions
- Vite-only plugins:
vite-plugin-* - Rollup-compatible:
rollup-plugin-* - Framework-specific:
vite-plugin-vue-*,vite-plugin-react-*
Universal Hooks (from Rolldown)
Called on server start:
options- Modify Rolldown optionsbuildStart- Build starting
Called per module request:
resolveId- Resolve import pathsload- Load module contenttransform- Transform module code
Called on server close:
buildEndcloseBundle
Vite-Specific Hooks
config
Modify config before resolution:
{
name: 'modify-config',
config(config, { command, mode }) {
if (command === 'build') {
return {
resolve: {
alias: { foo: 'bar' }
}
}
}
}
}
configResolved
Access final resolved config:
{
name: 'read-config',
configResolved(config) {
this.config = config
}
}
configureServer
Add dev server middleware:
{
name: 'configure-server',
configureServer(server) {
// Before Vite's middlewares
server.middlewares.use((req, res, next) => {
// Handle request
next()
})
// Return function to run after Vite's middlewares
return () => {
server.middlewares.use((req, res, next) => {
// Post middleware
})
}
}
}
transformIndexHtml
Transform HTML files:
{
name: 'html-transform',
transformIndexHtml(html) {
return html.replace(/<title>(.*?)<\/title>/, '<title>New Title</title>')
}
}
Inject tags:
{
name: 'html-inject',
transformIndexHtml() {
return {
tags: [
{
tag: 'script',
attrs: { src: '/inject.js' },
injectTo: 'body' // 'head' | 'body' | 'head-prepend' | 'body-prepend'
}
]
}
}
}
handleHotUpdate
Custom HMR handling:
{
name: 'custom-hmr',
handleHotUpdate({ file, server, modules }) {
if (file.endsWith('.custom')) {
server.ws.send({
type: 'custom',
event: 'custom-update',
data: { file }
})
return [] // Prevent default HMR
}
}
}
Virtual Modules
Provide build-time information to source code:
export default function myPlugin() {
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:
import { msg } from 'virtual:my-module'
Client-Server Communication
Server to Client
{
configureServer(server) {
server.ws.on('connection', () => {
server.ws.send('my:greetings', { msg: 'hello' })
})
}
}
Client receives:
if (import.meta.hot) {
import.meta.hot.on('my:greetings', (data) => {
console.log(data.msg)
})
}
Client to Server
// Client
if (import.meta.hot) {
import.meta.hot.send('my:from-client', { msg: 'Hey!' })
}
// Server (in plugin)
{
configureServer(server) {
server.ws.on('my:from-client', (data, client) => {
console.log(data.msg)
client.send('my:reply', { msg: 'Got it!' })
})
}
}
Transform with Filtering
{
name: 'transform-js',
transform: {
filter: {
id: /\.js$/ // Only .js files
},
handler(code, id) {
return transformCode(code)
}
}
}
Path Normalization
Use POSIX separators for cross-platform compatibility:
import { normalizePath } from 'vite'
normalizePath('foo\\bar') // 'foo/bar'