How to create reliable and scalable frontend applications
Tags: javascript, react, angular, webdev
Published: 2022-01-21 14:41:33

  
### Intro


A software engineer day to day work usually focused on some specific application or even piece of that software. When a long period of time developer works on only one program he may experience difficulties in the case he needs to start with a **new project**.

In this article, I would like to share my findings which come from frontend applications built by me in recent years.



### **Overview**

First, a walk when planning a new application it has to be decided what is the main purpose.

There are two main directions for a web-based application:

* A website with a **public content**

* **Web/Native** **application**

For content websites, it’s highly suggested to use server-side rendering such as Next.Js, Angular SSR, Gatsby, or similar. These technologies will provide a better performance as well as better Search engine optimization.

On the other hand, web or native applications are used when it’s required a high level of in-app interactions.

In addition, it has to be defined whether the application will have offline mode or features. In that case, the application is considered a Progressive Web App and the usage of service workers will be required.



### **Proposed Technologies list**

* State — Redux

* React, react-router

* UI — MUI or Bootstrap

* Linting — Husky, eslint, prettier

* Testing — Jest

* CI/CD — Gitlab



### **Folders structure**

The following folder structure can be used for the medium as well as small apps.

* Components — all components. Each can have input/output

* Containers — components defining specific layout

* Pages — A page will use one of the containers and contains components.

* Routes — contains route declarations

* Config — Constants

* Services

* Api specific files

* Authorization

* General services — such as traces/logs, system notifications, etc

* Store — Redux’s store files. Such as reducers

* The root folder will contain package.json, eslint, etc.

* .ENV — environment-specific constants

For large and multi-application projects consider reading the article [“Semantic Grouping Folders with Nx”](https://dev.to/this-is-learning/semantic-grouping-folders-with-nx-3467).



### **General essential features**

* Logging, tracing

* Authorization: Send credentials -> receive token. All manipulations with sensitive data should be working via the [Authorization header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).

* Centralized system notifications

* Generic pop-ups: Confirmation popup

* User activity statistics: Backend should save each user action/request for further analysis or an external service can be used.



### **Code modularity**

Modularity is achieved by separating functionality into **components**. Each of them should have one responsibility. Components will have Input/Output data.



### **State management**

**[Redux ](https://redux.js.org/tutorials/fundamentals/part-1-overview)**is one of the suggested options for state management. State flow in react app **unidirectional **and **immutable**. Immutability allows stability and debugging features such as states history. Where it’s possible to go “back in time” analyzing all the state changes.

There are two types of components:

* **Stateless **— has I/O data and does not manage states

* **Stateful **— manages states and transfers into the components. Also are dividing when to transfer state to regular components in order to reduce component rerendering



### **Performance**

* APi calls In browser **caching **— rarely updated data should be stored in Browser’s cache. It is achieved by setting cache [headers for HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) responses.

* App files caching — images, fonts, js bundles should be cached in the browser.

* Reduce components **re-rendering** by limiting states flow.

* **Lazy loading** — the application will load only necessary bundle files. Achieved by [code splitting](https://reactjs.org/docs/code-splitting.html) techniques.



### **Code quality**

In general, the code has to obey industry best practices. The code has to be easily readable and built of small components/methods/classes where each has one responsibility focused.

However, each developer may have his own code style preferences. Therefore it’s strongly suggested to force project-specific code standards. Alignment with code standards can be achieved by using **eslint** library. **Pre-commit hooks** will secure that no non-standard code arrives in the Git repository.

In addition code formatting could be done by **Prettier**. This operation can be attached to the pre-commit hook as well.

Code readability can be achieved with the help of the **CodeMetrics, SonarLint, SonarQube** vscode plugins or similar. The tool will analyze the **cognitive complexity** of the code and will suggest improvements. In general functions/methods should be short and avoid multilevel nested loops or conditionals.

Type declarations are another important point in frontend development. Static type definition provides greater reliability as well as readability. The application should be written on **[TypeScript](https://www.typescriptlang.org/)** which has wide support and community.



### **Unit testing**

Each component has to be test covered by at least 70%. **[Jest](https://jestjs.io/)** is one of the well-supported libraries for that purpose.



### **Versioning**

Git is the most preferred option for version control.

Each commit has to obey commit message standards. [This link](https://www.conventionalcommits.org/en/v1.0.0/) gives a good explanation. Following the standard will provide good readability of the app development history.



### **Deployment**

Gitlab can be used for managing deployments and Continous Integration. Repository updates have to be pushed as new branches. On each commit Gitlab will run unit tests.
After the code review and pipeline passes, a merge request can be created. After the MR is approved commits will become a part of the master/main branch and the original branch will be erased.

The application should have multiple deployment environments such as Stage, Dev, Production. The stage will have the latest master version. After it passes QA tests it can be promoted to Production.



### **Accessibility**

The application has to be accessible to people with all, abilities. It has to support screen readers, color schemes, and font size adaptability.

Chrome Lighthouse dev tool can be used to analyze the level of accessibility covered by an application.



### **UI**

* Use one of the well-supported UI frameworks such as **[Mui ](https://mui.com/)**or **[Bootstrap](https://getbootstrap.com/)**

* Multiple themes support. At least two: light and dark modes should be

* Responsive — mobile-first approach. Guarantees the app will not lack functionality on all devices.



### **Security**

At least the following points should be considered when creating a Frontend application.

Frontend:

* User-generated data **sanitation.** React and Angular natively support sanitation.

* Auth **token secure storage** in HttpOnly only cookies. Refer to the [explanation ](https://owasp.org/www-community/HttpOnly)on the OWASP page.



Backend:

* **Limit** number of **HTTP requests** per user in order to avoid DDOS attacks

* Limit **login attempts**

* **[OWASP ](https://owasp.org/)rules**



### Migration

**Styles separation** — when creating custom styles separate a set of SCSS files containing all the common styles. In the case of migration to another SPA library, the styles can be reused.

It is always difficult to migrate a large codebase. For instance, an Angular app migrates to React. In the major part of the cases, each SPA library has its own architecture and it will not be possible to copy the components. 

However such tools as [NX ](https://nx.dev/)or [Module Federation](https://www.npmjs.com/package/@angular-architects/module-federation) can manage micro frontends and allow gradual migration from one SPA library to another.



### Conclusion

The current article discussed the main best practices which should be considered when planning a new frontend application. All the mentioned techniques may seem like an exaggeration. Though each of them increases the maintainability and reliability of an application.

Let’s recap what we learned:

* Define the type of the project if it’s content-based or app

* Performance

* Modularity

* State management

* Code quality: Typescript, linting

* Stability: Unit tests

* Versioning: git

* Deployment: GitLab

* UI: MUI, Bootstrap

* Accessibility

* Security

* Migration

Photo by <a href="https://unsplash.com/@marcojodoin?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Marc-Olivier Jodoin</a> on <a href="https://unsplash.com/@marcojodoin?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>