Docker/K8s配置的API_URL在React应用中返回undefined的问题排查
问题分析与解决方案
你的问题核心在于构建时注入变量和运行时环境变量的时机不匹配:
- Webpack的
DefinePlugin是在React应用构建阶段把process.env.API_URL硬编码到代码里,但此时这个变量根本不存在(构建过程中没有传入API_URL),所以最终代码里的process.env.API_URL被替换成了undefined。 - 而K8s设置的
API_URL是容器运行阶段的环境变量,无法直接被已经构建完成的静态React代码读取。
解决方法(两种常用方案)
方案一:通过Nginx启动脚本替换静态文件占位符
思路是在React代码里用占位符代替变量,容器启动时用脚本把占位符替换成K8s传入的环境变量值。
修改React代码
把代码里的process.env.API_URL替换成自定义占位符,比如__REACT_APP_API_URL__:// React组件中使用示例 const apiUrl = '__REACT_APP_API_URL__'; fetch(`${apiUrl}/some-endpoint`)修改Dockerfile
添加启动脚本,在Nginx启动前替换静态文件里的占位符:FROM nginx:latest ENV API_URL $API_URL COPY deployment-configs/nginx.conf /etc/nginx/conf.d/default.conf WORKDIR /usr/share/nginx/html RUN rm -rf ./* COPY packages/Project/Container/dist . # 替换占位符后启动nginx CMD ["/bin/sh", "-c", "sed -i 's|__REACT_APP_API_URL__|'"$API_URL"'|g' /usr/share/nginx/html/*.js && nginx -g 'daemon off;'"]K8s清单保持不变
你当前的K8s环境变量配置已经正确,会把API_URL传入容器,启动脚本会自动替换静态文件中的占位符。
方案二:通过index.html注入全局变量
思路是在Nginx提供的index.html中,通过脚本标签注入环境变量,React代码直接读取全局变量。
修改React代码
直接读取全局变量window.API_URL:// React组件中使用示例 const apiUrl = window.API_URL; fetch(`${apiUrl}/some-endpoint`)修改项目的index.html
在<head>中添加占位脚本:<script> window.API_URL = '%API_URL%'; </script>修改Dockerfile
在启动时替换index.html中的占位符:FROM nginx:latest ENV API_URL $API_URL COPY deployment-configs/nginx.conf /etc/nginx/conf.d/default.conf WORKDIR /usr/share/nginx/html RUN rm -rf ./* COPY packages/Project/Container/dist . CMD ["/bin/sh", "-c", "sed -i 's|%API_URL%|'"$API_URL"'|g' /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"]
额外注意点
- 原Dockerfile中
ENV API_URL $API_URL是把构建时的API_URL传递到容器,但构建时这个变量不存在,所以容器启动前API_URL是空的,但K8s的env配置会覆盖这个值,运行时容器内的API_URL是正确的,无需修改K8s配置。 - 如果静态文件有多个js文件,方案一中的sed命令可以调整为匹配所有相关文件,比如
*.js或者更精确的文件名。
内容的提问来源于stack exchange,提问作者Nikhil
相关产品推荐
相关产品推荐

