Vue 项目打包后环境变量丢失问题(清除缓存),区分.env和.env.*文件
问题背景
今天在导报项目的时候遇到一个问题问题:在开发环境 中一切正常,但在打包后的生产环境中 ,某些环境变量(如 VUE_APP_BASE_API
)无法正确读取,导致出现 VUE_APP_BASE_API 不存在
的错误。
下面就解决这个问题 ,让环境变量在打包后的生产环境中能够正常使用 ,进行了进一步的思考衍生。
知识储备
要解决上面的问题需要,了解一下下面的内容
在开发 Vue 项目的过程中,使用环境变量来管理不同环境下的配置(例如 API 地址、密钥等)。
文件.env
开发环境 和生产环境公用的一些配置
//.env
VUE_APP_NAME=red润
VUE_APP_BASE_API=/api2
VUE_APP_API_BASE_URL=https://本地开发地址.com
文件.env.productioin
生产环境单独使用的配置 ,如果和.env
内容相同,.env.production
将会覆盖 .env
里面的内容
VUE_APP_API_BASE_URL=https://线上域名.com
VUE_APP_BASE_API=/api
在 Vue CLI 中,环境变量的加载是有优先级的 。当你运行构建命令时(如 npm run build
),Vue CLI 会按以下顺序加载环境变量:
.env
:基础的环境变量文件,通常包含开发、生产和测试等环境共享的变量。.env.local
:如果存在,它会覆盖.env
中的变量,适用于本地开发环境(注意:此文件通常不会提交到版本控制中)。.env.development
或.env.production
:这些文件用于特定环境(开发环境、生产环境等),会覆盖.env
和.env.local
中的相同变量。.env.development.local
或.env.production.local
:这些是针对特定环境的本地配置文件,会覆盖上述所有文件中的变量。
所以,在你的情况下,如果 .env.production
和 .env
中有相同的环境变量,process.env.VUE_APP_BASE_API
的值会使用 .env.production
中的值,而 .env
中的配置会被覆盖。
问题描述
在本地开发时,使用以下代码来引用环境变量:
const version = `${process.env.VUE_APP_BASE_API}`;
在开发环境下,process.env.VUE_APP_BASE_API
正常返回预期的值。
但是,当进行打包构建时,线上环境却出现了 VUE_APP_BASE_API 不存在
的错误,导致 API 请求无法正常发起。
问题原因
这个问题通常发生在 Vue CLI 构建项目时,它会自动根据不同环境加载不同的 .env
文件。如果 .env.production
或 .env
中没有正确配置环境变量,或者构建过程没有正确读取到这些变量,线上就无法获取到相应的环境变量。
解决方案
以下是几种常见的解决方法,我们可以逐一排查。
1. 确保 .env
文件配置正确
首先,确保你已经在项目根目录下创建了 .env
或 .env.production
文件,并且在文件中定义了所需要的环境变量。例如:
VUE_APP_BASE_API=https://your-api-endpoint.com
注意:Vue CLI 会自动加载以 VUE_APP_
为前缀的环境变量。如果你的环境变量没有以 VUE_APP_
开头,它将不会被嵌入到最终的构建中。
2. 清除缓存并重新打包(这是我的解决方案ok)
有时候旧的构建缓存 可能导致环境变量没有被更新。为了确保环境变量被正确加载,可以尝试在打包时加上 --no-cache
标志:
enpm run build --no-cache
这将确保构建过程从头开始,而不会使用任何缓存文件。
3. 打包时检查环境变量
你可以在构建过程中使用 console.log(process.env)
来检查环境变量是否正确加载。可以在 src/main.js
或 src/App.vue
中添加以下代码来调试:
console.log(process.env); // 打印所有环境变量
这将帮助你确认构建后的代码中是否包含了你设置的 VUE_APP_BASE_API
变量。
4. 使用 webpack 的 DefinePlugin
明确注入环境变量(究极方案)
如果以上方法都没有解决问题,可以尝试通过 webpack 的 DefinePlugin
来显式地将环境变量注入到构建代码中:
// vue.config.js
const webpack = require('webpack');
module.exports = {
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
'process.env.VUE_APP_BASE_API': JSON.stringify(process.env.VUE_APP_BASE_API)
})
]
}
}
这样,VUE_APP_BASE_API
将被直接注入到打包后的代码中,确保在生产环境中能够正常使用。
webpack.DefinePlugin
的作用
webpack.DefinePlugin
用于在打包时,静态地将代码中的指定字符串替换为给定的值。它会查找代码中的匹配项,并将其替换为我们提供的值。这是一种预处理机制,允许你在构建时动态替换代码中的常量值。
process.env
与环境变量
在 Node.js 中,
process.env
是一个包含所有环境变量的对象。在 Vue CLI 中,process.env
主要用于访问不同的环境变量。像VUE_APP_BASE_API
这样的变量通常在.env
文件中定义,并通过process.env.VUE_APP_BASE_API
来访问。
然而,process.env
只是 Node.js 的一个对象,Webpack 在构建过程中并不会自动注入这些环境变量。因此,使用DefinePlugin
插件,可以手动将这些环境变量注入到构建代码中。
JSON.stringify()
的作用
在
webpack.DefinePlugin
中,值需要以字符串的形式提供,因为 Webpack 会在构建时进行替换。直接传递 JavaScript 的对象或变量是无效的,因此必须使用JSON.stringify()
将process.env.VUE_APP_BASE_API
的值转换为一个字符串,这样 Webpack 才能正确地将它嵌入到构建后的代码中。
例如,如果.env
中的VUE_APP_BASE_API
为https://api.example.com
,JSON.stringify()
会将其转换为字符串'https://api.example.com'
,然后 Webpack 会将代码中所有process.env.VUE_APP_BASE_API
的引用替换为这个字符串。
如何工作
通过这种方式,Webpack 会在构建时查找代码中所有的
process.env.VUE_APP_BASE_API
,并将其替换为https://api.example.com
(或其他.env
文件中定义的值)。
举个例子,假设你在 Vue 组件中使用以下代码:
const apiUrl = process.env.VUE_APP_BASE_API;
在构建时,Webpack 会将 process.env.VUE_APP_BASE_API
替换为你在 webpack.DefinePlugin
中定义的值,即:
const apiUrl = 'https://api.example.com';
5. 检查部署环境的环境变量配置
如果你使用 CI/CD 进行自动化构建,确保部署环境(例如 Docker、云平台等)中也已经配置了正确的环境变量。在一些部署平台中,你可能需要手动设置环境变量,以便构建过程能正确读取。
总结
通过上述方法,我们可以有效地解决 Vue 项目在打包后,环境变量丢失的问题。我们解决思路如下:
- 确保
.env
文件正确配置。 - 清除缓存并重新打包。
- 使用
console.log(process.env)
检查环境变量是否正常加载。 - 使用 webpack
DefinePlugin
明确注入环境变量。 - 确保部署环境配置了正确的环境变量。