{"id":23581,"url":"https://github.com/akhilben/angular-awesome","name":"angular-awesome","description":"⚡⚡ A collection of Angular best practices and tips for building fast, scalable enterprise level applications! Awesome coding! 😎🤘","projects_count":53,"last_synced_at":"2026-06-03T15:00:23.348Z","repository":{"id":53932652,"uuid":"270536977","full_name":"akhilben/angular-awesome","owner":"akhilben","description":"⚡⚡ A collection of Angular best practices and tips for building fast, scalable enterprise level applications! Awesome coding! 😎🤘","archived":false,"fork":false,"pushed_at":"2024-07-28T13:54:27.000Z","size":424,"stargazers_count":25,"open_issues_count":0,"forks_count":3,"subscribers_count":4,"default_branch":"master","last_synced_at":"2026-05-18T03:03:13.309Z","etag":null,"topics":["angular","angular-8","angular-9","angular-applications","angular-beginners","angular-best-practices","angular-cli","angular-starter-kit","angular10","best-practices","editor-extension","reference-material"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/akhilben.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-08T05:09:55.000Z","updated_at":"2025-11-11T02:46:49.000Z","dependencies_parsed_at":"2024-11-10T17:01:06.273Z","dependency_job_id":null,"html_url":"https://github.com/akhilben/angular-awesome","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/akhilben/angular-awesome","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akhilben%2Fangular-awesome","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akhilben%2Fangular-awesome/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akhilben%2Fangular-awesome/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akhilben%2Fangular-awesome/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akhilben","download_url":"https://codeload.github.com/akhilben/angular-awesome/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akhilben%2Fangular-awesome/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33870026,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"created_at":"2024-01-13T12:56:35.036Z","updated_at":"2026-06-03T15:00:23.349Z","primary_language":null,"list_of_lists":false,"displayable":true,"categories":["`😎 IDE and Plugins`","`⚡ Performance Cheatsheet`","`📚 Folder Structure`","`❄️ Commit Guidelines`","`👷 Configuring Your Project`","`Roadmap`","`🎉 Using Starter Kits`"],"sub_categories":["3. Use tree-shakable providers","Shared Module","Other performance optimisation techniques","Prettier","Aliasing Folders","Core Module","Styling","2. Use trackBy with ngFor","4. Unsubscribe observables","7. Use preloading strategy","8. Lazy load components","9. Use ChangeDetectionStrategy.OnPush","11. Run outside angular","TSLint (⚠️ Deprecated from Angular 11)","1. Avoid function calls in templates.","10. Disable change detection"],"readme":"\u003c!-- PROJECT LOGO --\u003e\n\u003cbr /\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/akhilben/angular-awesome\"\u003e\n    \u003cimg src=\"images/logo.svg\" alt=\"Logo\" width=\"100%\"\u003e\n  \u003c/a\u003e\n\n  \u003cp align=\"center\"\u003e \u003cb\u003e\n    :star: Collection of best practices and tips for building scalable and performant Angular applications. :star: \u003c/b\u003e\n    \u003cbr /\u003e\n    \u003ca href=\"https://github.com/akhilben/angular-awesome/issues\"\u003eReport Bug\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/akhilben/angular-awesome/issues\"\u003eRequest Feature\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n[![GitHub contributors](https://img.shields.io/github/contributors/akhilben/angular-awesome?color=blue\u0026style=for-the-badge)](https://github.com/akhilben/angular-awesome/graphs/contributors) \u0026emsp; [![GitHub](https://img.shields.io/github/license/akhilben/angular-awesome?style=for-the-badge\u0026color=green)](https://github.com/akhilben/angular-awesome/blob/master/LICENSE) \u0026emsp; [![Maintenance](https://img.shields.io/maintenance/yes/2021?color=brightgreen\u0026style=for-the-badge)](https://github.com/akhilben/angular-awesome/graphs/commit-activity) \u0026emsp; [![For](https://img.shields.io/badge/For-Angular-red?style=for-the-badge\u0026logo=angular\u0026color=DD0031)](https://github.com/angular/angular) \u0026emsp; [![Help](https://img.shields.io/badge/-need--help-blueviolet?style=for-the-badge)](#contributing)\n\n\u003cbr /\u003e\n\n\u003c!-- ABOUT THE PROJECT --\u003e\n\n## `🌟 Preface`\n\nThis repo serves as a reference handbook for both starters and experienced developers to look at from time to time to refresh memory and to develop better :notebook:.\n\n\u003e :warning: **_Warning_** : The contents in this document are just general suggestions taken from the Angular community on how to do stuff. As there can be many solutions to a problem, just take the contents as mere suggestions and make use of it if you think it suits your application.\n\nDo lookout (and don't ignore :eyes:) for the **_Tips_** section to find out how to do things more better. Make sure to **expand the collapse** of a section; it's there just for a better user experience. Get the summarized points labelled as **_Takeaway_** at the end of each section if you don't want to spend your time to read the whole.\n\nNow, step in to find some of the recommended good practices and tips for building awesome Angular applications :confetti_ball: :tada:.\n\n\u003cbr /\u003e\n\n\u003c!-- TABLE OF CONTENTS --\u003e\n\n## `📑 Table of Contents`\n\n- [Preface](#-preface)\n\n- [IDE and Plugins](#-ide-and-plugins)\n\n- [Using Starter Kits](#-using-starter-kits)\n\n- [Commit Guidelines](#%EF%B8%8F-commit-guidelines)\n\n- [Configuring Your Project](#-configuring-your-project)\n\n- [Folder Structure](#-folder-structure)\n\n- [Performance Cheatsheet](#-performance-cheatsheet)\n\n\t* [Function calls in templates](#1-avoid-function-calls-in-templates)\n\n  \t* [Use trackBy](#2-use-trackby-with-ngfor)\n\n  \t* [Tree shakable providers](#3-use-tree-shakable-providers)\n\n    * [Unsubscribe observables](#4-unsubscribe-observables)\n\n\t* [Async pipe](#5-use-async-pipe)\n\n    * [Lazy load modules](#6-lazy-load-modules)\n\n    * [Preloading strategy](#7-use-preloading-strategy)\n\n    * [Lazy load components](#8-lazy-load-components)\n\n    * [ChangeDetectionStrategy.OnPush](#9-use-changedetectionstrategyonPush)\n\n    * [Disable change detection](#10-disable-change-detection)\n\n    * [Run outside angular](#11-run-outside-angular)\n\n    * [Other techniques](#other-performance-optimisation-techniques)\n\n- [Contributing](#contributing)\n\n- [License](#license)\n\n\u003cbr /\u003e\n\n\u003c!-- CHOOSING IDE --\u003e\n\n## `😎 IDE and Plugins`\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\nThere are several powerful free and paid IDE's available in the market today. Choosing the right IDE is very important for development since not all IDE's are great for every language/framework/library. Have added a list of awesome plugins/extensions for IDE's below for a smooth development.\n\n1. \u003cimg src=\"images/code.svg\" alt=\"VS Code\" width=\"30\" height=\"30\" vertical-align=\"middle\"\u003e \u0026nbsp; \u003cb\u003e[Visual Studio Code](https://code.visualstudio.com/)\u003c/b\u003e\u003cbr /\u003e\n   VS Code is a very powerful code editor from Microsoft which is highly recommended for working with Angular. Why? It has a great \u003cb\u003esupport for TypeScript\u003c/b\u003e out of the box. Moreover, it has \u003cb\u003esyntax highlighting\u003c/b\u003e and autocomplete with \u003cb\u003eIntelliSense\u003c/b\u003e, which provides smart completions based on variable types, function definitions, and imported modules. Adding up to many other powerfull features, it is \u003cb\u003ehighly customizable with tons of extensions\u003c/b\u003e, especially for Angular. Below is a list of few vs code extensions that are useful while developing Angular applications. \u003cbr /\u003e\n\n   - [ES Lint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint):\u003cbr /\u003e\n     A must have extension which marks the code where you have a problem and display a \u003cb\u003elist of warnings \u0026 errors\u003c/b\u003e on hovering it. It even have an \u003cb\u003eautofix problems\u003c/b\u003e functionality. This will help you to adhere to the recommented styleguides and conventions for Angular.\u003cbr /\u003e\n   - [Angular Language Service](https://marketplace.visualstudio.com/items?itemName=Angular.ng-template):\u003cbr /\u003e\n     This extension provides a rich editing experience \u003cb\u003efor Angular templates\u003c/b\u003e, both inline and external templates including \u003cb\u003ecompletions lists, AOT diagnostic messages, quick info and go to definition\u003c/b\u003e\u003cbr /\u003e\n   - [Angular Snippets](https://marketplace.visualstudio.com/items?itemName=johnpapa.Angular2):\u003cbr /\u003e\n     This extension adds \u003cb\u003esnippets for Angular for TypeScript, HTML and NgRx\u003c/b\u003e. This will help you save a lot of time while developing applications. Just type part of a snippet, press enter, and the snippet unfolds! [Angular 8 Snippets](https://marketplace.visualstudio.com/items?itemName=Mikael.Angular-BeastCode) is also another similar, honorable mention.\n   - [Angular Schematics](https://marketplace.visualstudio.com/items?itemName=cyrilletuzi.angular-schematics):\u003cbr /\u003e\n     This extension allows you to \u003cb\u003egenerate Angular schematics with a Graphical User Interface\u003c/b\u003e. This extension promote Angular good practices, by improving component generation with the suggestion of different component types. Use this extension to \u003cb\u003equickly generate component, module, service\u003c/b\u003e etc. [Angular Files](https://marketplace.visualstudio.com/items?itemName=alexiv.vscode-angular2-files) is also another similar, honorable mention.\n   - [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode):\u003cbr /\u003e\n     Prettier is an opinionated \u003cb\u003ecode formatter\u003c/b\u003e. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary.\u003cbr /\u003e\n   - [GitLens — Git supercharged](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens):\u003cbr /\u003e\n     GitLens supercharges the Git capabilities built into Visual Studio Code. It helps you to \u003cb\u003evisualize code authorship\u003c/b\u003e at a glance via Git blame annotations and code lens, seamlessly \u003cb\u003enavigate and explore Git repositories\u003c/b\u003e, gain valuable \u003cb\u003einsights via powerful comparison commands\u003c/b\u003e, and so much more.\n\n2. \u003cimg src=\"images/webstorm.svg\" alt=\"WebStorm\" width=\"30\" height=\"30\" vertical-align=\"middle\"\u003e \u0026nbsp; \u003cb\u003e[WebStorm](https://www.jetbrains.com/webstorm/)\u003c/b\u003e\u003cbr /\u003e\n   One of the smartest and most powerful IDE's for developing Javascript applications available out there. WebStorm by IntelliJ is a highly recommended pick for developing Angular applications with built-in \u003cb\u003esupport for TypeScript\u003c/b\u003e out of the box. WebStorm comes with \u003cb\u003eintelligent code completion, on-the-fly error detection, powerful navigation and refactoring for Typescript and stylesheet languages\u003c/b\u003e. WebStorm is fully packed with a variety of \u003cb\u003ebuilt-in developer tools\u003c/b\u003e and various other features and thus saves your time juggling multiple plugins for seamless development. Below is a list of few WebStorm plugins that are useful while developing Angular applications. \u003cbr /\u003e\n   - [Angular and AngularJS](https://plugins.jetbrains.com/plugin/6971-angular-and-angularjs):\u003cbr /\u003e\n     This all-in-one framework integration plugin packs tons of features such as: \u003cb\u003ecode completion\u003c/b\u003e for components, built-in and custom directives, and methods in both templates and ts files; \u003cb\u003enavigation\u003c/b\u003e from the component, custom directives and event handlers to their definition; \u003cb\u003ecode snippets\u003c/b\u003e and \u003cb\u003eAngular CLI integration\u003c/b\u003e.\u003cbr /\u003e\n   - [Prettier](https://plugins.jetbrains.com/plugin/10456-prettier):\u003cbr /\u003e\n     This plugin adds support for Prettier, an opinionated \u003cb\u003ecode formatter\u003c/b\u003e. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary.\u003cbr /\u003e\n   - [GitToolBox](https://plugins.jetbrains.com/plugin/7499-gittoolbox):\u003cbr /\u003e\n     This plugin \u003cb\u003eextends Git Integration\u003c/b\u003e with additional features such as \u003cb\u003estatus display, auto fetch, inline blame annotation, commit dialog completion, behind notifications\u003c/b\u003e and more.\n\n \u003cbr /\u003e\n   \n \u003eDo check out the [Angular IDE](https://www.genuitec.com/products/angular-ide/) by Codemix, which is a dedicated, powerful IDE for Angular.\n \n \u003c/details\u003e  \n   \n \u003cbr /\u003e\n   \n| :heart: _Takeaway_ : Use your favorite IDE ([Visual Studio Code](https://code.visualstudio.com/) or [WebStorm](https://www.jetbrains.com/webstorm/) recommended) along with awesome plugins for a smooth development experience. |\n| :--- |\n\n\u003cbr /\u003e\n\n🔝 [Back to Contents](#-table-of-contents)\n\n\u003cbr /\u003e\n  \n\u003c!-- STARTER KITS --\u003e\n## `🎉 Using Starter Kits`\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n  \nThere is no doubt that the Angular CLI's `ng new` command generates a decent base app to kick-start your project. But sometimes, we want more. Angular starter kits/boilerplates will heavily **reduce the development time for initial setups** - from basic recommended folder structure to interceptors and guards, these seeds have many features readily available. Below are some of the most used and well maintained Angular starter kits:\n\n1. [Angular, NgRx and Angular Material Starter](https://github.com/tomastrajan/angular-ngrx-material-starter) : As the name suggests, the stack includes **Angular, NgRx, Angular Material and Bootstrap 4**. This starter has a **strong application structure** that is easily scalable and suitable for big projects. It also packs **basic interceptors, error-handlers, auth-guards, ngrx files, Travis CLI etc.** used along with a TODO application example.\n\n2. [ngX Starter Kit](https://github.com/ngx-rocket/starter-kit) : Generated using [ngx-Rocket](https://github.com/ngx-rocket/generator-ngx-rocket), this starter kit includes **modern tools** and workflow based on angular-cli, **best practices** from the community, a **scalable base template** and a good learning base. This starter kit comes pre-equipped with **Bootstrat 4, Font Awesome, RxJS, ng-bootstrap, ngx-translate and Lodash**. The starter also includes a basic \\*\\*login screen, interceptors, guards etc.\n\n3. [ngx-admin](https://akveo.github.io/ngx-admin/) : One of the most widely used Angular **admin dashboard template** based on **Angular 9+, Bootstrap 4+ and Nebular**. This template packs all the features and more that you will need for an admin dashboard template.\n\n\u003c/details\u003e\n\n\u003cbr /\u003e\n   \n| :heart: _Takeaway_ : Use starters/boilerplates to save initial setup time and for a smooth start. |\n| --- |\n\n\u003cbr /\u003e\n\n🔝 [Back to Contents](#-table-of-contents)\n\n\u003cbr /\u003e\n\n## `❄️ Commit Guidelines`\n\n \u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nUsually developers tend to add some random commit messages which doesn't actually add any value to the project. By using some precise rules over how the commit messages are formatted can lead to more readable messages that are easy to follow when looking through the project history. We can even generate changelogs from such commit messages :astonished:! It's recommended to follow the commit guidelines from the [official Angular repo](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines).\u003cbr /\u003e\n\n- Each commit message consists of a **header**, a **body**, and a **footer (optional)**. The header has a special format that includes a type, and a subject: \u003cbr /\u003e\n  ```\n  \u003ctype\u003e: \u003csubject\u003e\n  \u003cBLANK LINE\u003e\n  \u003cbody\u003e\n  \u003cBLANK LINE\u003e\n  \u003cfooter\u003e\n  ```\n- The `type` can be any of the following:\u003cbr /\u003e\n\n  - **docs**: Documentation only changes\n  - **feat**: A new feature\n  - **fix**: A bug fix\n  - **perf**: A code change that improves performance\n  - **refactor**: A code change that neither fixes a bug nor adds a feature\n  - **test**: Adding missing tests or correcting existing tests\n\n- The `footer` should contain a closing reference issue if any.\n\n\u003cbr /\u003e\n\nEg:\n\n```\nfix: no password validations\n\nlength and pattern validations for password\n\nPR Close #11721\n```\n\n\u003cbr /\u003e\n\n\u003e :bulb: **_Tip_** : Use [Conventional Changelog](https://github.com/conventional-changelog/conventional-changelog) or it’s [standard version](https://github.com/conventional-changelog/standard-version) to generate changelogs and release notes from project's commit messages and metadata with this commit guideline.\n\n\u003c/details\u003e\n\n\u003cbr /\u003e\n   \n| :heart: _Takeaway_ : It's recommended to follow the commit guidelines of the [official Angular repo](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines); consisting of a header, a body, and a footer (optional). Use these commits for generating changelogs. |\n| :--- |\n\n\u003cbr /\u003e\n\n🔝 [Back to Contents](#-table-of-contents)\n\n\u003cbr /\u003e\n\n\u003c!-- CONFIGURING --\u003e\n\n## `👷 Configuring Your Project`\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n  \n  There is no doubt that Angular CLI has covered most of the recommended configurations out of the box for us. But we can still make it better :heart_eyes_cat:!\n  \n  ### TSLint (⚠️ Deprecated from Angular 11)\n  Angular CLI generates a basic set of tslint rules for us for **static code analysis** using [codelyzer](https://github.com/mgechev/codelyzer) by [Minko Gechev](https://github.com/mgechev). Below is the recommended configuration:\n  ```js\n  {\n  // The rules component-selector and directive-selector have the following arguments:\n  // [ENABLED, \"attribute\" | \"element\", \"prefix\" | [\"listOfPrefixes\"], \"camelCase\" | \"kebab-case\"]\n  \"component-selector\": [true, \"element\", [\"cmp-prefix1\", \"cmp-prefix2\"], \"kebab-case\"],\n  \"directive-selector\": [true, \"attribute\", [\"dir-prefix1\", \"dir-prefix2\"], \"camelCase\"],\n\n\"component-max-inline-declarations\": true,\n\"contextual-lifecycle\": true,\n\"no-conflicting-lifecycle\": true,\n\"no-host-metadata-property\": true,\n\"no-input-rename\": true,\n\"no-inputs-metadata-property\": true,\n\"no-output-native\": true,\n\"no-output-on-prefix\": true,\n\"no-output-rename\": true,\n\"no-outputs-metadata-property\": true,\n\"no-queries-metadata-property\": true,\n\"prefer-inline-decorator\": true,\n\"template-banana-in-box\": true,\n\"template-no-negated-async\": true,\n\"use-lifecycle-interface\": true,\n\"use-pipe-transform-interface\": true,\n\n// The rules component-class-suffix and directive-class-suffix have the following arguments:\n// [ENABLED, \"suffix\" | [\"listOfSuffixes\"]]\n// Where \"suffix\" is/are your custom(s) suffix(es), for instance \"Page\" for Ionic components.\n\"component-class-suffix\": [true, \"Component\"],\n\"directive-class-suffix\": [true, \"Directive\"]\n}\n\n````\n\n\u003cbr /\u003e\n\n\u003e :bulb: **_Tips_** : Want to add more rules on top of the Angular CLI configuration? It's highly recommended to use the [Angular TSLint Preset](https://github.com/mgechev/tslint-angular) by [Minko Gechev](https://github.com/mgechev).\u003cbr /\u003e\nIt's highly recommended to use [Husky 🐶](https://github.com/typicode/husky) to check for lint issues on a git commit hook and avoid bad commit/push.\n\n\u003cbr /\u003e\n\n### Prettier\nThe **opinionated code formatter**, prettifies our code to look even more beautiful :heart_eyes:. First step is to install the Prettier plugin in your favorite IDE (go to [Choosing IDE](#sunglasses-choosing-ide)) or `npm install prettier` to make your team members reference the same configuration file regardless of the IDE. Don't forget to set the _format on save_ option in your IDE.\n\n```js\n// For VS Code\n“editor.formatOnSave”: true\n````\n\nGreat :clap:! But, how will the prettier and tslint work together? It’s simple, we can **leave the code-quality rules for TSLint** to handle, and we can have **Prettier take care of formatting rules** by removing formatting rules from tslint.json.\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : Check out [Setting up Prettier in an Angular CLI Project](https://medium.com/@victormejia/setting-up-prettier-in-an-angular-cli-project-2f50c3b9a537) by [Victor Mejia](https://medium.com/@victormejia).\n\n\u003cbr /\u003e\n\n\u003e :bulb: **_Tip_** : Use [tslint-config-prettier](https://github.com/prettier/tslint-config-prettier) to use TSLint and Prettier without conflicts.\n\n \u003cbr /\u003e\n \n ### Aliasing Folders\n You might have come across some import statements in codes which is way too long and dirty, like this ```import { RandomService } from '../../../../core/services/random.service'``` :dizzy_face:. To avaoid such situations, we can use aliases for folder paths **making the imports cleaner, readable and consistent**. So, how will we do this? Head to the `tsconfig.json` in your project root and add aliases to the `paths` property:\n \n ```json\n \"paths\": {\n      \"@app/*\": [\"./src/app/*\"],\n      \"@shared/*\": [\"./src/app/shared/*\"],\n      \"@core/*\": [\"./src/app/core/*\"],\n      \"@env/*\": [\"environments/*\"]\n    }\n```\nAwesome :sunglasses:! Now we can import with more cleaner statements like : \n```js\nimport { RandomService } from '@core/services/random.service'\n```\n \u003cbr /\u003e\n \n Ok, but hold on, what about imports for style processors like scss? Angular have a solution for that as well :beers:. Head on to `angular.json` and add a property to the `options` property (the property inside which you add additional scripts/styles).\n \n ```json\n \"stylePreprocessorOptions\": {\n\t\t\"includePaths\": [\n\t\t\t\"src/theme/\"\n\t\t]\n\t}\n ```\n \n (:page_with_curl: Note that we have included the path in assumption that scss files are inside `theme` folder) Cool :snowman:! Now we can import like :\n \n ```css\n @import \"variables\";\n ```\n \u003cbr /\u003e\n \n \u003e :gift: **_Resources_** : \u003cbr /\u003e\n \t1. Check out [6 Best Practices \u0026 Pro Tips when using Angular CLI](https://medium.com/@tomastrajan/6-best-practices-pro-tips-for-angular-cli-better-developer-experience-7b328bc9db81) by [@tomastrajan](https://medium.com/@tomastrajan). \u003cbr /\u003e\n \t2. Check out [Angular - Shortcut to Importing Styles Files in Components](https://scotch.io/tutorials/angular-shortcut-to-importing-styles-files-in-components) on [scotch.io](https://scotch.io/)\n \n \u003c/details\u003e\n\n\u003cbr /\u003e\n   \n| :heart: _Takeaway_ : Setup tslint for code quality rules and Prettier for code formatting rules and use pre-commit hooks to check for lint issues. Add aliases for folders to remove relative paths in import statements. |\n| :--- |\n\n\u003cbr /\u003e\n\n🔝 [Back to Contents](#-table-of-contents)\n\n\u003cbr /\u003e\n\n\u003c!-- FOLDER STRUCTURE --\u003e\n\n## `📚 Folder Structure`\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n  \n  Finding a scalable and clean folder structure architecture is always hard. Without a proper architecture, you will end up having a really clumsy and hard to maintain piece of codes :worried:. There are several blogs/repos which specifies a proper architecture for Angular applications, and each one is a bit different. This section is just a suggestion for architecting a proper folder structure; so just take away the main points and choose a suitable one for yourself (blogs and repos attached in `resources` at the end of this section). **A good guideline to follow is to split our application into at least three different modules — Core, Shared and Feature.** Okay, let's dive into it one by one :dolphin:.\n\t\n### Core Module\nIdeally, the `CoreModule` contains files that are singleton, that is, those files which we only need to load at run-time. The module can contain **singleton services, core components, guards, interceptors, constants, enums and core models**. The core module should be imported only once, which is inside `AppModule`.\n\n```\n|-- 📁 core\n|      |-- 📁 components\n|      |      |-- 📁 shells\n|      |      |-- 📁 header\n|      |      |-- 📁 page-not-found\n|      |      ...\n|      |-- 📁 guards\n|      |      |-- 📄 auth.guard.ts\n|      |      ...\n|      |-- 📁 interceptors\n|      |      |-- 📄 api-prefix.interceptor.ts\n|      |      |-- 📄 error-handler.interceptor.ts\n|      |      ...\n|      |-- 📁 services\n|      |      |-- 📄 utility.service.ts\n|      |      |-- 📄 authentication.service.ts\n|      |      ...\n|      |-- 📁 enums\n|      |-- 📁 models\n|      |-- 📁 constants\n|      |-- 📄 core.module.ts\n|      |-- 📄 ensureModuleLoadedOnceGuard.ts\n|      |-- 📄 logger.service.ts\n```\n\n\u003cbr /\u003e\n\n\u003e :bulb: **_Tips_** : Add a check in the `CoreModule` constructor and throw an error if already loaded or add a guard for the same to avoid accidental imports (refer [here](https://github.com/ngx-rocket/starter-kit/blob/master/src/app/%40core/core.module.ts)) .\u003cbr /\u003e\n\u003e Add a logger system in `logger.service.ts` file (refer [here](https://github.com/ngx-rocket/starter-kit/blob/master/src/app/%40core/logger.service.ts)).\n\n\u003cbr /\u003e\n\n### Shared Module\n\n`SharedModule` is the module where all our **shared or _dumb components_, directives and pipes** go. We can also **add any third-party components/directives/pipes** (like [Angular Material](https://material.angular.io/) components) which will be needed throughout our application, to the `imports` and `exports` of the module. This module can be then imported to each _feature module_.\n\n```\n|-- 📁 shared\n|      |-- 📁 components\n|      |      |-- 📁 loader\n|      |      |-- 📁 confirmation-dialog\n|      |      ...\n|      |-- 📁 directives\n|      |      |-- 📄 drag-drop.directive.ts\n|      |      |-- 📄 scroll-spy.directive.ts\n|      |      ...\n|      |-- 📁 pipes\n|      |      |-- 📄 custom-date.pipe.ts\n|      |      |-- 📄 safe.pipe.ts\n|      |      ...\n|      |-- 📁 models\n|      |      |-- 📄 user.ts\n|      |      |-- 📄 api-response.ts\n|      |-- 📄 shared.module.ts\n```\n\n\u003cbr /\u003e\n\n\u003e :page_with_curl: **_Note_** : Don't forget to add the components, directives and pipes to the `exports` inside `shared.module.ts`.\n\n\u003cbr /\u003e\n\n### Feature Modules\n\nIt's recommended to create feature modules **for every independent feature** of our application. Ideally, **feature modules shouldn't be dependant on other modules other than the services provided by CoreModule and features exported by SharedModule**. A feature module directory can contain `components`, `pages`, `services` etc. that is specific to the corresponding feature.\n\u003cbr /\u003e\u003cbr /\u003e\nThe `pages` folder contains higher level components or even lazy loaded modules. We can refer to a `page` as the parent component which contains several other child components which ultimately makes up a _page_. The `components` folder contains components which are consumed by various `pages` of the corresponding feature.\n\n```\n|-- 📁 modules\n|      |-- 📁 home\n|      |      |-- 📁 components\n|      |      |      |-- 📁 table\n|      |      |      ...\n|      |      |-- 📁 pages\n|      |      |      |-- 📁 home\n|      |      |      |-- 📁 details\n|      |      |      ...\n|      |      ...\n|      |      |-- 📄 home-routing.module.ts\n|      |      |-- 📄 home.module.ts\n|      |-- 📁 users\n|      |      |-- 📁 components\n|      |      |-- 📁 pages\n|      |      ...\n|      |      |-- 📄 users-routing.module.ts\n|      |      |-- 📄 users.module.ts\n```\n\n\u003cbr /\u003e\n\n### Styling\n\nIt's preferred to add a `theme` folder inside `src` to include custom themes and scss variables.\n\n```\n|-- 📁 theme\n|      |-- 📁 partials\n|      |-- 📄 variables.scss\n|      |      ...\n|      |-- 📄 theme.scss\n```\n\nNow we can import the `theme.scss` in our main `styles.scss` where we add global styles and import other style files.\n\n\u003c/details\u003e\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : \u003cbr /\u003e 1. Check out [Choosing The Right File Structure for Angular in 2020 and Beyond 📕!](https://itnext.io/choosing-the-right-file-structure-for-angular-in-2020-and-beyond-a53a71f7eb05) by [Mathis Garberg](https://itnext.io/@mathis.garberg). \u003cbr /\u003e 2. Check out [How to architect epic Angular app in less than 10 minutes! ⏱️😅](https://medium.com/@tomastrajan/how-to-build-epic-angular-app-with-clean-architecture-91640ed1656) by [Tomas Trajan](https://medium.com/@tomastrajan). \u003cbr /\u003e 3. Check out [Angular Folder Structure](https://medium.com/@motcowley/angular-folder-structure-d1809be95542) by [Tom Cowley](https://medium.com/@motcowley). \u003cbr /\u003e 4. Check out the excellent folder structure in these [starter kits](#-using-starter-kits).\n\n\u003cbr /\u003e\n\n| :heart: _Takeaway_ : Split our application into at least three different modules — Core, Shared and Feature; below is the bigger picture 🖼️ : |\n| :-------------------------------------------------------------------------------------------------------------------------------------------- |\n\n\n```\nsrc/\n|-- 📁 app\n|      |-- 📁 core            \t    core module (singleton services, single-use components, interceptors, guards etc.)\n|      |-- 📁 shared          \t    shared module  (common components, directives and pipes)\n|      |-- 📁 modules         \t    feature modules (each containing pages, components, services etc.)\n|      |-- 📄 app.component.*\n|      |-- 📄 app.module.ts\n|      |-- 📄 app-routing.module.ts\n|      +- ...\n|-- 📁 assets\n|-- 📁 environments\n|-- 📁 theme                  \t    app global scss variables, partials and theme\n|-- 📁 translations/                translations files\n|-- 📄 index.html\n+- ...\n|-- 📄 main.ts\n```\n\n\u003cbr /\u003e\n\n🔝 [Back to Contents](#-table-of-contents)\n\n\u003cbr /\u003e\n\n## `⚡ Performance Cheatsheet`\n\n\u003cdetails open\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nIt's a known fact that Angular is a highly performant framework. But we can make it better by following some best practices. Let's jump in to the list of such best practices :nerd_face: :\n\n### 1. Avoid function calls in templates.\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nIt is not a good practice to write function calls for computing values inside the templates. And if it's a complex function, a big NO :skull:.\n\n```html\n\u003ctr *ngFor=\"let book of books\"\u003e\n  {{calculatePrice(book)}}\n\u003c/tr\u003e\n❌\n```\n\n#### Why?\n\nAngular will run your function in each of it's change detection cycle (which is quite frequent) and if the function is a complex one, this will impose a serious effect on the performance.\n\n#### Solution:\n\nThere may be some cases where this is unavoidable, but for most cases this can be avoided by:\n\n1.  **Creating a property in the ts file and setting the value to it once.**\n\n    ```js\n    this.books = this.books.map(book =\u003e ( { ...books, price: calculatePrice(book)  } );\n    ```\n\n2.  **Using pure pipes** : A pure pipe is a pipe that will always always return the same output for an input. Angular executes a pure pipe only when it detects a pure change to the input value because it already knows that the pipe will return the same value for the same input.\n\t\n\n    ```js\n    @Pipe({\n\t\tname: 'dummy',\n\t\tpure: true\n\t})\n\texport class somePipe implements PipeTransform {\n\t\ttransform(value: any, args?: any): any {\n\t\t\t // logic\n\t\t}\n\t}\n    ```\n\t\n\n    \u003e :gift: **_Resources_** : Check out [The essential difference between pure and impure pipes in Angular and why that matters](https://indepth.dev/the-essential-difference-between-pure-and-impure-pipes-in-angular-and-why-that-matters/) by [Max Koretskyi](https://indepth.dev/author/maxkoretskyi/)\n\n\u003c/details\u003e\n\n### 2. Use trackBy with ngFor\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nWhen using `*ngFor` to loop over an array which might change over time, it is recommended to use `trackBy` **to track array items with unique identifier**.\n\n#### Why?\n\nWhen an array changes (eg: when we push a new item to array), Angular will remove all the DOM elements associated with that array and create all of it again. This is because Angular has no knowledge of which items have been removed or added.\n\n#### Solution:\n\nUse `trackBy`. If we provide a `trackBy` function, Angular can track which items have been added or removed in the array according to the unique identifier. It then has to create or destroy the DOM elements for only those items that have changed. Cool :gem:! Now, this is how we dot it:\n\n```html\n\u003ctr *ngFor=\"let book of books; trackBy: trackByFn\"\"\u003e{{book.name}}\u003c/tr\u003e\n```\n\nand then in your `component.ts`:\n\n```js\ntrackByFn(index: number, book: Book) {\n    return item.id;\n}\n```\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : Check out [Angular — Improve Performance with trackBy](https://netbasal.com/angular-2-improve-performance-with-trackby-cc147b5104e5) by [Netanel Basal](https://netbasal.com/@NetanelBasal)\n\n\u003c/details\u003e\n\n### 3. Use tree-shakable providers\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nMake your services **tree-shakable by using the `providedIn` attribute** of the `@Injectable()` decorator instead of explicitely specifying in the `providers` attribute of a module/component :palm_tree:.\n\n#### Why?\n\nIf your service is tree-shakable, Angular can exclude the code in the final build bundle provided that it's not used anywhere. This can help reduce the overall bundle size :tada:.\n\n#### Solution:\n\nBy default, value for `providedIn` is `root`. This will provide your service at the root injector level and can be injected anywhere in your application. Angular 9+ comes with a couple of other options as well:\n\n1. `platform` - The use case comes when you are running multiple [angular elements (web components)](https://angular.io/guide/elements) in a single page. Your service will now become a global singleton at the platform-level, and is shared between all of the Angular applications on your page.\n2. `any` - Angular will provide a unique instance of your service for every module that injects it.\n\n```js\nimport { Injectable } from \"@angular/core\";\n\n@Injectable({\n  providedIn: \"root\", // or 'any' or 'platform'\n})\nexport class SomeService {}\n```\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : Check out [Dependency injection with Angular 9](https://blog.angulartraining.com/dependency-injection-with-angular-9-63ce524496d9) by [Alain Chautard](https://blog.angulartraining.com/@angulartraining)\n\n\u003c/details\u003e\n\n### 4. Unsubscribe observables\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nWhen you subscribe to observables, make sure to unsubscribe them in the `ngOnDestroy` method :eyes:.\n\n#### Why?\n\nIf you fail to unsubscribe your observables, chances are there that **memory leaks** might happen since your observable stream is left open even after that component is destroyed. This will lead to uexpected behaviours and serious performance issues :scream:.\n\n#### Solution:\n\nThere are various ways to unsubscribe observables:\n\n1. We can make use of `takeUntil` to listen to the changes until another observable emits a value.\n\n   ```js\n   private _destroy$ = new Subject();\n\n   public ngOnInit(): void {\n     sampleObservable$\n     .pipe(\n       // listen to the observable until this._destroy$ emits a value\n       takeUntil(this._destroy$)\n     )\n     .subscribe(item =\u003e // logic);\n   }\n\n   public ngOnDestroy(): void {\n     this._destroyed$.next();\n     this._destroyed$.complete();\n   }\n   ```\n\n2. If you need to subscribe to an observable only once, use `take(1)`. 📄 Note that you will need to use `takeUntil` to avoid any memory leaks caused when the subscription hasn’t received a value before the component got destroyed.\n\n   ```js\n   sampleObservable$\n   .pipe(\n     take(1),\n     takeUntil(this._destroy$)\n   )\n   .subscribe(item =\u003e // logic);\n   ```\n\n3. Using `unsubscribe()` method of `Subscription`. Using this method, you have to `add()` your observables (if you have multiple :train:) to the `Subscription` and destroy on `ngOnDestroy` with the `unsubscribe()` method.\n\n   ```js\n   private _subscriptions$ = new Subscription();\n\n   public ngOnInit (): void {\n     // we can add multiple observables to _subscriptions$ with add()\n     this._subscriptions$.add(\n       sampleObservable1$\n       .subscribe(item =\u003e // logic)\n     );\n   }\n\n   public ngOnDestroy (): void {\n     this._subscriptions$.unsubscribe();\n   }\n   ```\n\n\u003cbr /\u003e\n\n\u003e :bulb: **_Tip_** : Make use of lint rules to detect any unsubscribed observables. Check out [rxjs-tslint](https://github.com/ReactiveX/rxjs-tslint) for TSLint rules targeting RxJS.\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : Check out [6 Ways to Unsubscribe from Observables in Angular](https://blog.bitsrc.io/6-ways-to-unsubscribe-from-observables-in-angular-ab912819a78f) by [Chidume Nnamdi](https://blog.bitsrc.io/@kurtwanger40)\n\n\u003c/details\u003e\n\n### 5. Use async pipe\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nIn the previous section, we learnt about unsubscribing observables. But there is a much more efficient way for the same problem, the magical `async` pipe :dizzy:. It's recommended to avoid subscribing to observables from components and instead subscribe to the observables from the template.\n\n#### Why?\n\nBecause subscriptions can lead to memory leaks if not properly unsubscribed and it's an additional overhead to do so :weary:.\n\n#### Solution:\n\nFear not! Angular have a magic potion up the sleeves just for **automatically managing subscriptions** - `async` pipe :crystal_ball:. Yes, it magically handles the subscriptions for us; no more memory leaks by forgetting to unsubscribe observables :smirk:. Use it whenever it's possible to.\n\n```html\n\u003cp\u003e{{ someObservable$ | async }}\u003c/p\u003e\n\n\u003cp\u003e{{ (someOtherObservable$ | async).value }}\u003c/p\u003e\n```\n\n\u003c/details\u003e\n\n### 6. Lazy load modules\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nLazy loading is said to be one of the most powerfull feature of Angular. It's recommended to **lazy load your feature modules whenever it's possible to.**\n\n#### Why?\n\nBy default, webpack (the default bundler of Angular), bundles all your code into one large bundle. This will largely increase the initial rendering time since the browser has to downlaod that one single large file initially itself, leading to a bad user experience :rage:.\n\n#### Solution:\n\nAngular offers a powefull solution to that problem. **Split your code to separate bundles and load them on demand :muscle:.** And we do that via 'lazy loading'. This will **reduce the initial rendering time** since the browser has to download only a small file that contains the code for just your initial page. The browser will be fed the other files on-demand, i.e, when the user needs it (by navigating to a certain page).\n\n```js\n// Note that the below syntax is valid for Angular 8 and above.\n{ path: 'home',  loadChildren: () =\u003e import('./home.module').then(module =\u003e module.HomeModule) }\n```\n\n\u003e :page_facing_up: **_Note_** : Do not lazy load the default route, as the browser will have to download an extra lazy loaded chunk after downloading the main chunk and parse it. This will slow down the initial rendering time.\n\n\u003c/details\u003e\n\n### 7. Use preloading strategy\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nPreloading strategy is a concept which can be used along with lazy loading to make our application much more faster. You can use Angular's default `PreloadAllModules` strategy, or you can even write your own cutom strategies depending upon the requirements :truck:.\n\n#### Why\n\nWhen we lazy load a module, there is a possible latency since the browser loads the lazy loaded chunk and parse it only when we navigate to that module. This will lead to a bad user experience since the user might be required to wait for sometime until the page gets loaded :construction:.\n\n#### Solution:\n\nUse preloading strategy to **load lazy loaded modules in the background after all the eager loaded modules are ready**. This eliminates the possible latency when navigating to a lazy loaded module, but still has the benefit of faster initial loading of the app because the initial module(s) get loaded first. Such a cool feature :snowflake:! We can do that in various ways:\n\n1. **PreloadAllModules** : This is the default preloading strategy of Angular. This will load all the lazy loaded modules in the background once all the eager loaded modules are ready.\n\n   ```js\n   imports: [\n     ...\n     RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })\n   ],\n   ```\n\n2. **Custom strategy** : We may not always want to preload all the modules. Some modules might be a less used module which we don't wan't to preload. Or you may want to preload the modules based on some conditions, say, by checking user's bandwidth. We can write a custom preloading strategy for that :heart_eyes_cat:.\n\n   ```js\n   import { Observable } from \"rxjs/Observable\";\n   import { PreloadingStrategy, Route } from \"@angular/router\";\n\n   export class CustomPreloadStrategy implements PreloadingStrategy {\n     preload(route: Route, preload: Function): Observable\u003cany\u003e {\n       if (someCondition) {\n         return preload();\n       }\n       return Observable.of(null);\n     }\n   }\n   ```\n\n   And in the `AppModule`:\n\n   ```js\n   imports: [\n     ...\n     RouterModule.forRoot(routes, { preloadingStrategy: CustomPreloadStrategy })\n   ],\n   ```\n\n\u003cbr /\u003e\n\n\u003e :bulb: **_Tips_** : It's highly recommended to use [ngx-quicklink](https://github.com/mgechev/ngx-quicklink) by [Minko Gechev](https://github.com/mgechev) which automatically downloads the lazy-loaded modules associated with all the visible links on the screen using [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API). It also checks if the user isn't on a slow connection before preloading :fire:. \u003cbr /\u003e\n\u003e Or, make use of machine learning by predictively preloading modules with [Guess.js](https://github.com/guess-js/guess) :crystal_ball:.\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : \u003cbr /\u003e 1. Check out [Preloading in Angular](https://alligator.io/angular/preloading/) on [alligator.io](https://alligator.io/). \u003cbr /\u003e 2. Check out [Route preloading strategies in Angular](https://web.dev/route-preloading-in-angular/) by [Minko Gechev](https://web.dev/authors/mgechev/).\n\n\u003c/details\u003e\n\n### 8. Lazy load components\n\n\u003e :page_facing_up: **_Note_** : This feature is only supported in Angular 9+.\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nYes, it's also possible to lazy load components or modules without a route with Angular's Ivy engine :fire:. We can use this awesome feature to reduce the load/rendering time again!\n\n#### Why?\n\nSometimes, you might have some components that are rarely used, say, an info popup that the users use very rarely. Pre loading the code for such components doesn't make any sense. If we can remove such components and load only those components that are necessary for the initial rendering, there will be a considerable gain in the rendering speed :zap:.\n\n#### Solution:\n\nLet's check out how to lazy load components through the below steps :\n\n1. First step is to create a container element for the component to be rendered in and get hold of that container in component using `@ViewChild`.\n\n   ```html\n   \u003cng-container #someContainer\u003e\u003c/ng-container\u003e\n   ```\n\n   In your component:\n\n   ```js\n   @ViewChild('someContainer', {read: ViewContainerRef}) someContainer: ViewContainerRef;\n   ```\n\n2. Use `ComponentFactoryResolver` and `Injector` to create an instance of the component.\n\n   ```js\n   constructor(\n     private injector: Injector,\n     private cfr: ComponentFactoryResolver\n   ) {}\n   ```\n\n3. Use async-await to lazy load the component.\n\n   ```js\n   async lazyLoadComponent() {\n     const { LazyComponent } = await import('./lazy.component');\n     const componentFactory = this.cfr.resolveComponentFactory(LazyComponent);\n     const { instance } = this.someContainer.createComponent(componentFactory, null, this.injector);\n\n     // Use the instance to pass down values to LazyComponent like this:\n     instance.someProperty = 'dummy property';\n\n     // Get hold of emitted values from LazyComponent:\n     instance.someEmitter.pipe(\n       takeUntil(instance.destroy$)\n     ).subscribe(() =\u003e // Do something);\n   }\n   ```\n\n4. Sometimes you will need to import other modules (like `SharedModule`) to include some features in your component. We can create a dedicated module for the lazy loaded component and add it to the `lazy.component.ts` file.\n\n   ```js\n   @NgModule({\n     declarations: [LazyComponent],\n     imports: [CommonModule, SharedModule],\n   })\n\n   // Remove export statement to avoid accidental imports in other files.\n   class LazyCompModule {}\n   ```\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : \u003cbr /\u003e 1. Check out [Angular 9: Lazy Loading Components](https://johnpapa.net/angular-9-lazy-loading-components/) by [John Papa](https://github.com/johnpapa). \u003cbr /\u003e 2. Check out [Lazy load Angular components](https://medium.com/angular-in-depth/lazy-load-components-in-angular-596357ab05d8) by [Kevin Kreuzer](https://medium.com/@kevinkreuzer).\n\n\u003c/details\u003e\n\n### 9. Use ChangeDetectionStrategy.OnPush\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nAngular gives us an option to choose the `ChangeDetectionStrategy` of a component. By default, the value is `Default`. It's recommended to change that to `OnPush` strategy to maximise the performance :ok_hand:.\n\n#### Why?\n\nBy default, Angular run its change detection cycle on all the components whenever there occurs some changes, like a simple click event or when we recieve data from ajax calls. Running change detection cycle on every such events are costly and may affect the performance when the app grows.\n\n#### Solution:\n\nWe can minimize these checks by setting our component's `changeDetection` to `ChangeDetectionStrategy.OnPush`. This will tell Angular to run change detection cycle only when:\n\n1. The `Input` reference changes.\n2. Some event occurs in the component or any of the children.\n\n```js\n@Component({\n  selector: 'app-selector',\n  ...\n  changeDetection: ChangeDetectionStrategy.OnPush\n})\n```\n\n\u003cbr /\u003e\n\n\u003e :page_facing_up: **_Note_** : Make use of `detectChanges()` or `markForCheck()` functions of `ChangeDetectorRef` to explicitely run the change detection cycle if required.\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : Check out [🚀 A Comprehensive Guide to Angular onPush Change Detection Strategy](https://netbasal.com/a-comprehensive-guide-to-angular-onpush-change-detection-strategy-5bac493074a4) by [Netanel Basal](https://netbasal.com/@NetanelBasal).\n\n\u003c/details\u003e\n\n### 10. Disable change detection\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nIt is recommended to detach and reattach the change detector whenever required, for components where data changes happen frequently :wrench:.\n\n#### Why?\n\nRunning change detection cycle frequently when data changes occur constantly is very costly and can lead to performance issues :small_red_triangle_down:.\n\n#### Solution:\n\nUse the `detach()` method of `ChangeDetectorRef` to detach the change detector so that Angular won't run any change detection cycle unless you explicitely says to, by calling `reattach()` or `detectChanges()`. The `reattach()` method can be used to re attacch the change detector when some frequent complex calculations have been finished. The `detectChanges()` can be used to detect the changes once, whenever required.\n\n```js\nconstructor(private cdRef: ChangeDetectorRef) {\n  cdRef.detach();\n\n  // to check and update view every 5sec for a frequently changing component\n  // or use this.cdRef.reattach() when frequent complex calculations have been finished\n  setInterval(() =\u003e {\n    this.cdRef.detectChanges();\n  }, 5000);\n}\n```\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : Check out [Everything you need to know about change detection in Angular](https://indepth.dev/everything-you-need-to-know-about-change-detection-in-angular/) by [Max Koretskyi](https://indepth.dev/author/maxkoretskyi/).\n\n\u003c/details\u003e\n\n### 11. Run outside angular\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nAngular make use of `NgZone`, which is a wrapper for `Zone` APIs, to detect when to run change detection cycle. Zones wrap asynchronous browser APIs, and notifies when an asynchronous task has started or ended. Angular takes advantage of these APIs to get notified when any asynchronous task like xhr calls or any user events is done to run it's change detection mechanism :angel:. So it is recommended to use the `runOutsideAngular` method of the `NgZone` instance to minimize running change detection cycles.\n\n#### Why?\n\nFor the same reason in the above section - running change detection cycle frequently when data changes occur constantly is very costly and can lead to performance issues :small_red_triangle_down:.\n\n#### Solution:\n\nWe can run complex functions that don't necessarily require a change detection cycle to run (inorder to reflect something in the view) inside the callback of `runOutsideAngular()`.\n\n```js\nconstructor(private zone: NgZone) {\n}\n\nsomeComplexFunction() {\n  this.zone.runOutsideAngular(() =\u003e {\n    // your complex logic\n  });\n}\n```\n\n\u003cbr /\u003e\n\n\u003e :page_facing_up: **_Note_** : Make use of `run()` method to explicitely run the change detection cycle if required.\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : Check out [Using Zones in Angular for better performance](https://blog.thoughtram.io/angular/2017/02/21/using-zones-in-angular-for-better-performance.html) by [Pascal Precht](https://twitter.com/PascalPrecht).\n\n\u003c/details\u003e\n\n### Other performance optimisation techniques\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n#### 1. Add API caching mechanisms\n\nWhile most of the time it is, not all the API responses are dynamic. Sometimes some of the responses do not change often. We can store those values from the API by adding a caching mechanism and return that when subsequent calls to that APIs are made. In this way we can reduce the ajax calls and significantly improve the speed of our application as we don't have to wait for the network.\n\n\u003cbr /\u003e\n\n\u003e :bulb: **_Tip_** : Use [cashew](https://github.com/ngneat/cashew) 🐿, an awesome, flexible library that caches HTTP requests in Angular. Caching is nut a problem anymore :wink:!\n\n\u003cbr /\u003e\n\n#### 2. Use service workers\n\nMake use of service workers to cache our static assets(images, icons and fonts) and build artifacts(JS and CSS bundles). This can significantly improve the rendering time and make our application lightning fast :zap: by reducing the number of network requests needed. You can even make your application work when offline serving from the saved cache :beers:!\n\n\u003cbr /\u003e\n\nWe can make our application a Progressive Web App (PWA), by adding `@angular/pwa` package. Play with the generated `ngsw-config.json` to to define what and how to cache. With this feature, we can add our web application to our mobile phone's home screen and make our web app to look and feel like a native mobile application by adding application icons, splash screens etc. We can even release the application in Google Playstore just like any mobile application with [Trusted Web Activity](https://developers.google.com/web/android/trusted-web-activity) :scream: :scream:!\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : \u003cbr /\u003e 1. Check out [Getting started with service workers](https://angular.io/guide/service-worker-getting-started) in the official Angular docs. \u003cbr /\u003e 2. Check out [Angular Service Worker - Step-By-Step Guide for turning your Application into a PWA](https://blog.angular-university.io/angular-service-worker/) on [Angular University](https://blog.angular-university.io/). \u003cbr /\u003e 3. Check out [How to build Progressive Web Apps with Angular.](https://scotch.io/tutorials/how-to-build-progressive-web-apps-with-angular) by [Eniola Lucas](https://scotch.io/@enirate).\n\n\u003cbr /\u003e\n\n#### 3. App Shell\n\nWe can improve the user experience by quickly launching a static rendered page (a skeleton common to all pages) while the browser downloads the full client version and switches to it automatically after the code loads. This will significantly reduce the time for the first paint since the browser just need to render HTML and CSS without the need for initialize any Javascript. Such a cool feature :hushed:!\n\n\u003cbr /\u003e\n\nWe can make use of the Angular CLI to automatically generate an app shell for us with the command `ng generate app-shell`. Or thinking ahead, we can make use of Angular Universal to pre-render a static app shell :milky_way:. Do check out the resources to know more about it.\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : \u003cbr /\u003e 1. Check out [App shell](https://angular.io/guide/app-shell) in the official Angular docs. \u003cbr /\u003e 2. Check out [Angular App Shell - Boosting Application Startup Performance](https://blog.angular-university.io/angular-app-shell/) on [Angular University](https://blog.angular-university.io/).\n\n\u003cbr /\u003e\n\n#### 4. Web Workers\n\nBy default, our code usually runs in a single thread. This leaves behind a problem of unresponsive ui if some computationally intensive tasks are being performed. But thanks to Angular's support for web workers, we can run such tasks in another thread in the background without blocking our main execution thread :sun_with_face:. In huge and complex applications, we can even go to an extend where we run our entire application (including change detection) in a Web Worker and leave the main UI thread responsible only for rendering.\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : Check out [Web Workers in Angular](https://angular.io/guide/web-worker) in the official Angular docs.\n\n\u003cbr /\u003e\n\n#### 5. Web Assembly\n\n\u003e :warning: **_Warning_** : Although most of the modern browsers support web assembly, it's still in a premature state and might be unstable. So use at your own risk :grin:!\n\nIf someone wants to go the extra mile for performance, web assembly is for you! So what exactly is web assembly :confused:? In a nutshell, it is a low-level assembly-like language with a size- and load-time-efficient binary format which can run in near native speed. Okay, so what has it got to do with Javascript :no_mouth:?\n\nWebAssembly is designed to run alongside JavaScript — using the WebAssembly JavaScript APIs, you can load WebAssembly modules into a JavaScript app and share functionality between the two. Meaning, we can write our code in C/C++, Rust etc., compile it into a web assembly module and use it with our Angular application :boom:. In short, we can run our computationally intensive tasks in web assembly and make full use of it's lightning speed :sparkles:!\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : \u003cbr /\u003e 1. Check out [Web Assembly](https://developer.mozilla.org/en-US/docs/WebAssembly) in MDN. \u003cbr /\u003e 2. Check out [Examples of how to use WebAssembly within Angular](https://github.com/boyanio/angular-wasm) by [Boyan Mihaylov](https://github.com/boyanio). \u003cbr /\u003e 3. Check out [Using Web Assembly to speed up your Angular Application](https://malcoded.com/posts/web-assembly-angular/) by [Lukas Marx](https://twitter.com/malcoded).\n\n\u003c/details\u003e\n\n\u003c!-- Main details tag close --\u003e\n\u003c/details\u003e\n\n\u003cbr /\u003e\n\n\u003e :gift: **_Resources_** : \u003cbr /\u003e 1. Do check out this awesome repo : [angular-performance-checklist](https://github.com/mgechev/angular-performance-checklist) by [Minko Gechev](https://github.com/mgechev) and find out more pro performance tips :heart_eyes:. \u003cbr /\u003e 2. Check out [Best practices for a clean and performant Angular application](https://www.freecodecamp.org/news/best-practices-for-a-clean-and-performant-angular-application-288e7b39eb6f/) by [Vamsi Vempati](https://twitter.com/_VamsiVempati_). \u003cbr /\u003e 3. Check out [Optimizing the Performance of Your Angular Application](https://netbasal.com/optimizing-the-performance-of-your-angular-application-f222f1c16354) by [Netanel Basal](https://netbasal.com/@NetanelBasal). 4. Check out [15 Angular Performance Tips \u0026 Tricks](https://angular-guru.com/blog/angular-performance-tips) on [The Angular Guru](https://angular-guru.com/).\n\n\u003cbr /\u003e\n\n| :heart: _Takeaway_ :                                                                                                                                                                    |\n| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| 1. Make use of pure pipes to avoid function calls in templates                                                                                                                          |\n| 2. Use `trackBy` with `*ngFor` to minimize DOM manipulations by tracking array items with a unique identifier.                                                                          |\n| 3. Use `providedIn` attribute to make your services tree shakable.                                                                                                                      |\n| 4. Unsubscribe your observables to avoid memory leaks and use async pipe whenever possible to make Angular handle the subscriptions.                                                    |\n| 5. Lazy load modules and components to separate build bundles and load them on demand. Make use of preloading strategies to avoid possible latency while loading the lazy loaded chunk. |\n| 6. Use a combination of `ChangeDetectionStrategy.OnPush`, `ChangeDetectorRef` and `NgZone` methods to minimize the number of change detection cycles.                                   |\n| 7. Use service workers, app shell and api caching to further improve the performance.                                                                                                   |\n\n\u003cbr /\u003e\n\n🔝 [Back to Contents](#-table-of-contents)\n\n\u003cbr /\u003e\n\n\u003c!-- ROADMAP --\u003e\n\n## `Roadmap`\n\nSee the [open issues](https://github.com/github_username/repo/issues) for a list of proposed features (and known issues).\n\n\u003cbr /\u003e\n\n\u003c!-- CONTRIBUTING --\u003e\n\n## `Contributing`\n\nContributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.\n\n1. Fork the Project\n2. Create your Feature Branch (`git checkout -b docs/AmazingDoc`)\n3. Commit your Changes (`git commit -m 'Add some AmazingDoc'`)\n4. Push to the Branch (`git push origin docs/AmazingDoc`)\n5. Open a Pull Request\n\n\u003cbr /\u003e\n\n\u003c!-- LICENSE --\u003e\n\n## `License`\n\nDistributed under the MIT License. See `LICENSE` for more information.\n\n\u003c!-- CONTACT : TODO--\u003e\n\n\u003c!-- ACKNOWLEDGEMENTS : TODO --\u003e\n","projects_url":"https://awesome.ecosyste.ms/api/v1/lists/akhilben%2Fangular-awesome/projects"}