关于Vite的define注入全局变量的小细节
type
status
date
slug
summary
tags
category
icon
password

问题

 
我提供vite的define字段,实现把打包时间注入window全局。都是测试发现,在dev环境window.__BUILD_TIME__可以获取到值;而prod环境下,window.__BUILD_TIME__是不存在的
 

原因分析

  1. define 字段的构建差异
    1. Vite 的 define 字段会在编译时进行静态替换(类似宏定义)。在开发环境(dev)中,代码是即时编译的,全局变量可能被保留;而在生产环境(prod)中,代码经过优化(如 Tree Shaking),可能导致 window.__BUILD_TIME__ 未被正确挂载
       
  1. 全局变量的作用域问题
    1. 直接通过 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 中声明全局变量类型:

 

© ittat 2016-2025