Saurabh
3 supporters
React JS— Architecture + Features + Fold ...

React JS— Architecture + Features + Folder structure + Design Pattern

May 31, 2021

Git repo: SAURABH SHAH / ReactJS myapp · GitLab (wip)
Code-sandbox live (playgroud embeded at bottom)
If you like the story, buy me a coffee!

image gitlab.com

Where all the paths are defined in CONSTANTS and the same are used in Link tags for navigation purposes. Refrain from hardcoding the paths all over your application.
Render this RouterConfig in your App.js between BrowserRouter as shown below:

image

Nested routing is the next step required for a corporate standard implementation.

Highly recommend to decide on routing hierarchy based in the initial phase for easy of dev and maintenance.

Refer story: React JS nested routing

Step-3: Material UI & Roboto font

(ref: https://material-ui.com/)

Material UI is a set of react js components that follow Material design pattern. It also enables the capability to use vector icons and various pre-build customizable components that come bundled with the Material UI module.

Above all, it provides a capability to define the style guide for overall application via its Theme provider module.

$ npm install @material-ui/core
$ npm install @material-ui/icons
$ npm install fontsource-roboto
(Very important: “install Roboto font, don’t just add a CDN link to avoid flickering issue.”)

Add reference to font in “/src/App.js”

import “fontsource-roboto”;

You can start using Material UI components in your app. Although I strongly recommend you to learn more about Material UI Customization and implement the ThemeProvider with base theme and wrap your app within ThemeProvider in “/src/App.js”.

Also, learn about customization and adding more styles using hooks or HOC. quick ref: https://material-ui.com/styles/basics/

Full React App with Router and MUI custom theme as a boilerplate available at GitLab:
Files · Step1–5-Router+MUI · SAURABH SHAH / ReactJS myapp · GitLab

Step-4: Backend Connectivity

We’ll cover 2 types of connectivity here. One is language/technology agnostic and very widely used and universally accepted data connectivity via “REST APIs”. Another is a technology specific, eg. “FIREBASE” connectivity using its Web-SDK.

AXIOS for REST API:

Axios is a simple data fetching module for REST API connectivity using all the required methods like GET, POST, PUT, DELETE, etc. Install axios in project using below command and we are ready to go.

$ npm install axios

Git repo with all coding so far.

Files · Step-6-axios · SAURABH SHAH / ReactJS myapp · GitLab
This example app has toggle option between “Remote API ”and corresponding “Local data” (toggle between via “/src/services/CONSTANTS.js” — good for dev)

A good reference for Axios with react js:
https://www.digitalocean.com/community/tutorials/react-axios-react

For further leveraging more hooks and ease of development, refer this library.
https://www.npmjs.com/package/use-axios-react

FIREBASE (Web-SDK)

Ref: https://firebase.google.com/docs/web/setup

This step is completely optional. If you do not want to have any backend REST APIs, services, endpoints, etc.. Firebase is one of the very good options. Firestore is a document database you can leverage for your DB requirements and firebase web-sdk provides you capability to connect, query and perform CRUD operations without the need of any middle-ware services like endpoints or API servers.

Setup for firebase web-sdk is very simple. The reference link is official documentation for the same. It is an easy to follow guide.
In this app we are using Firebase’s Firestore document database.

$ npm install firebase

In our app, we have a “/src/services” directory dedicated for backend calls and data connectivity. Thus, all our firebase configurations reside there. Biggest advantage of this architectural design step is decoupling of data connectivity from the business logic and presentation layer of the app. Thus, if we want to change the connectivity or scale the database to some other source, it is only here that we need to make changes. Below is the snapshot of our “/src/services/firebase.js”

image

Okay, I agree, this “process.env.REACTAPP****” is something alien. Let me cover this in the upcoming part “Multi-environment setup”.
Although, it is exactly the same firebaseConfig that you get from your firebase project. Only difference is, we are storing and fetching the values from environment variables.

BONUS: Firebase Auth

If you are using the firebase authentication module, you can also leverage the firebaseUI module, which provides authentication UI and logic out-of-the-box for us. (https://firebase.google.com/docs/auth/web/firebaseui)


Step-5: Redux & Thunk

(ref: https://redux.js.org/ & https://react-redux.js.org/)

Redux is used for the provision of a central or app level state/store. All the data that needs to be shared across features, modules or react-component trees, can be added to the redux store.

Thunk is the middleware that works hand-in-hand with redux for handling the side-effects like fetching data from database, REST APIs, application processing delays, etc. It is promise based.

$ npm install redux react-redux
$ npm install redux-thunk

Once installed, we have to create all the required reducers and corresponding actions and action-creators. All the reducers will then be combined in single app level state and as defined in redux store.

Full React App with Redux in a boilerplate at GitLab:
Files · Redux+Thunk · SAURABH SHAH / ReactJS myapp · GitLab

If you are learning react-redux, try redux-toolkit.

BONUS: Redux Dev tools configuration: (not required with redux toolkit)

We need to configure the redux dev tools while defining our store in “/src/redux/store.js” like:

image store.js: configure Redux dev tools for ease of debugging redux state.

Here process.env.NODE_ENV is by default available with create-react-app. Simply copy the same code.

Finally, our App.js has a return method somewhat like below: (includes MUI, Redux & Router)

image

Redux Toolkit:

ref: Quick Start | Redux Toolkit (redux-toolkit.js.org)

This is an Optional (EXTRA) package that can be used to simplify the implementation of redux in our react application. It is fairly new and one of the best features is “createSlice”.
In simple words, fundamentals are same, react and redux are same, only the way actions, store, reducers, selectors were defined is different (better) with “@reduxjs/toolkit” package.

$ npm install @reduxjs/toolkit

Usage of redux-toolkit is totally optional and personal choice. Remember few things:
* An extra package required to be installed.
* No added feature.
* Only simplicity in coding actions & reducers.

Redux vs Context API

Honestly, this is still debatable. Context being a powerful feature, available OOTB with react is definitely the best choice, but when?

I have used both together as well:
Redux for the shared state for big application across features.
Context API for the props drilling within the feature.

Personally, I still don’t consider Context API as a complete replacement of Redux.


Step-6: Multi-Environment setup (environment variables)

Ref: https://www.npmjs.com/package/env-cmd

We all have this requirement to create builds pointing to a specific data environment. Problem here is how to configure a specific environment when required. Changing the code every time is not the right way. Using environment variables is the perfect and universally accepted solution for this. Env-cmd is a module that adds this capability to any react js application.

$ npm install env-cmd

Once installed, simply define all the dynamic configuration parameters in the corresponding .env files. For example, for 3 envs like “development”, “staging” & “production”, we can have corresponding .env files “.env.development”, “.env.staging” & “.env.production”.

Remember, the basic rule is every environment variable we define in these files has to start with the “REACT_APP” prefix. 
Also, we need to make changes to our build script to adapt the required data environment while running the application. Same applies for the scripts to create environment specific deployable packages. Refer official npm module reference for all the details. So the “npm start” command in package json needs to be changed from “react-scripts start” to “env-cmd -e development react-scripts start”.

An intuitive implementation example: https://medium.com/better-programming/managing-environments-for-provisional-builds-with-react-app-1fb411e3597

This is a totally optional step and based on personal choice or preference. Env-cmd module gives us different ways to define environments. Most common is an individual file for each environment. I personally prefer to have all configurations in one file like a .rc or .json file.
So our single “/.env-cmdrc.json” file resides at the root of our application and looks like:

image .env-cmdrc.json

We added a dropConsole.js utility in the beginning. We can leverage .env for deciding that as well.

Step-7: Internationalization (I18n)

(ref: https://react.i18next.com/getting-started & https://www.i18next.com/overview/getting-started)

react-i18next is a library to enable multilingual support to our reactjs app. It comes handy with various features like change app rendering language, fallback language for missing translations, translation configurations, capability to add default language detection middlewares, etc.

We’ll also use a browser-languagedetector to detect the default language of the end user.

Use following command to add internationalisation and corresponding modules in the app:

$ npm install react-i18next i18next
$ npm install i18next-browser-languagedetector

Please refer to official documentation for applying translations, changing user language, etc.

We have a dedicated directory in our architecture for internationalization. A snapshot of how our “/src/i18n/index.js” may look is as below:

image

Further you can export getter setter for selected language and use it from app.

Step-8: Unit testing framework

(ref: https://jestjs.io/docs/en/tutorial-react)

Jest is default supported in react js applications for unit testing. This will enable us to perform unit testing and generating code coverage reports.
Jest gives below features out of the box:

  • Minimal configuration

  • Watches only changed files

  • Fast

  • Snapshot testing

  • Coverage out of box

In this app, we’re not emphasizing on testing framework. Although, for bigger apps, it is highly recommended to implement unit testing. It will save a lot of efforts while scaling the app in future.

Step-9: Deployment / Hosting

Hosting or deploying the webapp can be troublesome if the build or package is not created properly. A react application ships with a build script for outputting a production ready build in a “/build” directory. This build directory is the final independent package that can be deployed or hosted in any web hosting platform.

We can define various build and deploy scripts in our “/package.json” > ‘scripts’ object like below:

image npm scripts in package.json file

Here, “development”, “staging” & “production” are the 3 environments mapped with corresponding databases. Build and Deploy script is defined for each environment. All the react specific scripts start with “env-cmd -e environment” for leveraging environment variables via “emd-cmd” node module.

BONUS: Firebase Hosting

(ref: https://create-react-app.dev/docs/deployment/#firebase)

One of the simplest hosting platforms is the firebase hosting by google. It is literally like hosting your web project build/bundle in 5 minutes. I bet it won’t take more than that.

Official documentation mentioned in reference is the best resource for hosting a reactjs app on a firebase project. Although, let me list down simple steps if you are already aware and want to just go with the flow.

Let us assume we have a firebase projects for hosting, viz; “project-env-development”.

Run below commands at the root of our project.

$ npm install -g firebase-tools
//Install firebase cli globally
$ firebase login
// This will open google login on browser to authenticate you.
$ firebase init
// and follow as per below screen shot.

image Steps followed for Firebase hosting project initialization

During this step, make sure you:
Select the appropriate firebase project you wish to host this application on;
Change the public directory to “build” as per our react js app;
Select Yes for single-page app;
Select No for Overwrite index.html.

$ firebase deploy // This will send the build to firebase for deployment / hosting.

Voila! deployed and available at “https://<your firebase project>.web.app/” over the internet.

Multi-project Firebase hosting setup:

(ref: https://firebase.googleblog.com/2016/07/deploy-to-multiple-environments-with.html)

You can also add multi-project setup for multi-environments like “project-env-development”, “project-env-staging” and “project-env-production” and use the deploy scripts in package.json accordingly.

$ firebase use — add // This will add a new firebase project in scope.

Added “project-env-staging” project with alias “staging”.

Switching environments:

$ firebase use // list all added environments with their alias.
$ firebase use default // change pointer to project-env-development firebase project.
$ firebase use staging // change pointer to project-env-staging firebase project.

Use below commands for deployment:

$ firebase deploy -P default
$ firebase deploy -P staging
(where, $ firebase deploy -P <environment default/staging>)

You can also manage/modify these alias in file “/.firebaserc” at the root of the project.

THE END!

Enjoy this post?

Buy Saurabh a coffee

More from Saurabh