Developing and deploying create-react-app to multiple Firebase environments
Tags: typescript, react, firebase
Published: 2019-09-12 05:19:49


# Introduction

create-react-app makes it easy to quickly get started with React. Firebase makes it easy to quickly get started with web deployments. This article will show how to configure, build and deploy a React app to multiple environments in Firebase. Plus we will get it all working well together with Typescript.

# Getting started

First we need to install some tools. These instruction assume a unix terminal prompt. For windows, install WSL (Windows Subsystem for Linux) from the Windows app store

## Install NodeJS

If you already have NodeJS installed, you can skip ahead. If not head on over to [nodejs.org](https://nodejs.org) and download an installer or use [nvm](https://github.com/nvm-sh/nvm) to be able to future-proof your NodeJS installation.

Using nvm:

```
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
```

Restart your terminal or follow the instructions on the terminal. Then install node:

```
nvm install 12 
```

## Run create-react-app

If you already have an application then you can skip these and go to installing Firebase.

To make some steps easier let's pick a name for our new application which we will save as an environment variable to reuse. 

```
export REACT_APP=hello-firebase; # replace with your application's name
```

Use npx and create-react-app to boilerplate a new react application. I recommend using Typescript to enable type-checking

```
npx create-react-app ${REACT_APP} --typescript
```

Wait a little bit while create-react-app gets ready. When finished enter the application directory:

```
cd ${REACT_APP}
```

## Install firebase-tools

In order to work with firebase you will need the `firebase` command line tool. The easiest way to get it is to install globally with npm:

```
npm i -g firebase-tools
```

# Create your firebase application

Head on over to [console.firebase.google.com](https://console.firebase.google.com/) and activate Firebase for your Google account. If you select the _Spark_ plan then for moderately sized applications there is no cost.

Once you have activated firebase, go back to the terminal and login:

```
firebase login
```

You will be presented with a login prompt in your browser. Click _Allow_ to complete the login

![Firebase login modal](https://thepracticaldev.s3.amazonaws.com/i/23jfjzxj22eijoz00jpt.png)

## Firebase environments

If you are just playing around then you can skip this step. When you get serious about developing a real application you will want to create multiple Firebase environments. To start let's create two firebase environments-- a development and production environment. The development environment will be the default environment that can be used for trying out new features and the production environment will the the "stable" customer facing environment.

```
firebase projects:create ${REACT_APP}-production
firebase projects:create ${REACT_APP}-development
```

Firebase environment names must be unique, so if the name you want is not available, try a different name.

## Initialize Firebase

Now we are ready to initialize firebase inside our create-react-app. Firebase has an interactive application for that:

```
firebase init
```

For now let's just pick _Hosting_ because that is all I am going to be covering. You can always re-run this command later to add features

![Firebase init component selection screen](https://thepracticaldev.s3.amazonaws.com/i/l9l79j2g2dorjwx530q5.png)

We'll use an existing project that we created earlier. If using multiple environments I recommend picking your development environment as the default.

![Firebase select project interactive screen](https://thepracticaldev.s3.amazonaws.com/i/c7spubd6xlnlb89oad2p.png)

Change the hosting location to _build_. Answer _yes_ to if the application is a SPA (single page application). 

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/vug8fazl1fr1wbugqe8x.png)

If you going to deploy to multiple environments, then add your secondary environment now:

```
firebase use --alias production ${REACT-APP}-production; # or whatever name you ended up picking
firebase use default; # switch back to development
```

## Firebase implicit initialization scripts

_Implicit initialization_ is a nifty way to initialize Firebase without config files. When supporting multiple configurations from a single project it is the only easy way to support multiple configurations. We really do not want to have the following code because it is not a good idea to leak non-production environment details in a production application:

```
if (process.env.REACT_APP_DEPLOY_ENV='production') {
  firebase.initializeApp(productionConfig)
} else {
  firebase.initializeApp(developmentConfig) 
}
```

_Implicit initialization_ works by loading Firebase javascript from a special `/__/` folder. We we deploy our app to Firebase this route will exist for us but locally we will need to do a little more work to set it up.

In your favorite code editor open up the _build/index.html_ that was created by `firebase init`. At the top of the body tag you will see a series of Firebase related script tags. Select and copy these tags:

![Firebase script config tags selected](https://thepracticaldev.s3.amazonaws.com/i/dcqvw1asw0hyej8968lv.png)

Paste them in your _public/index.html_ file at the top of the body tag. Feel free to remove features you are not using. 

## Firebase serve for local development

firebase-tools comes with a server that supports the implicit initialization, but first we need to set up a few things in create-react-app.

First let's install `run-p` which is a handy tool for running multiple npm scripts in parallel. In addition we will need to configure an http proxy.

```
npm i -D npm-run-all http-proxy-middleware
```

In your _package.json_ change the `start` script from `react-scripts start` to:

```
    "start": "run-p --race dev:firebase dev:react",
    "dev:firebase": "firebase serve -p 4000",
    "dev:react": "react-scripts start",
```

Now create _src/setupProxy.js_ file and type:


```
const proxy = require('http-proxy-middleware')

module.exports = function(app) {
  app.use(
    '/__',
    proxy({
      target: 'http://localhost:4000'
    })
  )
}

```

Now we are ready for local development. In your terminal run:

```
npm start
```

If all is well you should see:

![A running react app](https://thepracticaldev.s3.amazonaws.com/i/cvoxiht95eo09h187rxr.png)

Checking developer tools and terminal console you should see that Firebase javascript is loading and no errors are present. Hot reloading works so you can make changes to code and they will be reflected immediately.

## Deploying Firebase Hosting

We are almost ready to deploy our react app to Firebase hosting. First we need to add a line to _firebase.json_ to automatically build our application before deploying. Otherwise you will forget to do it. Add the following line to the `hosting` section:

```
"predeploy": ["npm --prefix \"$RESOURCE_DIR/..\" run build"]
```

![Firebase config](https://thepracticaldev.s3.amazonaws.com/i/k9943qsfpuafc6bxgn5p.png)

Now we can deploy:

```
firebase deploy
```

React will build and a link will be provided in the console. You should be able to click on that link your React application will load!

## Switching Environments

When you are ready to deploy to production all it takes is an environment switch. 

```
firebase use production; # switches all future firebase commands to production
firebase deploy
```

Or use the `-P` flag

```
firebase -P ${REACT_APP}-production deploy; # Does not switch default environment but still deploys to production
```

## Typescript typings

If you start using Firebase in your Typescript application you need to let Typescript know about this global `firebase` variable that you know have access to. First install `firebase` not to import but simply to get access to the types contained within:

```
npm i -D firebase
```

Now create a _src/firebase.d.ts_ file and copy the following:

```
import firebase from 'firebase'

declare global {
  export const firebase = firebase
}

```

Now you have full typescripts bindings available.

# Conclusion

I hope this guide makes it easy to use create-react-app together with Firebase for modern web application development combined with free application hosting.