从CRA迁移至Vite:如何将变量挂载到window对象
CRA 迁移到 Vite 4.3.5 后 window 变量挂载问题解析与解决方案
一、CRA 与 Vite 在全局变量处理上的核心差异
- 作用域隔离机制
- CRA 基于 Webpack,对 HTML 脚本的处理偏向传统模式:无论普通脚本还是模块脚本,挂载到
window的变量会直接进入全局作用域,其他脚本只要执行顺序正确就能访问。 - Vite 原生遵循 ES 模块规范,带
type="module"的脚本拥有独立作用域。即便在模块内修改window,如果其他脚本(尤其是非模块脚本)在模块加载完成前执行,就会出现无法读取属性的情况;同时 Vite 开发服务器的模块预构建机制,进一步强化了作用域隔离。
- CRA 基于 Webpack,对 HTML 脚本的处理偏向传统模式:无论普通脚本还是模块脚本,挂载到
- 脚本执行时机
- CRA 中普通脚本默认同步执行,模块脚本的加载顺序由依赖关系决定,全局挂载的变量会立即暴露。
- Vite 中模块脚本默认异步加载,若业务代码在模块脚本完成加载前尝试访问
window变量,自然会读取失败。而直接在 HTML 的<script>标签内定义变量(无type="module")时,脚本运行在全局作用域,变量会被立即挂载到window,因此能正常访问。
二、通过单独 config.js 实现 window 变量挂载的可行方案
方案1:保持模块格式,确保加载顺序与执行时机
在 config.js 中显式挂载变量,并确保业务代码在其加载完成后执行:
// config.js window.redirectToLogin = "你的登录跳转地址"; window.authAppUrl = "你的授权应用地址"; window.apiUrl = "你的API地址";
在 index.html 中,将依赖这些变量的脚本放在 config.js 之后,或给业务脚本添加 defer 属性:
<script type="module" src="/config.js"></script> <!-- 依赖变量的脚本放在后面,或添加 defer --> <script defer src="/your-business-script.js"></script>
如果是 React 应用入口脚本(比如 main.jsx),直接在入口顶部导入 config.js 即可:
// main.jsx import './config.js'; import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <App /> </React.StrictMode> );
方案2:将 config.js 改为全局作用域脚本(无 type="module")
放弃模块格式,让 config.js 运行在全局作用域,和 CRA 行为完全一致:
// config.js window.redirectToLogin = "你的登录跳转地址"; window.authAppUrl = "你的授权应用地址"; window.apiUrl = "你的API地址";
在 index.html 中引入时去掉 type="module":
<script src="/config.js"></script>
这种方式无需担心作用域和加载顺序问题,变量会被立即挂载到全局 window 对象。
方案3:使用 Vite 环境变量替代全局挂载(推荐)
如果变量是环境相关配置,更推荐用 Vite 原生环境变量机制,避免污染全局作用域:
- 在项目根目录创建
.env文件:
VITE_REDIRECT_TO_LOGIN="你的登录跳转地址" VITE_AUTH_APP_URL="你的授权应用地址" VITE_API_URL="你的API地址"
- 在代码中通过
import.meta.env访问:
// 业务代码中直接使用 const redirectToLogin = import.meta.env.VITE_REDIRECT_TO_LOGIN; const authAppUrl = import.meta.env.VITE_AUTH_APP_URL; const apiUrl = import.meta.env.VITE_API_URL;
这种方式符合 Vite 设计理念,同时支持开发/生产等不同环境的配置隔离。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

