Ways to load env variables for your script
Several years ago when I decided to write an article, I got this inject-env-variables-with-no-tears. At that time, I know nothing about makefile and shell script(almost), the only idea in my brain is just Nodejs. Years later, I got new and better solutions.
Firstly, let’s talk about what env variables act in software like a project written in Nodejs. Let’s say it’s an app that is bootstrapped by create-react-app. By default, this app will be served on the root path of a host, like medium.com. If it’s supposed to be served on a sub-path like /apps/my-app, you have to tell the build script what the exact path it is. The way it receives the path value is through the env variable.
The reason why it prefers the env variable not an inline argument is env variable is the most unified. Different operations may have different ways in commands, data format, etc. But they all have basic support for the env variable. That means the great cross-platform. That’s it.
Now, let talk about how to inject env variables into the project.
Shell Script
For example, you are going to set an env variable for the app.
PUBLIC_PATH=/apps/my-app
Let’s create a file named build.sh
#!/bin/bash
export PUBLIC_PATH=/apps/my-app
/node_modules/.bin/react-scripts build
If there are multiple stacks for deployment, just created more build-[stack-name].sh, tell the build manager(like Jenkins) that executes the correct shell script.
Makefile
Makefile is like shell script plus tasks.
PATH := ./node_modules/.bin:${PATH}.PHONY: start buildstart:
react-scripts startbuild:
export PUBLIC_PATH=/apps/my-app; \
react-scripts build
The start and build are tasks (called target by Makefile) defined by the Makefile. In the build target, the first line is to set the PUBLIC_PATH. Please be noticed it ends with a semicolon followed by a backslash. This is because each line in a target is executed in a standalone shell by default, which means the env variable set in the first line is not readable by the second line. The sign that a semicolon followed by a backslash asks Makefile that the next line executes in the current shell, which means they share the same context. In this way, the second line receives the env variable.
There is another way to declare that the lines in the target share the same shell, one-shell. It is not available in some old implementations, such as mine. So I still use the old mark. If you have a new Makefile, try yourself if one-shell works.
Why not Nodejs
The reason why I give up using Nodejs here is the native approach(shell or Makefile) is more powerful. For example, if it’s required to load env from files for a different purpose, how to make it come true if the original build tool like react-scripts did not provide similar functions. Fork a copy of it and modify the code, come on, believe me, you will never want to do this. The best idea is to create a shell script to do things about env variables before Nodejs. If you know Makefile then you can mix the usage with Makefile and shell script, that is a more big world than tools in Nodejs like dot-env could do.