The Complete DevOps Guide with React, Firebase, and GitlabCI, Part 2
Configuring Environments
Git Workflow
It’s time to dig deep into learning about different developer environments. The easiest and most commonly adopted technique by most people is to work on the master branch in Git or create separate feature branches for different features. However, doing a bit differently and adopting the different environments and branches that we’ll see shortly is so damn handy and trouble-saving in the long run, and leads to a cleaner working environment.
development
— This is the branch where you should be making changes in your code. You can create multiplefeature
branches off of this branch and then merge them with the development branch when you’re done.staging
— Once the features are implemented and considered fairly stable, they get merged into thestaging
branch and then automatically deployed to the Staging environment. This is when quality assurance kicks in: testers go to staging servers and verify that the code works as intended.production
— When all the testing is done, and it is ensured that there are no bugs, then the code can be deployed to production. This is what the end users will be seeing.master
—This branch will have the latest stable version of the code. Nothing is ever committed to themaster
branch directly, but rather just merged from the production branch.
When you start off, you have one branch by default — the master
branch.
We first need to make 3 branches off of this branch:
$ git branch development
$ git branch staging
$ git branch production
Creating Dev, Staging, and Prod Projects in Firebase
So, we’ve seen why we need different branches. Now, go ahead and create a project in Firebase for Development, Staging, and Production (Skip this step if you already have 3 projects or create 2 more if you already have one).
Note down the web configuration somewhere safe for now. I’ll tell you exactly where to place them in your React app in a moment. Remember in the previous part where I told you not to choose a default project for the current directory as we’ll be having multiple projects? This is why.
So how do I host in these different projects?
For these, I’d recommend creating project aliases.
In your command line, running firebase list
will list all the firebase (or Google Cloud) projects that you have.
You can configure aliases for the projects as follows (An alias is an alternative name for the project):
$ firebase use --add
Use the arrow keys to select a project. Type in an alias that you want. For example, I have myapp-staging
project which I want to call staging
. So I’ll type in the alias as staging
. Do this for development and production projects too (call them dev
or development
, and prod
or production
respectively).
P.S.: You can have another project for running unit tests.
Since each project has its own configuration keys, we need a mechanism to determine which key to use when a particular project has to be deployed.
Environment Variables in React
There is an environment variable in node, process.env.NODE_ENV
which is immutable. This variable will let you know the current environment.
process.env.NODE_ENV
takes different values at different times:
npm start
— developmentnpm test
— testnpm build
— production
In the root directory (this is not the src
directory), create files named .env.development
and .env.production
.
All the custom environment variables in React must be prepended with REACT_APP_
. We can add our corresponding project keys as follows in our .env.development
and .env.production
files:
REACT_APP_FIREBASE_API_KEY=<your-api-key>
REACT_APP_FIREBASE_AUTH_DOMAIN=<your-firebase-auth-domain>
REACT_APP_FIREBASE_DATABASE_URL=<your-firebase-db-url>
REACT_APP_FIREBASE_PROJECT_ID=<your-firebase-proj-id>
REACT_APP_FIREBASE_STORAGE_BUCKET=<your-fb-storage-bucket>
REACT_APP_FIREBASE_MESSAGING_SENDER_ID=<your-fb-message-sender-id>
Note that we don't need quotes for the values.
How do I use these values?
Thanks to process.env
which gives us access to the environment variables.
You can modify your firebase configuration object in the firebase.js
file to use the environment variables, rather than the hardcoded keys:
let config = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
};
So this is how our modified firebase.js
file (in the src/firebase
directory) will look like:
Hold on, so where does staging come in here?
This is the part that I had a lot of trouble figuring out. Yeah it’s kinda messy and it’s better to override them using an npm package called env-cmd
.
You can either install it globally or as a dev dependency. I’m going ahead with the latter.
$ npm install --save-dev env-cmd
In the root directory of your project, create a new file named .env-cmdrc
and enter your project keys as follows.
We need to build the staging and production projects to use their corresponding environment variables. (We needn’t worry about development, because by default, npm start
will use the development environment variable).
We add the following two lines in the package.json
file:
"build:staging": "env-cmd -e staging react-scripts build", "build:production": "env-cmd -e production react-scripts build",
The -e
flag stands for ‘execute’. So we’re telling env-cmd to use the staging
key from the .env-cmdrc
file if we run npm run build:staging
in the terminal and production
key if we run npm run build:production
.
Set up deploy targets
For deploying to the corresponding sites, you can avoid the hassle by setting up the deploy targets.
$ firebase target:apply hosting staging <staging-proj-name>
$ firebase target:apply hosting prod <production-proj-name>
Configure your firebase.json file to use deploy targets
We need to build the staging project into the build/staging
directory and the production project to the build/production
directory.
Deploy
Now you can deploy them using: (Note the absence of the--project
flag)
$ firebase deploy --only hosting:staging staging
$ firebase deploy --only hosting:prod production
…to be continued.