Appearance
Vite 插件
Vite 的插件系统基于 Rollup 插件接口,并添加了 Vite 独有的钩子。插件是扩展 Vite 功能的主要方式,可以用于处理特定类型的文件、转换代码、注入全局变量等。
插件基础
插件结构
一个基本的 Vite 插件包含一个名称和一个或多个钩子函数:
javascript
export default function myPlugin() {
return {
name: 'my-plugin',
// 插件钩子
resolveId(id) {
// ...
},
load(id) {
// ...
}
}
}
使用插件
在 vite.config.js 中使用插件:
javascript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import myPlugin from './my-plugin'
export default defineConfig({
plugins: [
vue(),
myPlugin()
]
})
常用官方插件
@vitejs/plugin-vue
用于支持 Vue 3 单文件组件(SFC)。
bash
npm install @vitejs/plugin-vue -D
javascript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()]
})
@vitejs/plugin-react
用于支持 React 和 JSX。
bash
npm install @vitejs/plugin-react -D
javascript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()]
})
@vitejs/plugin-legacy
用于支持旧版浏览器。
bash
npm install @vitejs/plugin-legacy -D
javascript
import { defineConfig } from 'vite'
import legacy from '@vitejs/plugin-legacy'
export default defineConfig({
plugins: [
legacy({
targets: ['defaults', 'not IE 11']
})
]
})
插件钩子
构建阶段钩子
options
在构建开始时调用,用于修改构建选项。
javascript
export default function myPlugin() {
return {
name: 'my-plugin',
options(options) {
// 修改或返回新的选项
return options
}
}
}
buildStart
在构建开始时调用。
javascript
export default function myPlugin() {
return {
name: 'my-plugin',
buildStart() {
console.log('构建开始')
}
}
}
resolveId
用于解析模块 ID。
javascript
export default function myPlugin() {
return {
name: 'my-plugin',
resolveId(id) {
if (id === 'virtual:my-module') {
return id
}
}
}
}
load
用于加载模块内容。
javascript
export default function myPlugin() {
return {
name: 'my-plugin',
load(id) {
if (id === 'virtual:my-module') {
return 'export const msg = "hello world"'
}
}
}
}
transform
用于转换源代码。
javascript
export default function myPlugin() {
return {
name: 'my-plugin',
transform(code, id) {
if (id.endsWith('.custom')) {
// 转换自定义文件格式
return code.replace(/%VERSION%/g, '1.0.0')
}
}
}
}
buildEnd
在构建结束时调用。
javascript
export default function myPlugin() {
return {
name: 'my-plugin',
buildEnd() {
console.log('构建结束')
}
}
}
输出阶段钩子
renderStart
在输出阶段开始时调用。
javascript
export default function myPlugin() {
return {
name: 'my-plugin',
renderStart() {
console.log('开始生成输出')
}
}
}
banner/footer
为每个输出块添加头部/尾部代码。
javascript
export default function myPlugin() {
return {
name: 'my-plugin',
banner(chunk) {
return '// 版权所有 (c) 2023'
},
footer(chunk) {
return '// 构建完成'
}
}
}
Vite 特有钩子
config
在解析 Vite 配置前调用,可以修改配置。
javascript
export default function myPlugin() {
return {
name: 'my-plugin',
config(config, { command }) {
if (command === 'build') {
config.build.minify = 'terser'
}
return config
}
}
}
configResolved
在解析 Vite 配置后调用,可以读取最终配置。
javascript
export default function myPlugin() {
return {
name: 'my-plugin',
configResolved(resolvedConfig) {
console.log('基础路径:', resolvedConfig.base)
}
}
}
configureServer
在开发服务器配置时调用,可以修改服务器中间件。
javascript
export default function myPlugin() {
return {
name: 'my-plugin',
configureServer(server) {
server.middlewares.use((req, res, next) => {
// 自定义中间件逻辑
console.log(`请求: ${req.url}`)
next()
})
}
}
}
handleHotUpdate
处理热更新。
javascript
export default function myPlugin() {
return {
name: 'my-plugin',
handleHotUpdate(ctx) {
console.log('热更新:', ctx.file)
}
}
}
实用插件示例
虚拟模块插件
创建一个提供虚拟模块的插件:
javascript
export default function virtualModulePlugin() {
const virtualModuleId = 'virtual:my-config'
const resolvedVirtualModuleId = '\0' + virtualModuleId
return {
name: 'virtual-module',
resolveId(id) {
if (id === virtualModuleId) {
return resolvedVirtualModuleId
}
},
load(id) {
if (id === resolvedVirtualModuleId) {
return `
export const config = {
apiUrl: 'https://api.example.com',
version: '1.0.0'
}
`
}
}
}
}
使用该插件:
javascript
// 在代码中使用
import { config } from 'virtual:my-config'
console.log(config.apiUrl) // 输出: https://api.example.com
环境变量注入插件
创建一个注入环境变量的插件:
javascript
export default function envPlugin(options = {}) {
const { prefix = 'APP_' } = options
return {
name: 'env',
config(config) {
config.define = config.define || {}
// 将环境变量注入到代码中
Object.keys(process.env).forEach(key => {
if (key.startsWith(prefix)) {
config.define[`process.env. ${key}`] = JSON.stringify(process.env[key])
}
})
}
}
}
文件监听插件
创建一个文件监听插件:
javascript
import { readFileSync } from 'fs'
export default function fileWatcherPlugin(filePath) {
return {
name: 'file-watcher',
configureServer(server) {
server.watcher.add(filePath)
server.watcher.on('change', (file) => {
if (file === filePath) {
// 重新加载文件内容
const content = readFileSync(filePath, 'utf-8')
// 触发全页重载
server.ws.send({
type: 'full-reload',
path: '*'
})
}
})
}
}
}
社区插件
unplugin-auto-import
自动导入常用的 API。
bash
npm install unplugin-auto-import -D
javascript
import AutoImport from 'unplugin-auto-import/vite'
export default defineConfig({
plugins: [
AutoImport({
imports: ['vue', 'vue-router'],
dts: true
})
]
})
unplugin-vue-components
自动导入 Vue 组件。
bash
npm install unplugin-vue-components -D
javascript
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
Components({
resolvers: [ElementPlusResolver()]
})
]
})
vite-plugin-pwa
为应用添加 PWA 支持。
bash
npm install vite-plugin-pwa -D
javascript
import { VitePWA } from 'vite-plugin-pwa'
export default defineConfig({
plugins: [
VitePWA({
registerType: 'autoUpdate',
manifest: {
name: 'My App',
short_name: 'My App',
theme_color: '#ffffff',
icons: [
{
src: 'pwa-192x192.png',
sizes: '192x192',
type: 'image/png'
}
]
}
})
]
})
插件开发最佳实践
1. 使用插件工厂函数
始终使用工厂函数来创建插件,这样可以接受配置参数:
javascript
export default function myPlugin(options = {}) {
return {
name: 'my-plugin',
// 插件实现
}
}
2. 提供有意义的插件名称
插件名称应具有描述性且唯一,便于调试:
javascript
export default function myAwesomePlugin() {
return {
name: 'my-awesome-plugin', // 易于识别的名称
// ...
}
}
3. 合理处理错误
在插件中妥善处理错误,并提供有意义的错误信息:
javascript
export default function errorHandlingPlugin() {
return {
name: 'error-handler',
transform(code, id) {
try {
// 转换逻辑
return transformCode(code)
} catch (error) {
this.error({
message: `转换文件 ${id} 时出错`,
stack: error.stack
})
}
}
}
}
4. 优化性能
避免在插件中执行不必要的操作,只在必要时才处理文件:
javascript
export default function optimizedPlugin() {
return {
name: 'optimized-plugin',
transform(code, id) {
// 快速检查是否需要处理
if (!id.endsWith('.special')) {
return // 不处理此文件
}
// 执行转换
return processSpecialFile(code)
}
}
}
通过了解和使用 Vite 插件系统,您可以根据项目需求扩展 Vite 的功能,创建更加灵活和强大的开发环境。