1. import.meta 是什么
- 归属:ECMAScript(ES Module)里的模块元信息,不是 Node 专有 API。
- 浏览器里:由引擎 + 构建工具(如 Vite)在模块代码里提供;Vite 会扩展出
import.meta.env、import.meta.hot 等。
- 为什么在控制台直接输入会报错:DevTools 默认不是
type="module" 的模块上下文,容易出现 Cannot use 'import.meta' outside a module。应在项目模块里 console.log,或用模块脚本验证。
2. import.meta.env 里到底有什么
- 不是整个
.env 文件原文,也不是机器上全部环境变量。
- 默认规则:只有以
VITE_ 开头的变量会暴露到前端 import.meta.env(可用 envPrefix 改,但要谨慎)。
- 另有:Vite 内置字段,如
MODE、BASE_URL、DEV、PROD、SSR 等(以当前 Vite 版本文档为准)。
- 未带
VITE_ 的变量:仍可被 vite.config 里 loadEnv() 读到,但不会自动进浏览器里的 import.meta.env。
3. .env 文件与 mode 怎么对应
vite / vite dev:默认 mode = development → 会加载 .env.development 等。
vite build:默认 mode = production → 会加载 .env.production 等。
- 显式指定:
vite build --mode test → 加载 .env.test;不会在默认 dev 下读 .env.test。
- 因此:写在
.env.test 里的 VITE_*,在 pnpm vite(development)下可能根本未加载,控制台就看不到。
4. 为什么用 VITE_ 前缀
- 目的:防止把数据库密码、内网地址等整份
.env 打进可在用户浏览器里执行的 JS。
VITE_ 表示:开发者明确允许该变量出现在前端构建产物里。
5. VITE_PROXY 与敏感信息
- 带
VITE_ 的变量有资格出现在 import.meta.env。
- 若业务代码从不访问
import.meta.env.VITE_PROXY,生产包未必会把该字符串打进 chunk;但在 dev 下若 console.log(import.meta.env),仍可能看到。
- 建议:仅给 Vite 开发服务器用的代理配置,用非
VITE_ 变量 + 只在 vite.config 里 loadEnv 读取,避免误暴露;不必为「配代理」强行抄进 test/pre/prod 的 .env.*,除非真有对应需求。
6. esbuild.drop 与 VITE_DROP_CONSOLE
项目中的逻辑(见 vite.config.ts):
drop: viteEnv.VITE_DROP_CONSOLE && isProdFn(mode) ? ['console', 'debugger'] : [],
isProdFn(mode):在 Node 读配置时判断,等价于 mode === 'production'(见 build/getEnv.ts)。
- 因此:只有
vite build 且未改 --mode(默认 production)或显式 --mode production 时,且 VITE_DROP_CONSOLE 为真,才会删 console / debugger。
vite build --mode test / pre 等:mode 不是 production,这条不会删 console(即使对应 .env 里写了 VITE_DROP_CONSOLE)。
- 开发:
mode === 'development',一般不删,方便调试。
- 与
build.minify: 'esbuild' 配合时,esbuild 相关选项才会在构建里稳定生效。
7. 「打包」≠ Vite 的 mode 一定是 production
- 每次
vite build 都是发布型构建(压缩等),但 mode 可以叫 test / pre / development / production,用于切换加载哪份 .env.* 和 import.meta.env.MODE。
vite build 不带 --mode:默认 mode = production。
8. getEnv.ts 的 isProdFn vs env.ts
getEnv.ts
export function isDevFn(mode: string): boolean {
return mode === 'development';
}
export function isProdFn(mode: string): boolean {
return mode === 'production';
}
export function isTestFn(mode: string): boolean {
return mode === 'test';
}
env.ts
*/
export const devMode = 'development'
export const testMode = 'test'
export const preMode = 'pre'
export const prodMode = 'production'
const KNOWN_LOGIN_ENV = new Set([devMode, testMode, preMode, prodMode])
export const getLoginEnv = () =>
import.meta.env.VITE_USER_MODE_ENV ?? (KNOWN_LOGIN_ENV.has(import.meta.env.MODE) ? import.meta.env.MODE : devMode)
export const isTestMode = () => getLoginEnv() === testMode
export const isPreMode = () => getLoginEnv() === preMode
export const isDevMode = () => import.meta.env.DEV
export const isProdMode = () => getLoginEnv() === prodMode
| 项目 | isProdFn(mode)(如 getEnv) | env.ts(如 getLoginEnv / isProdMode) |
|---|
| 运行位置 | 仅 Node,解析 vite.config 时 | 浏览器 / 打包后的前端代码 |
| 数据来源 | defineConfig(({ mode }) => ...) | import.meta.env(含 VITE_USER_MODE_ENV、MODE、DEV 等) |
| 用途 | 构建行为(删 console、代理等) | 业务逻辑(如版本检查间隔、登录环境) |
| 能否互相替代 | 不能:浏览器里调不到 isProdFn | 不能:vite.config 里不能靠运行时代码判断业务环境 |
isProdMode()(当前实现):getLoginEnv() === 'production',优先 VITE_USER_MODE_ENV,表达的是业务四环境,和 import.meta.env.PROD(是否「已构建产物」)不一定同一含义。
isDevMode():对应 import.meta.env.DEV(本地 dev server 为 true,一般 build 产物为 false)。
9. 快速对照表
| 问题 | 结论 |
|---|
控制台为何没有 import.meta | 默认非模块上下文 |
| 为何只有部分 env 出现在前端 | 默认仅 VITE_* + 内置字段 |
.env.test 在 dev 里看不到 | dev 默认 development,不加载 .env.test |
vite build 默认 mode | production |
| 删 console 何时生效 | mode === 'production' 且 VITE_DROP_CONSOLE 为真(按当前项目写法) |