Nginx 可通过 map 指令根据域名动态映射环境变量,并用 sub_filter 在响应 HTML 中注入 window.__ENV__,实现 React 应用运行时多环境配置。

用 Nginx 托管 React 应用时,若需通过不同域名(如 dev.example.com、staging.example.com、prod.example.com)自动加载对应环境的配置(比如 API 地址、功能开关),不建议在构建时硬编码环境变量——而应让 Nginx 在请求阶段动态注入。Nginx 的 map 指令正是实现该目标轻量又可靠的方式。
用 map 提取并映射域名到环境标识
map 是 Nginx 的变量映射模块,运行在请求处理早期,开销极小,适合做域名分类。它不能写在 server 块内,必须置于 http 块顶层:
http {
# 定义 $env 变量:根据 host 自动匹配环境
map $host $env {
default "production";
~^dev\. "development";
~^staging\. "staging";
~^demo\. "demo";
}
<pre class='brush:php;toolbar:false;'># 可选:进一步映射为 API 基础地址
map $env $api_base {
"development" "https://api.dev.example.com";
"staging" "https://api.staging.example.com";
"demo" "https://api.demo.example.com";
"production" "https://api.example.com";
}}
注意正则匹配需加 ~^ 表示“以…开头”,避免误匹配子域名(如 mydev.example.com 不会命中 dev\.);default 保证兜底安全。
在 HTML 中注入环境变量(无需构建多版本)
React 应用启动前需读取环境信息。可在 Nginx 的 location / 块中,利用 sub_filter 动态替换 HTML 模板中的占位符:
server {
listen 80;
server_name ~^(?<domain>.+)\.example\.com$;
<pre class='brush:php;toolbar:false;'>root /var/www/react-app;
index index.html;
location / {
try_files $uri $uri/ /index.html;
# 注入环境变量到 index.html
sub_filter_once off;
sub_filter '<head>' '<head><script>window.__ENV__ = {env: "$env", apiBase: "$api_base"};</script>';
sub_filter_types text/html;
}}
这样每个域名访问时,返回的 index.html 都会包含对应环境的全局变量,React 启动时即可直接读取:console.log(window.__ENV__.env); // "staging"
配合 create-react-app 的运行时环境方案
若使用 CRA,默认不支持运行时变量。需两步适配:
- 在
public/index.html中预留注入点,例如:<script id="env-inject"></script> - 修改 Nginx 的
sub_filter,精准替换该 script 标签:sub_filter '<script id="env-inject"></script>' '<script>window.__ENV__ = {env: "$env", apiBase: "$api_base"};</script>'; - 在
src/index.js最顶部添加判断逻辑,确保变量存在再渲染:if (typeof window.__ENV__ === 'undefined') throw new Error('Environment not injected');
验证与调试技巧
部署后快速确认是否生效:
- 直接访问
curl -s http://dev.example.com | grep __ENV__,检查输出是否含正确值 - 浏览器开发者工具中执行
window.__ENV__,验证对象内容 - 在 Nginx 日志中临时开启
log_format记录$env,排查匹配逻辑:log_format debug '$remote_addr — $host → env:$env';
不复杂但容易忽略:确保 sub_filter 开启且作用于正确 MIME 类型,同时禁用浏览器缓存(开发期加 add_header Cache-Control "no-cache";),避免旧 HTML 覆盖新注入。


















