Delivery
6 min
Web apps grow with each new feature release. In companies with a mature DevOps process, these releases often happen daily.
With such high-velocity release cycles, the code can quickly become unwieldy. This is especially true for JavaScript-based projects such as NextJS or Angular.
Below are our top five Angular best practices to organize your project for maximum readability, maintainability, and scalability.
At the core of many monolithic applications is a single code base with bloated classes. By nature, these monoliths are challenging to maintain.
They are fragile in the sense that a change to even one line of code could have catastrophic effects on the entire system. The single responsibility principle evolved as a way to prevent these types of problems.
The single responsibility principle means that every software component should have one and only one job.
Building an app using this approach results in a modular framework in which the application is built by stringing together these blocks of code.
Following this approach leads to software that is easier to read and easier to maintain. It's also easier to locate specific functions within the application.
To ensure your code meets this requirement ask yourself this one question. “What does this code do?” If the answer includes the word “and” it’s time to refactor the code down to one responsibility.
Building Angular applications and scaling them is a continuous exercise. This list of best practices for organizing your project will make your application clean, readable, and maintainable.
Angular modules are an implementation of the single responsibility principle. In Angular, each module represents a discrete and independent function.
Angular provides several types of modules to specify how to logically group or organize them.
A core module is a NgModule that instantiates the app and loads core functions that will be used globally across the application.
Thus any singleton service should be implemented in a core module. A header, footer, or navigation bar are examples of this type of module.
All services that have to have one and only one instance per application (singleton services) should be implemented here. Examples include an authentication service or user service.
A feature module represents code that makes up the features of your app. In an online shopping app, for example, you might have a feature module for adding items to a cart and a separate module for making payments.
Shared modules are made of functions that can be combined to create feature modules. An example is a search function that could be used across multiple features.
Structuring the code this way makes things easier to locate and increases opportunities for reusability of code.
Stylesheet files can quickly become disorganized if a common structure is not followed. A general best practice is to use the 7-1 pattern which uses seven folders and one file as follows:
App — The main folder for the project.
Abstract—The Abstract partial, contains all the variables, mixings, and similar components.
Core —Contains typography, resets, and boilerplate code, used across the whole website.
Components — Contains styles for all components that are to be created for one website, such as buttons, tabs and modals.
Layout — Contains files required to define the layout of the site such as the header and footer.
Pages— Contains styles for each specific page.
Vendors — This optional folder is intended for bootstrap frameworks, if any, that are being used for the project.
Create an all.scss file for every folder that contains all the imports for that specific folder.
Many services are designed to operate at the global level. However, there are instances when a service is needed by only one component. Traditional coding best practices recommend the single responsibility principle.
Under this approach, the service and the component would be written as separate items.
However, consider what would happen if the component that requires the service were removed? What you’d end up with is dead code that only serves to clutter the repo. In this case, the best practice is to put the service logic inside the component.
That way, maintaining both the component and service is easier. Plus, you don’t wind up with unused code sitting in the project.
Nested file structures are inherently easier to navigate than a flat-file system that has all code files in a single directory.
However, as the project grows the directory structure could become quite complex. While this makes it easier to locate code, it presents a challenge when writing import statements.
When a directory structure starts to grow beyond three or four levels, the import statement becomes extremely long and is hard to read.
The solution to the problem is to configure path aliases in the tsconfig.json file.
In this file is an array named compilerOptions. Here is where you path aliases to be used throughout the application.
When the code is compiled, any path aliases defined in this array appear in the code it gets replaced with the actual path. The value for each path is a key-value pair object that contains the actual path and alias.
Building Angular applications and scaling them is a continuous exercise. This list of Angular best practices for organizing your project will make your application clean, readable, and maintainable.
Adservio's main goal is to help companies embrace strategies and best practices to meet their digital transformation goals.
Reach out to us to see how we’ve partnered with our clients to deliver quality IT services.