Let’s say you’re developing a system that should provide different applications to different user base, and you want to re-use the code that you have already implemented in those applications, you basically have these 2 choices:
- Create and manage multiple codebases for sharing components and functions between applications and those applications as well. It works but it might be too much if most of the shared components are developed specifically to these applications, and would not be used again in another project, not to mention the time to manage, and and deployment preparation for all these codebase.
- Restructuring the old codebase that host all of those applications and the shared components. Its downside is for bigger project, this codebase will balloon up, and become harder to manage, but it’s quick and easy.
In this post I’m not discussing about the pros and cons of these solutions, I will only go in detail on the 2nd choice, hence the title.
In real life, we employ the 3rd option, a mix of the 2 for our development process. While this post use yarn
as dependency manager, npm
would also work similarly.
Restructuring create-react-app folder
We have to start somewhere. For creating a simple react app, you will start with create-react-app
library. And for firebase, we use firebase init
command.
The default folder structure after running these commands:
...
|--package.json
|--firebase.json
|--src
|--|--index.tsx
|--|--App.tsx
|--|--components
...
Where index.tsx
and App.tsx
is the entry for our single app. Now we want to re-structure it to support multiple apps, in this case, we have 2 different applications for customer
and manager
, and we put them in the apps
folder:
...
|--package.json
|--firebase.json
|--src
|--|--apps
|--|--|--manager
|--|--|--|--index.tsx
|--|--|--|--App.tsx
|--|--|--customer
|--|--|--|--index.tsx
|--|--|--|--App.tsx
|--|--index.ts
|--|--components
...
Updated src/index.ts
:
Then we will have the similar entry for each of the application inside apps
:
And now we can start to implement our 2 apps within the same codebase, using shared components
and other utilities
.
Switching between applications
So far so good, but how would you develop and deploy the 2 applications independently?
You can see that inside index.ts
, we’re using process.env.REACT_APP_TARGET
for switching between 2 applications. You guessed it, we just need to provide the correct environment variable and we can target whichever application we like.
Updated package.json
. Please note that this is an ejected react codebase, you can use the same method for not-yet-ejected codebase.
During development, instead of using yarn start
we can use yarn start:customer
and yarn start:manager
for the respective application. The same would be applied for yarn build
and yarn deploy
Building and Firebase hosting deployment
First we need to update create-react-app
’s build command, by default this command build the app into dist
. We want 2 apps to be built now, and we don’t want them to use the same folder, because, we might deploy wrong application or what not. Luckily this build command supports BUILD_PATH
environment variable, so we can specify 2 different folder for the 2 applications ./out/customer
and ./out/manager
. Don’t forget to add out/*
to .gitignore
though.
With the build command finally done, the last step is to deploy it to Firebase hosting.
Updated firebase.json
:
The 3 line that we want to update are below
...
"target": "customer",
"public": "out/customer",
"predeploy": [
"yarn build:customer"
]
With "target": "customer"
we can specify to deploy only customer app by using
firebase deploy --only hosting:customer
And public
is the output folder previously mentioned. Lastly predeploy
will specify the commands that we want to run prior to deploy, in this case, we want to build the corresponding app.
And that’s it! Code and deploy away.