版本:0.1.5 | 协议:MIT | 依赖:Vite ^5.0.0 || ^6.0.0 || ^7.0.0
写在前面
v0.1.5 的主题是:让 import 语句自动生成,让工具层只保留真正的复用逻辑。
每次写 Vue 组件都要手动 import { ref, reactive, computed } from 'vue',每次用 useRouter 都要 import { useRouter } from 'vue-router'------这些重复的导入语句既繁琐又容易遗漏。v0.1.5 带来的 autoImport
插件,让你彻底告别手动 import。同时,我们对 Common 工具模块进行了精简,移除了使用不足的模块,只保留真正在多处复用的核心工具。
本版重点:
| 能力 | 一句话说明 | 你需要做什么 |
|---|---|---|
autoImport 插件 |
自动检测标识符并注入 import 语句 | 新增配置 |
| Common 工具模块精简 | 移除 compress/object/path,保留 6 个核心模块 | 检查依赖 |
升级方式 :修改 devDependencies 中版本号为 ^0.1.5。注意:common/compress、common/object、common/path 三个子路径已移除,如有使用请迁移。
一、5 分钟快速上手
1.1 安装与最小配置
json
{
"devDependencies": {
"@meng-xi/vite-plugin": "^0.1.5"
}
}
typescript
import { autoImport } from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [
autoImport({
imports: {
vue: ['ref', 'reactive', 'computed', 'watch', 'onMounted']
}
})
]
})
1.2 立刻看到效果
之前:每个组件都要手动导入
vue
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
const count = ref(0)
const state = reactive({ name: 'app' })
const double = computed(() => count.value * 2)
onMounted(() => {
console.log('mounted')
})
</script>
之后:直接使用,无需导入
vue
<script setup lang="ts">
const count = ref(0)
const state = reactive({ name: 'app' })
const double = computed(() => count.value * 2)
onMounted(() => {
console.log('mounted')
})
</script>
插件会自动检测代码中使用的 ref、reactive、computed 等标识符,并在文件顶部注入对应的 import 语句。
1.3 它解决了什么
typescript
// ❌ 没有 autoImport 的日常
import { ref, reactive, computed, watch, onMounted, onUnmounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { storeToRefs } from 'pinia'
// ... 每个文件都要写一遍
// ✅ 有 autoImport:配置一次,全局生效
autoImport({
imports: {
vue: ['ref', 'reactive', 'computed', 'watch', 'onMounted', 'onUnmounted'],
'vue-router': ['useRouter', 'useRoute'],
pinia: ['storeToRefs']
}
})
二、核心能力:autoImport 四大特性
autoImport 从四个维度提供自动导入能力:
预设映射 ──→ 目录扫描 ──→ Vue 模板 ──→ 类型声明
(配置) (自动) (增强) (开发体验)
2.1 预设映射:声明式配置导入规则
简写格式
最常用的方式,键为模块路径,值为导入名称数组:
typescript
autoImport({
imports: {
vue: ['ref', 'reactive', 'computed', 'watch', 'onMounted'],
'vue-router': ['useRouter', 'useRoute'],
pinia: ['defineStore', 'storeToRefs']
}
})
完整格式
支持默认导入配置:
typescript
autoImport({
imports: [
{ module: 'lodash', names: ['debounce', 'throttle'], defaultImport: false },
{ module: 'dayjs', names: ['dayjs'], defaultImport: true }
// 生成: import dayjs from 'dayjs'
]
})
混合格式
两种格式可以在数组中混合使用:
typescript
autoImport({
imports: [{ vue: ['ref', 'reactive', 'computed'] }, { module: 'lodash', names: ['debounce'], defaultImport: false }, { 'vue-router': ['useRouter', 'useRoute'] }]
})
2.2 目录扫描:自动发现模块导出
配置 dirs 后,插件会自动扫描指定目录下的 .ts/.js/.mts/.mjs 文件,将导出的函数、变量、类注册为可自动导入的标识符:
typescript
autoImport({
dirs: ['src/composables', 'src/stores', 'src/utils']
})
扫描规则:
| 规则 | 说明 |
|---|---|
| 递归扫描 | 自动遍历子目录 |
| 跳过 node_modules | 忽略依赖目录 |
| 跳过隐藏目录 | 忽略以 . 开头的目录 |
| 跳过 .d.ts | 忽略类型声明文件 |
| 支持的扩展名 | .ts、.js、.mts、.mjs |
目录结构示例:
src/composables/
├── useAuth.ts → export function useAuth() {}
├── useFetch.ts → export function useFetch() {}
└── useTheme.ts → export const useTheme = () => {}
配置 dirs: ['src/composables'] 后,useAuth、useFetch、useTheme 均可自动导入。
2.3 Vue 模板支持:template 中也能自动导入
开启 vueTemplate 后,Vue SFC <template> 中使用的 API 也会被自动导入:
typescript
autoImport({
imports: { vue: ['ref', 'computed'] },
vueTemplate: true
})
vue
<template>
<!-- ref 和 computed 无需在 script 中导入即可在模板中使用 -->
<p>{{ count }}</p>
<p>{{ double }}</p>
</template>
<script setup lang="ts">
const count = ref(0)
const double = computed(() => count.value * 2)
</script>
检测范围:
| 位置 | 示例 |
|---|---|
| 插值表达式 | {``{ count }} |
| 指令绑定 | v-if="isVisible" |
| 属性绑定 | :class="activeClass" |
| 事件绑定 | @click="handleClick" |
2.4 类型声明生成:IDE 智能提示
开启 dts 后,插件自动生成 .d.ts 类型声明文件,让 IDE 识别全局可用的标识符:
typescript
autoImport({
imports: { vue: ['ref', 'reactive', 'computed'] },
dts: 'src/auto-imports.d.ts'
})
生成的 src/auto-imports.d.ts:
typescript
// 由 @meng-xi/vite-plugin/autoImport 自动生成
// 请勿手动修改
declare const ref: (typeof import('vue'))['ref']
declare const reactive: (typeof import('vue'))['reactive']
declare const computed: (typeof import('vue'))['computed']
dts 选项:
| 值 | 行为 |
|---|---|
'path' |
在指定路径生成类型声明文件 |
true |
使用默认路径 auto-imports.d.ts |
false |
不生成类型声明文件 |
三、精细控制
3.1 忽略标识符
某些标识符可能已通过其他方式全局注册,不需要自动导入:
typescript
autoImport({
imports: { vue: ['ref', 'reactive'] },
ignore: ['React'] // React 已通过 CDN 全局注入
})
3.2 文件过滤
控制哪些文件需要被 transform 钩子处理:
typescript
autoImport({
fileFilter: /\.(vue|tsx|ts)$/ // 只处理 .vue、.tsx、.ts 文件
})
3.3 注入位置
控制 import 语句在文件中的插入位置:
typescript
autoImport({
injectAtPosition: 'after-last-import' // 注入到最后一个 import 之后
})
| 位置 | 行为 |
|---|---|
'top' |
注入到文件有效代码最顶部(默认) |
'after-last-import' |
注入到最后一个已有 import 之后,无则回退顶部 |
四、Common 工具模块精简
v0.1.5 对 Common 工具模块进行了严格审查,移除了使用次数不足 2 次的模块和函数,只保留在多处被复用的核心工具。
4.1 移除的模块
| 模块 | 移除原因 | 迁移方式 |
|---|---|---|
common/compress |
calculateGzipSize 仅在 bundleAnalyzer 使用 |
已内联到 bundleAnalyzer 插件 |
common/object |
deepMerge 仅在 loadingManager 使用 |
已内联到 loadingManager 插件 |
common/path |
isNodeModule 仅在 bundleAnalyzer 使用 |
已内联到 bundleAnalyzer 插件 |
4.2 移除的函数
以下函数因仅在单处使用,已从 common 中移除并内联到各自的消费者中:
| 函数 | 原所属模块 | 当前位置 |
|---|---|---|
padNumber |
common/format | buildProgress 插件内部 |
generateRandomHash |
common/format | generateVersion 插件内部 |
formatDate |
common/format | generateVersion 插件内部 |
parseTemplate |
common/format | htmlInject 插件内部 |
toCamelCase |
common/format | autoImport 插件内部 |
toPascalCase |
common/format | autoImport 插件内部 |
stripJsonComments |
common/format | autoImport 插件内部 |
escapeHtmlAttr |
common/format | htmlInject 插件内部 |
getExtension |
common/format | bundleAnalyzer 插件内部 |
SPINNER_FRAMES |
common/ui | buildProgress 插件内部 |
stripAnsi |
common/ui | buildProgress 插件内部 |
4.3 保留的 6 个核心模块
| 模块 | 描述 | 导出内容 |
|---|---|---|
common/format |
格式化工具 | getDateFormatParams、formatFileSize、DateFormatOptions |
common/fs |
文件系统工具 | checkSourceExists、copySourceToTarget、writeFileContent、scanDirectory、writeJsonReport 及相关类型 |
common/html |
HTML 注入工具 | injectBeforeTag、injectHeadAndBody、sanitizeContent 及相关类型 |
common/script |
脚本生成工具 | makeCallback |
common/ui |
终端 UI 工具 | ANSI |
common/validation |
参数验证工具 | Validator、validateGlobalName、validateNoScriptInTemplate、validateCallbackFields |
精简原则:只有被 ≥2 个模块使用的逻辑才保留在 common 中。单一消费者内部的工具函数应内联到消费者中,避免 common 成为"万能垃圾桶"。
五、实战场景
5.1 Vue 3 + Vue Router + Pinia 全家桶
typescript
import { defineConfig } from 'vite'
import { autoImport, buildProgress, envGuard } from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [
autoImport({
imports: {
vue: ['ref', 'reactive', 'computed', 'watch', 'watchEffect', 'onMounted', 'onUnmounted', 'nextTick'],
'vue-router': ['useRouter', 'useRoute', 'onBeforeRouteLeave'],
pinia: ['defineStore', 'storeToRefs']
},
dts: 'src/auto-imports.d.ts',
vueTemplate: true
}),
buildProgress({ format: 'bar' }),
envGuard({
required: {
VITE_API_URL: { type: 'url', required: true }
}
})
]
})
5.2 自动扫描 composables 目录
typescript
import { autoImport } from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [
autoImport({
imports: {
vue: ['ref', 'reactive', 'computed', 'onMounted']
},
dirs: ['src/composables', 'src/stores'],
dts: 'src/auto-imports.d.ts',
vueTemplate: true
})
]
})
5.3 uni-app 项目(仅 H5 平台)
typescript
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import { autoImport } from './uni_modules/vite-plugin/js_sdk/index.mjs'
export default defineConfig({
plugins: [
uni(),
autoImport({
imports: {
vue: ['ref', 'reactive', 'computed', 'watch', 'onMounted', 'onUnmounted']
},
dts: 'auto-imports.d.ts',
vueTemplate: true,
enabled: process.env.UNI_PLATFORM === 'h5'
})
]
})
六、autoImport 完整配置参考
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| imports | Record<string, string[]> | ImportMapping[] | Array<...> |
{} |
导入映射配置 |
| dirs | string[] |
[] |
需要扫描的目录列表 |
| dts | string | boolean |
'auto-imports.d.ts' |
类型声明文件输出路径,false 不生成 |
| vueTemplate | boolean |
false |
是否为 Vue 模板启用自动导入 |
| ignore | string[] |
[] |
需要忽略的标识符列表 |
| fileFilter | RegExp |
`/.(vue | jsx |
| injectAtPosition | 'top' | 'after-last-import' |
'top' |
import 语句注入位置 |
ImportMapping 类型:
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| module | string |
--- | 模块路径 |
| names | string[] |
--- | 要导入的名称列表 |
| defaultImport | boolean |
false |
是否为默认导入 |
ResolvedImport 类型:
| 属性 | 类型 | 描述 |
|---|---|---|
| module | string |
模块路径 |
| name | string |
导入标识符名称 |
| isDefault | boolean |
是否为默认导入 |
ScannedModule 类型:
| 属性 | 类型 | 描述 |
|---|---|---|
| filePath | string |
模块文件的绝对路径 |
| exports | string[] |
命名导出名称列表 |
| defaultExport | string | null |
默认导出名称,无则为 null |
TransformResult 类型:
| 属性 | 类型 | 描述 |
|---|---|---|
| code | string |
转换后的代码字符串 |
| map | any |
Source map 信息(可选) |
七、迁移指南
从 v0.1.4 升级到 v0.1.5
1. 检查 common 子路径导入
如果项目中使用了以下子路径,需要移除或替换:
typescript
// ❌ 已移除
import { calculateGzipSize } from '@meng-xi/vite-plugin/common/compress'
import { deepMerge } from '@meng-xi/vite-plugin/common/object'
import { isNodeModule } from '@meng-xi/vite-plugin/common/path'
// ✅ 这些功能已内联到对应插件中,如需使用请直接调用插件内部逻辑
// 或自行实现等价函数
2. 检查 common barrel 导入
以下函数已从 @meng-xi/vite-plugin/common 中移除:
typescript
// ❌ 已移除的导出
import {
calculateGzipSize, // → 内联到 bundleAnalyzer
deepMerge, // → 内联到 loadingManager
isNodeModule, // → 内联到 bundleAnalyzer
SPINNER_FRAMES, // → 内联到 buildProgress
stripAnsi, // → 内联到 buildProgress
escapeHtmlAttr, // → 内联到 htmlInject
getExtension, // → 内联到 bundleAnalyzer
padNumber, // → 内联到 buildProgress
generateRandomHash, // → 内联到 generateVersion
formatDate, // → 内联到 generateVersion
parseTemplate, // → 内联到 htmlInject
toCamelCase, // → 内联到 autoImport
toPascalCase, // → 内联到 autoImport
stripJsonComments // → 内联到 autoImport
} from '@meng-xi/vite-plugin/common'
3. 新增 autoImport 插件(可选)
typescript
import { autoImport } from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [
autoImport({
imports: { vue: ['ref', 'reactive', 'computed'] },
dts: 'src/auto-imports.d.ts',
vueTemplate: true
})
]
})
本文基于 @meng-xi/vite-plugin@0.1.5 版本撰写,所有代码示例均来自实际源码。