为React单页应用提供Runtime运行时环境变量

使用create-react-app创建的单页应用(SPA)是在build时注入环境变量的。一旦build成静态文件便不能动态提供环境变量了。
比如build一个单页应用的docker image,可以在build时提供环境变量。但是已经build完成,使用docker run运行的时候不能再传递环境变量。
本文主要解决在运行时提供环境变量的问题。
原理:通过一段shell脚本将指定将env转换为config.js文件,该文件和build好的static文件serve在同一目录下,在应用中引用config.js文件,通过window._env获取环境变量。shell脚本通过docker image的entrypoint执行。服务使用go构建的一个简单服务器,比nginx轻量很多。

  1. 将如下env.sh文件拷问到项目目录下,在entrypoint(docker run)时执行,作用是将环境变量转出config.js
#!/bin/sh
if [ $CONFIG_VARS ]; then
  # clear
  echo -n > ${CONFIG_FILE_PATH}/config.js

  SPLIT=$(echo $CONFIG_VARS | tr "," "\n")
  echo "window._env = {" >> ${CONFIG_FILE_PATH}/config.js

  for VAR in ${SPLIT}; do
      VALUE=$(printenv ${VAR})
      echo "  ${VAR}: \"${VALUE}\"," >> ${CONFIG_FILE_PATH}/config.js
  done

  echo "}" >> ${CONFIG_FILE_PATH}/config.js
fi

# disable broswer cache
sed -i "s/config.js?v=[0-9]*/config.js?v=$(date +'%s')/g" /srv/http/index.html
# for macOS
# sed -i "" "s/config.js?v=[0-9]*/config.js?v=$(date +'%s')/g" /srv/http/index.html

# exec CMD
exec "$@"

例如

# 传入
CONFIG_VARS=ABC,XYZ
ABC=helloabc
XYZ=HELLOXYZ

# 转换为
window._env = {
  ABC: "helloabc",
  XYZ: "HELLOXYZ",
}
  1. 编写Dockerfile,使用goStatic当做静态文件服务器(比nginx轻量)。build完成只有几MB.
FROM node:11 AS builder
COPY . /app
WORKDIR /app
RUN yarn install
RUN yarn run build

FROM wlchn/gostatic:latest
ENV CONFIG_FILE_PATH /srv/http
COPY --from=builder /app/build /srv/http
COPY ./env.sh /env.sh
# Ensure convert envs to window._env
ENTRYPOINT ["sh", "/env.sh"]
# start server. listen on 8043(in container) by default.
CMD ["/goStatic"]
  1. 在项目中引用config.js
<script type="text/javascript" src="/config.js?v="></script>
  1. 使用环境变量,通过window._env获取
let _env = process.env;
// check if there is env exits in local, otherwise using window._env
if (_env.ENV_ABC) {
  _env = window._env;
}
// so you can use env like _env.ENV_ABC
  1. 转换示例
# pass envs like:
CONFIG_VARS=ABC,XYZ
ABC=helloabc
XYZ=HELLOXYZ

# you coud get config.js
window._env = {
  ABC: "helloabc",
  XYZ: "HELLOXYZ",
}

# in your app, you can use like
console.log(_env.ABC)
console.log(_env.XYZ)

GitHub

reference

推荐阅读更多精彩内容

  • SPA 没有运行时环境变量的痛点 目前我的绝大部分的项目都是一个前后端分离的方式开发的。其中前端基本都是用 cre...
    eisenxu阅读 440评论 0 1
  • js的变量命名规范:1.变量可以由任意大小的大小写字母,下划线,美元符号($)组成,但不能以数字开头,不能是jav...
    挂树上的骷髅怪阅读 85评论 0 0
  • 记忆停留在那年的午后。 皮旧沙发, 昏黄书架, 还有不会说话的布娃娃。 橱窗里飘来饭菜的香味, 爸爸看着报纸喝着茶...
    大嘴巴蜗牛阅读 80评论 2 1
  • 假期开始了,但是对写作的人来说,真正的挑战也才刚刚开始。 工作日反正也累了一天,晚上坚持写作也就是熬一熬的事情,可...
    苏秦知识创客阅读 58评论 0 1
  • 金秋十月,丹桂飘香,金风送爽,又是一年一度吃螃蟹的日子了,最有名的就要属我们家乡的阳澄湖大闸蟹了。 ...
    lclars阅读 131评论 0 0