创建反应应用程序无法在构建后读取环境变量
create react app cannot read environment variable after build
我有一个 React 应用程序,使用 create-react-app
创建,然后我使用以下命令构建应用程序:npm run build
它在构建后使用 serve
到 运行 应用程序,如果我们通过 运行ning ENV=production npm run start
使用开发代码启动应用程序它可以读取 process.env.ENV
变量,因为我将这个插件添加到 webpack 开发配置中
new webpack.DefinePlugin({
'process.env':{
'ENV': JSON.stringify(process.env.ENV),
}
}),
我也将上面的脚本添加到webpack prod config中,但是如果我在构建后尝试这个命令ENV=prod serve -s build
,它无法读取环境变量
如何解决这个问题?
无法读取ENV
var 的原因是:
(1) 在 开发 模式下 webpack
监视您的文件并动态捆绑您的应用程序。它还会读取(因为 DefinePlugin
)您的 process.env.ENV
并将其添加为全局变量。所以它基本上是从 process.env
到你的 JS 应用程序的管道变量。
(2) 在您 构建 您的应用程序(使用 webpack
)之后,所有内容都已捆绑到一个或多个文件中。当您 运行 serve
时,您只需启动一个为 static 构建文件提供服务的 HTTP 服务器。因此无法将 ENV
通过管道传输到您的应用程序。
基本上 DefinePlugin
所做的就是向捆绑包中添加一个 var
。例如
new webpack.DefinePlugin({
'token': '12356234ga5q3aesd'
})
将添加类似这样的一行:
var token = '12356234ga5q3aesd';
因为 JS 文件是 static 没有办法改变这个变量 after 你 build/bundled 它与webpack
。基本上,当您执行 npm run build
时,您正在创建已编译的二进制文件/.dll
/.jar
/... 文件并且不能再通过插件影响其内容。
您可以将 .env
文件添加到项目的根目录并在那里定义环境变量。这将是您的默认(生产)环境变量定义。但是你可以有一个名为 .env.local
的本地文件来覆盖默认值。
定义环境变量时,请确保它们以 REACT_APP_
开头,这样您的环境变量定义将如下所示:
REACT_APP_SERVER_URL=https://my-awesome-app.herokuapp.com
此外,将其添加到 .gitignore 中,这样您就不会提交本地覆盖:
.env*.local
参考:
Adding Development Environment Variables In .env (create-react-app)
来自create-react-app documentation:
Your project can consume variables declared in your environment as if
they were declared locally in your JS files. By default you will have
NODE_ENV defined for you, and any other environment variables starting
with REACT_APP_.
您可以从代码中的 process.env 读取它们:
render() {
return (
<div>
<small>You are running this application in <b>{process.env.NODE_ENV}</b> mode.</small>
<form>
<input type="hidden" defaultValue={process.env.REACT_APP_NOT_SECRET_CODE} />
</form>
</div>
);
}
如果您在 app.config.js
中设置了所有环境变量,您可以在 main.????????.chunk.js
文件中构建 之后替换它们 。
示例 app.config.js
可能如下所示:
export default {
SOME_URL: "https://${ENV_VAR_1}"
SOME_CONFIGURATION: "${ENV_VAR_2}",
}
保持 app.config.js
文件不变,不用 将环境变量替换为它们的实际值。然后,创建优化的生产版本:
npm ci # if not already installed
npm run build
如果使用默认的webpack配置,app.config.js
的内容会被打包到build/static/js/main.????????.chunk.js
中。环境变量的值可以是 envsubst,使用 bash 这样的脚本:
main_chunk=$(ls build/static/js/main.*.js)
envsubst <$main_chunk >./main_chunk_temp
cp ./main_chunk_temp $main_chunk
rm ./main_chunk_temp
注:上例中envsubst在运行时读取环境中设置的实际变量,字面上替换了${ENV_VAR_1}
和${ENV_VAR_2}
和他们在一起。所以,你只能运行这一次,因为块正在被覆盖。
我有一个 React 应用程序,使用 create-react-app
创建,然后我使用以下命令构建应用程序:npm run build
它在构建后使用 serve
到 运行 应用程序,如果我们通过 运行ning ENV=production npm run start
使用开发代码启动应用程序它可以读取 process.env.ENV
变量,因为我将这个插件添加到 webpack 开发配置中
new webpack.DefinePlugin({
'process.env':{
'ENV': JSON.stringify(process.env.ENV),
}
}),
我也将上面的脚本添加到webpack prod config中,但是如果我在构建后尝试这个命令ENV=prod serve -s build
,它无法读取环境变量
如何解决这个问题?
无法读取ENV
var 的原因是:
(1) 在 开发 模式下 webpack
监视您的文件并动态捆绑您的应用程序。它还会读取(因为 DefinePlugin
)您的 process.env.ENV
并将其添加为全局变量。所以它基本上是从 process.env
到你的 JS 应用程序的管道变量。
(2) 在您 构建 您的应用程序(使用 webpack
)之后,所有内容都已捆绑到一个或多个文件中。当您 运行 serve
时,您只需启动一个为 static 构建文件提供服务的 HTTP 服务器。因此无法将 ENV
通过管道传输到您的应用程序。
基本上 DefinePlugin
所做的就是向捆绑包中添加一个 var
。例如
new webpack.DefinePlugin({
'token': '12356234ga5q3aesd'
})
将添加类似这样的一行:
var token = '12356234ga5q3aesd';
因为 JS 文件是 static 没有办法改变这个变量 after 你 build/bundled 它与webpack
。基本上,当您执行 npm run build
时,您正在创建已编译的二进制文件/.dll
/.jar
/... 文件并且不能再通过插件影响其内容。
您可以将 .env
文件添加到项目的根目录并在那里定义环境变量。这将是您的默认(生产)环境变量定义。但是你可以有一个名为 .env.local
的本地文件来覆盖默认值。
定义环境变量时,请确保它们以 REACT_APP_
开头,这样您的环境变量定义将如下所示:
REACT_APP_SERVER_URL=https://my-awesome-app.herokuapp.com
此外,将其添加到 .gitignore 中,这样您就不会提交本地覆盖:
.env*.local
参考: Adding Development Environment Variables In .env (create-react-app)
来自create-react-app documentation:
Your project can consume variables declared in your environment as if they were declared locally in your JS files. By default you will have NODE_ENV defined for you, and any other environment variables starting with REACT_APP_.
您可以从代码中的 process.env 读取它们:
render() {
return (
<div>
<small>You are running this application in <b>{process.env.NODE_ENV}</b> mode.</small>
<form>
<input type="hidden" defaultValue={process.env.REACT_APP_NOT_SECRET_CODE} />
</form>
</div>
);
}
如果您在 app.config.js
中设置了所有环境变量,您可以在 main.????????.chunk.js
文件中构建 之后替换它们 。
示例 app.config.js
可能如下所示:
export default {
SOME_URL: "https://${ENV_VAR_1}"
SOME_CONFIGURATION: "${ENV_VAR_2}",
}
保持 app.config.js
文件不变,不用 将环境变量替换为它们的实际值。然后,创建优化的生产版本:
npm ci # if not already installed
npm run build
如果使用默认的webpack配置,app.config.js
的内容会被打包到build/static/js/main.????????.chunk.js
中。环境变量的值可以是 envsubst,使用 bash 这样的脚本:
main_chunk=$(ls build/static/js/main.*.js)
envsubst <$main_chunk >./main_chunk_temp
cp ./main_chunk_temp $main_chunk
rm ./main_chunk_temp
注:上例中envsubst在运行时读取环境中设置的实际变量,字面上替换了${ENV_VAR_1}
和${ENV_VAR_2}
和他们在一起。所以,你只能运行这一次,因为块正在被覆盖。