关于Vite的define注入全局变量的小细节
type
status
date
slug
summary
tags
category
icon
password
问题
我提供vite的define字段,实现把打包时间注入window全局。都是测试发现,在dev环境window.__BUILD_TIME__可以获取到值;而prod环境下,window.__BUILD_TIME__是不存在的
原因分析
define
字段的构建差异。
Vite 的
define
字段会在编译时进行静态替换(类似宏定义)。在开发环境(dev)中,代码是即时编译的,全局变量可能被保留;而在生产环境(prod)中,代码经过优化(如 Tree Shaking),可能导致 window.__BUILD_TIME__
未被正确挂载- 全局变量的作用域问题。
直接通过
define
定义的 __BUILD_TIME__
是全局常量,但未显式绑定到 window
对象。生产构建时,代码可能被压缩或优化,导致全局变量丢失解决方案
方法 1:显式绑定到 window
在入口文件(如
main.tsx
)中手动将变量赋值给 window
:方法 2:直接使用__BUILD_TIME__
而不是 window.__BUILD_TIME__
1. 直接使用
__BUILD_TIME__
的逻辑• 静态替换机制
Vite 的
define
字段会在编译阶段执行全局字符串替换,将代码中的 __BUILD_TIME__
直接替换为 JSON.stringify(new Date().toISOString())
生成的字符串值。这类似于 C 语言中的宏定义。- 生产环境优化
在生产构建时,Vite 会对代码进行压缩和 Tree Shaking。此时,
__BUILD_TIME__
已经被替换为具体的字符串(如 "2025-05-15T08:00:00Z"
),不再依赖 window
对象。因此,无论环境如何,都能直接通过变量名访问到值。2. 使用
window.__BUILD_TIME__
的逻辑• 开发环境的行为
在开发模式下,Vite 的代码未经过压缩,且全局变量可能被保留。此时,
define
注入的变量会默认挂载到全局作用域,因此通过 window.__BUILD_TIME__
可以访问。- 生产环境的问题
生产构建时,代码优化工具(如 Rollup)会尝试移除未显式声明的全局变量。由于
window.__BUILD_TIME__
未被明确绑定(例如未在入口文件中声明),优化器可能将其视为未使用的变量并删除,导致访问失败。关键差异总结
方式 | 开发环境表现 | 生产环境表现 | 原因 |
__BUILD_TIME__ | ✅ 直接访问 | ✅ 直接访问 | 编译时静态替换,与运行时环境无关 |
window.__BUILD_TIME__ | ✅ 可访问 | ❌ 不可访问 | 依赖运行时全局对象,生产优化可能删除未显式声明的全局变量 |
推荐方案
• 优先使用直接变量名
如
__BUILD_TIME__
,避免依赖 window
对象,确保编译时静态替换的可靠性。• 显式声明类型(TypeScript 项目)
在
env.d.ts
中声明全局变量类型: