
Vite 生产构建会剥离匿名函数名,导致 func.name 为空;改用具名函数对象导出可保留名称,实现稳定注册全局 $filters。
vite 生产构建会剥离匿名函数名,导致 `func.name` 为空;改用具名函数对象导出可保留名称,实现稳定注册全局 `$filters`。
在 Vue 3 + Vite 项目中,为复用逻辑(如格式化函数),常希望模拟 Vue 2 的全局过滤器行为,通过 app.config.globalProperties.$filters 注册后在模板中直接调用:{{ $filters.currency(price) }}。但实践中发现:开发环境正常显示 func.name(如 "currency"),生产构建后却返回空字符串 ""——根本原因是 Vite 默认使用 esbuild 或 terser 压缩代码时,将数组内定义的具名函数(如 function currency() {...})转为匿名函数并优化掉名称信息,尤其当函数被包裹在数组字面量中时,其 name 属性无法被静态分析保留。
✅ 正确做法:避免将函数存入数组,改为直接导出具名函数组成的对象。这样函数以属性形式存在,名称在 AST 中清晰可辨,即使经过压缩仍能被正确提取:
// ./common/filters/currency.filter.ts
export const currency = (value: string | number): string => {
if (value == null) return ''
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(Number(value))
}
export const percent = (value: number): string => {
return `${(value * 100).toFixed(1)}%`
}
export default {
currency,
percent
}
然后在 main.ts 中统一注册:
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// 动态导入所有 filters 并注册到 $filters
const filtersModules = import.meta.glob('./common/filters/*.filter.ts', {
eager: true,
import: 'default'
})
app.config.globalProperties.$filters = {}
Object.values(filtersModules).forEach((module: Record<string function>) => {
Object.entries(module).forEach(([key, func]) => {
// ✅ key 即函数名,稳定可靠,不再依赖 func.name
app.config.globalProperties.$filters[key] = func
})
})
app.mount('#app')</string>
⚠️ 注意事项:
- 不要使用
import.meta.glob(..., { eager: true })后再.map()或.forEach()提取func.name—— 生产环境下不可靠; - 导出对象必须是 具名导出 + 默认导出对象结构(如
export const xxx = ...; export default { xxx }),确保键名与函数名一致; - 若需类型安全,可在
shims-vue.d.ts中补充声明:declare module '@vue/runtime-core' { interface ComponentCustomProperties { $filters: Record<string function> } }</string>
该方案兼顾可维护性与构建稳定性:每个过滤器文件职责单一、名称显式可控,且无需额外插件或配置,完全适配 Vite 默认构建流程。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











