为什么 Vite 的 define 在开发环境正常,构建后却得到 undefined?
问题出在读取方式上:配置的是 __APP_VERSION__,代码读取的却是 globalThis.__APP_VERSION__。按题目中的配置,应直接使用 __APP_VERSION__:
state: () => ({
// 其他状态保持原样
appVersion: __APP_VERSION__,
}),
这与现有的 define 配置和类型声明一致,应优先采用这种修复方式。
为什么开发环境能用,构建后却是 undefined?
Vite 的 define 在开发阶段提供全局值,在构建阶段执行静态替换,处理方式有所不同。Vite 官方文档说明了这一区别,Vite 8.0.1 的实现也保留了开发阶段注入全局值的处理。
在题目描述的浏览器开发环境中,注入的值可以通过全局对象访问,所以 globalThis.__APP_VERSION__ 能读到版本号。构建时,配置中的键用于匹配代码表达式:
define: {
__APP_VERSION__: JSON.stringify(packageJson.version),
},
这条规则的替换目标是标识符 __APP_VERSION__。globalThis.__APP_VERSION__ 是对象属性访问,属性名相同并不意味着它会匹配这条规则。
因此,根据给出的代码,访问方式可以解释开发与构建表现不同,无需先认定为 Vite 的构建缺陷。
配置和业务代码应该怎样写?
保留现有 Vue 插件等配置,将下面的 define 合并到 vite.config.ts 中:
import { defineConfig } from 'vite';
import packageJson from './package.json';
export default defineConfig({
// 保留项目原有的 plugins 等配置
define: {
__APP_VERSION__: JSON.stringify(packageJson.version),
},
});
原问题中的 import packageJson from 后面多了一个反引号。如果实际文件中也有这个字符,需要删除,否则会导致语法错误。这个问题应单独检查,不能用来解释成功构建后出现的 undefined。
在 vite-env.d.ts 中保留:
declare const __APP_VERSION__: string;
然后在 ApplicationStore.ts 中直接读取常量:
state: () => ({
// 其他状态保持原样
appVersion: __APP_VERSION__,
}),
AboutView.vue 中拼接标题的计算属性,以及 <NavBarTitle :title="appTitle" /> 的绑定方式,可以继续使用。
对于 package.json 中的版本 1.0.0,上述赋值在构建时的预期语义相当于:
appVersion: '1.0.0',
为什么写死版本号和修改 tsconfig 没有效果?
写死版本号只改变了替换值的来源,业务代码仍在访问 globalThis.__APP_VERSION__,表达式不匹配的问题还在。
将 package.json 加入 tsconfig.node.json 的 include,也不会改变 Vite 的替换目标。类型检查范围与 define 的表达式匹配属于不同环节。
同样,declare const __APP_VERSION__: string; 只提供 TypeScript 类型信息,不会生成 JavaScript,也不会在运行时给 globalThis 添加属性。Vite 文档要求添加该声明,是为了类型检查和编辑器提示。类型声明说明
如何确认修改生效?
修改配置后重启开发服务器,再重新构建并预览:
npx vite build
npx vite preview
如果项目的构建依赖自定义脚本或配置参数,应使用项目已有的构建、预览命令。
在预览页面检查标题。按题目中的版本号和拼接逻辑,预期显示 cDirector v1.0.0。如果仍有问题,检查构建是否加载了预期的配置文件,以及是否有条件配置覆盖了 define。
不要只在浏览器控制台输入 __APP_VERSION__ 来验证:构建产物中的引用可能已经被替换成字符串,控制台不一定存在同名全局变量。
备注:内容仅供参考。
