The document provides best practice guidelines for developing Angular applications from version 2 to 6. It covers topics such as file structure conventions, naming conventions, coding conventions, component guidelines, directives, services and more. The guidelines aim to promote consistency, readability and maintainability of Angular codebases.
2.
Table of contents
1. Introduction
2. Application Framework/Software Details
3. Angular Project Scaffolding and File Structure Guidelines
3.1 Project Bootstrap/Setup
3.2 File Naming Directory Structure Conventions
3.3 Single Responsibility
3.4 Naming
4. Coding Conventions Guidelines
4.1 Classes
4.2 Constants
4.3 Interfaces
4.4 Properties and methods
4.5 Import line spacing
4.6 Module
4.7 Feature modules
4.8 Shared feature module
4.9 Core feature module
4.10 Prevent re-import of the core module
4.11 Lazy Loaded folders
5. Angular Components
5.1 Component selector names
5.2 Components as elements
5.3 Extract templates and styles to their own files
5.4 Decorate input and output properties
5.5 Avoid aliasing inputs and outputs
5.6 Member sequence
5.7 Delegate complex component logic to services
5.8 Don't prefix output properties
5.9 Put presentation logic in the component class
6. Angular Directives
6.1 Use directives to enhance an element
6.2 HostListener/HostBinding decorators versus host metadata
7. Angular Services
7.1 Services are singletons
7.2 Single responsibility
7.3 Providing a service
7.4 Use the @Injectable() class decorator
8. Data Services
2
3. 8.1 Talk to the server through a service
9. Lifecycle hooks
10.Editor/IDE For Angular 2/4
11. Microsoft Typescript Guidelines
11.1 Names
11.2 Components as elements
11.3 Types
11.4 null and undefined
11.5 General Assumptions
11.6 Classes
11.7 Flags
11.8 Comments
11.9 Strings
11.10 Diagnostic Messages
11.11 Diagnostic Message Codes
11.12 General Constructs
11.13 Style
12.Prod/Dev Environment Variables
13.Generating and serving an Angular project
14.Best Practices for Handling External Libraries
15.Project version control
16.Deployment
17.External References
18.About Perfomatix
3
4. 1. Introduction
This document describes the best practice guidelines for developing UI components
using Angular 2 and 6
2. Application Framework/Software Details
Name Angular (commonly referred to as
"Angular 2+" or "Angular 2")
Type TypeScript, Single-page application
Framework
Developer(s) Google
Supported Platform Cross-platform,PWA, modern browsers
only
Initial Release 14 September 2016
Latest version 6.0.5 Stable
Typescript Version 2.9.0
Latest version Release Date 14 JUNE 2018
License MIT License
Website https://angular.io/
3.Angular Project Scaffolding and File Structure Guidelines
3.1 Project Bootstrap/Setup
- Install/Update NodeJS,Angular CLI to latest Stable/LTS version.
- Verify/Check installed CLI/Node JS version in locally and globally.
- Use Angular CLI to Create New Project without Git file and using Sass.
- Use Yarn to install dependency Packages.
- Check/Verify all installed packages Versions are Correct.
- Reinitialize Git.
- Update/Change Existing Git READ.md and changelog file.
- Commit initail project codes and verify the committed files.
4
5. Advantages of yarn package manager :
- You run npm install, and you get an error on the terminal, then you run the
same command again and the error is gone. This is sometimes caused by
proxies and network issues, but a lot of times it's not the case.
- you have a project running on on your machine in one folder, but you checkout
the code to another folder and install it there, and it's somehow not working
there due to dependencies issues.
- your production or staging environment build fails due to dependency related
errors that you don’t have on your local machine.
- Another developer working on the same project is running into dependencies
issues but on your machine it's working great: or the other way around.
- yarn will take packages from NpmJS or Bower registries, it also runs
dependency installs parallel to each other.
- A single request failing won't cause an install to fail. Requests are retried upon
failure.
3.2 File Naming Directory Structure Conventions
Some code examples display a file that has one or more similarly named companion
files. For example, hero.component.ts and hero.component.html.uses the shortcut
hero.component.ts|html|css|spec to represent those various files.
3.3 Single Responsibility
Apply the single responsibility principle (SRP) to all components, services, and other
symbols. This helps make the app cleaner, easier to read and maintain, and more
testable.
- Do define one thing, such as a service or component, per file.One component
per file makes it far easier to read, maintain, and avoid collisions with teams in
source control.That file avoids hidden bugs that often arise when combining
components in a file where they may share variables, create unwanted
closures, or unwanted coupling with dependencies.
- Consider limiting files to 400 lines of code.The key is to make the code more
reusable, easier to read, and less mistake prone.
- Consider limiting to no more than 75 lines for small functions because they are
easier to test, especially when they do one thing and serve one purpose.Small
functions help avoid hidden bugs that come with large functions that share
variables with external scope, create unwanted closures, or unwanted coupling
with dependencies.
5
6.
3.4 Naming
3.4.1 General Naming Guidelines
- Do use consistent names for all symbols: Naming conventions help provide a
consistent way to find content at a glance. Consistency within the project is
vital. Consistency with a team is important. Consistency across a company
provides tremendous efficiency.
- Do follow a pattern that describes the symbol's feature then its type. The
recommended pattern is feature.type.ts.The naming conventions should
simply help find desired code faster and make it easier to understand.Names
of folders and files should clearly convey their intent. For example,
app/heroes/hero-list.component.ts
3.4.2 Separate file names with dots and dashes
- Do use dashes to separate words in the descriptive name. for example,
home-list.ts
- Do use dots to separate the descriptive name from the type.Type names
provide a consistent way to quickly identify what is in the file.
- Do use consistent type names for all components following a pattern that
describes the component's feature then its type. A recommended pattern is
feature.type.ts.
- Do use conventional type names including .service, .component, .pipe, .module,
and .directive. Invent additional type names if you must but take care not to
create too many.
3.4.3 Symbols and file names
- Do use consistent names for all assets named after what they represent.
- Do use upper camel case for class names.
- Do match the name of the symbol to the name of the file.
- Do append the symbol name with the conventional suffix (such as Component,
Directive, Module, Pipe, or Service) for a thing of that type.
- Do give the filename the conventional suffix (such as .component.ts,
.directive.ts, .module.ts, .pipe.ts, or .service.ts) for a file of that type.
3.4.4 Service names
- Do use consistent names for all services named after their feature.Provides a
consistent way to quickly identify and reference services.
- Do suffix a service class name with Service. For example, something that gets
6
7. data or heroes should be called a DataService or a HeroService.
3.4.5 Bootstrapping
- Do put bootstrapping and platform logic for the app in a file named main.ts.
- Do include error handling in the bootstrapping logic and follows a consistent
convention for the startup logic of an app.
- Avoid putting app logic in main.ts. Instead, consider placing it in a component
or service.
3.4.6 Directive selectors
- Do Use lowercamelcase for naming the selectors of directives because it keeps
the names of the properties defined in the directives that are bound to the
view consistent with the attribute names.Also the Angular HTML parser is case
sensitive and recognizes lower camelcase.
3.4.7 Custom prefix for components
- Do use a hyphenated, lowercase element selector value (e.g. admin-users)
because its prevents element name collisions with components in other apps
and with native HTML elements.
- Do use a custom prefix for a component selector. For example, the prefix toh
represents from Tour of Heroes and the prefix admin represents an admin
feature area this will make it easier to promote and share the component in
other apps and also components are easy to identify in the DOM.
3.4.8 Custom prefix for directives
- Do use a custom prefix for the selector of directives (e.g, the prefix toh from
Tour of Heroes).
- Do spell non-element selectors in lower camelcase unless the selector is meant
to match a native HTML attribute.
3.4.9 Pipe names
- Do use consistent names for all pipes, named after their feature because it
provides a consistent way to quickly identify and reference pipes
3.4.10 Unit test file names
- Unit test file names: Do name test specification files the same as the
component they test.Do name test specification files with a suffix of .spec.
7
8. 3.4.11 Angular NgModule names
- Do append the symbol name with the suffix Module because it provides a
consistent way to quickly identify and reference modules
- Do give the file name the .module.ts extension.Upper camel case is
conventional for identifying objects that can be instantiated using a
constructor.
- Do name the module after the feature and folder it resides in.
- Do suffix a RoutingModule class name with RoutingModule.
- Do end the filename of a RoutingModule with -routing.module.ts.
4.Coding Conventions Guidelines
4.1 Classes
- Do use upper camel case when naming classes.Classes can be instantiated and
construct an instance. By convention, upper camel case indicates a
constructible asset.
4.2 Constants
- Do declare variables with const if their values should not change during the
application lifetime.
- Consider spelling const variables in lowercamelcase.The tradition of naming
constants in UPPER_SNAKE_CASE reflects an era before the modern IDEs that
quickly reveal the const declaration. TypeScript prevents accidental
reassignment.
- Do tolerate existing const variables that are spelled in UPPER_SNAKE_CASE.The
tradition of UPPER_SNAKE_CASE remains popular and pervasive, especially in
third party modules
4.3 Interfaces
- Do name an interface using upper camel case.
4.4 Properties and methods
- Do use lower camel case to name properties and methods.
- Avoid prefixing private properties and methods with an underscore.
4.5 Import line spacing
- Consider leaving one empty line between third party imports and application
imports.
- Consider listing import lines alphabetized by the module.
8
9. - Consider listing destructured imported symbols alphabetically.
4.6 Module
- Do create an NgModule in the app's root folder, for example, in /src/app.
- Consider naming the root module app.module.ts
4.7 Feature modules
- Do create an NgModule for all distinct features in an application; for example, a
Heroes feature.
- Do place the feature module in the same named folder as the feature area; for
example, in app/heroes.
- Do name the feature module file reflecting the name of the feature area and
folder; for example, app/heroes/heroes.module.ts.
- Do name the feature module symbol reflecting the name of the feature area,
folder, and file; for example, app/heroes/heroes.module.ts defines
HeroesModule.
4.8 Shared feature module
- Do create a feature module named SharedModule in a shared folder; for
example, app/shared/shared.module.ts defines SharedModule.
- Do declare components, directives, and pipes in a shared module when those
items will be re-used and referenced by the components declared in other
feature modules.
- Consider using the name SharedModule when the contents of a shared module
are referenced across the entire application.
- Avoid providing services in shared modules. Services are usually singletons that
are provided once for the entire application or in a particular feature module.
- Do import all modules required by the assets in the SharedModule; for
example, CommonModule and FormsModule
- Do declare all components, directives, and pipes in the SharedModule.
- Do export all symbols from the SharedModule that other feature modules
need to use.
- Avoid specifying app-wide singleton providers in a SharedModule. Intentional
singletons are OK.
4.9 Core feature module
- Consider collecting numerous, auxiliary, single-use classes inside a core
module to simplify the apparent structure of a feature module.
- Consider calling the application-wide core module, CoreModule. Importing
9
10. CoreModule into the root AppModule reduces its complexity and emphasizes
its role as orchestrator of the application as a whole.
- Do create a feature module named CoreModule in a core folder (e.g.
app/core/core.module.ts defines CoreModule).
- Do put a singleton service whose instance will be shared throughout the
application in the CoreModule (e.g. ExceptionService and LoggerService).
- Do import all modules required by the assets in the CoreModule (e.g.
CommonModule and FormsModule).
- Do gather application-wide, single use components in the CoreModule. Import
it once (in the AppModule) when the app starts and never import it anywhere
else. (e.g. NavComponent and SpinnerComponent).
- Avoid importing the CoreModule anywhere except in the AppModule.
- Do export all symbols from the CoreModule that the AppModule will import
and make available for other feature modules to use.
4.10 Prevent re-import of the core module
- Only the root AppModule should import the CoreModule.
- Do guard against re-importing of CoreModule and fail fast by adding guard
logic.
4.11 Lazy Loaded folders
- A distinct application feature or workflow may be lazy loaded or loaded on
demand rather than when the application starts.
- Do put the contents of lazy loaded features in a lazy loaded folder. A typical
lazy loaded folder contains a routing component, its child components, and
their related assets and modules.
- Avoid allowing modules in sibling and parent folders to directly import a
module in a lazy loaded feature.
5. Angular Components
5.1 Component selector names
- Do use dashed-case or kebab-case for naming the element selectors of
components because it will Keeps the element names consistent with the
specification for Custom Elements.
5.2 Components as elements
- Do give components an element selector, as opposed to attribute or class
selectors because components have templates containing HTML and optional
Angular template syntax. They display content. Developers place components
10
11. on the page as they would native HTML elements and web components.It is
easier to recognize that a symbol is a component by looking at the template's
html.
5.3 Extract templates and styles to their own files
- Do extract templates and styles into a separate file, when more than 3 lines.
- Do name the template file [component-name].component.html, where
[component-name] is the component name.
- Do name the style file [component-name].component.css, where
[component-name] is the component name.
- Do specify component-relative URLs, prefixed with ./. Large, inline templates
and styles obscure the component's purpose and implementation, reducing
readability and maintainability. In most editors, syntax hints and code snippets
aren't available when developing inline templates and styles. The Angular
TypeScript Language Service (forthcoming) promises to overcome this
deficiency for HTML templates in those editors that support it; it won't help
with CSS styles.The ./ prefix is standard syntax for relative URLs; don't depend
on Angular's current ability to do without that prefix.
5.4 Decorate input and output properties
- Do use the @Input() and @Output() class decorators instead of the inputs and
outputs properties of the@Directive and @Component metadata.
- Consider placing @Input() or @Output() on the same line as the property it
decorates because It is easier and more readable to identify which properties
in a class are inputs or outputs. If you ever need to rename the property or
event name associated with @Input or @Output, you can modify it in a single
place.
- The metadata declaration attached to the directive is shorter and thus more
readable.
- Placing the decorator on the same line usually makes for shorter code and still
easily identifies the property as an input or output. Put it on the line above
when doing so is clearly more readable.
5.5 Avoid aliasing inputs and outputs
- Avoid input and output aliases except when it serves an important purpose
because Two names for the same property (one private, one public) is
inherently confusing.
- You should use an alias when the directive name is also an input property, and
the directive name doesn't describe the property.
5.6 Member sequence
11
12. - Do place properties up top followed by methods.
- Do place private members after public members, alphabetized because placing
members in a consistent sequence makes it easy to read and helps instantly
identify which members of the component serve which purpose.
5.7 Delegate complex component logic to services
- Do limit logic in a component to only that required for the view. All other logic
should be delegated to services.
- Do move reusable logic to services and keep components simple and focused
on their intended purpose. Because logic may be reused by multiple
components when placed within a service and exposed via a function. Logic in
a service can more easily be isolated in a unit test, while the calling logic in the
component can be easily mocked.
- Removes dependencies and hides implementation details from the
component.
- Keeps the component slim, trim, and focused.
5.8 Don't prefix output properties
- Do name events without the prefix on.
- Do name event handler methods with the prefix on followed by the event
name,Because Angular allows for an alternative syntax on-*. If the event itself
was prefixed with on this would result in an on-onEvent binding expression.
5.9 Put presentation logic in the component class
- Do put presentation logic in the component class, and not in the template
because logic will be contained in one place (the component class) instead of
being spread in two places.Also it is Keeping the component's presentation
logic in the class instead of the template improves testability, maintainability,
and reusability.
6 Directives
6.1 Use directives to enhance an element
- Do use attribute directives when you have presentation logic without a
template.Attribute directives don't have an associated template.
6.2 HostListener/HostBinding decorators versus host metadata
- Consider preferring the @HostListener and @HostBinding to the host property
of the @Directive and @Component decorators.
- Do be consistent in your choice because the property associated with
12
13. @HostBinding or the method associated with @HostListener can be modified
only in a single place—in the directive's class. If you use the host metadata
property, you must modify both the property declaration inside the controller,
and the metadata associated with the directive.
7. Services
7.1 Services are singletons
- Do use services as singletons within the same injector. Use them for sharing
data and functionality because services are ideal for sharing methods across a
feature area or an app.Also Services are ideal for sharing stateful in-memory
data.
7.2 Single responsibility
- Do create services with a single responsibility that is encapsulated by its
context because when a service has multiple responsibilities, it becomes
difficult to test,every component or service that injects it now carries the weight
of them all.
- Do create a new service once the service begins to exceed that singular
purpose.
7.3 Providing a service
- Do provide services to the Angular injector at the top-most component where
they will be shared.When providing the service to a top level component, that
instance is shared and available to all child components of that top level
component. This is ideal when a service is sharing methods or state and this is
not ideal when two different components need different instances of a service.
In this scenario it would be better to provide the service at the component level
that needs the new and separate instance.
7.4 Use the @Injectable() class decorator
- Do use the @Injectable() class decorator instead of the @Inject parameter
decorator when using types as tokens for the dependencies of a service. The
Angular Dependency Injection (DI) mechanism resolves a service's own
dependencies based on the declared types of that service's constructor
parameters.When a service accepts only dependencies associated with type
tokens, the @Injectable() syntax is much less verbose compared to using
@Inject() on each individual constructor parameter.
13
14. 8. Data Services
8.1 Talk to the server through a service
- Do refactor logic for making data operations and interacting with data to a
service.
- Do make data services responsible for XHR calls, local storage, stashing in
memory, or any other data operations.The component's responsibility is for
the presentation and gathering of information for the view. It should not care
how it gets the data, just that it knows who to ask for it. Separating the data
services moves the logic on how to get it to the data service, and lets the
component be simpler and more focused on the view.This makes it easier to
test (mock or real) the data calls when testing a component that uses a data
service. The details of data management, such as headers, HTTP methods,
caching, error handling, and retry logic, are irrelevant to components and other
data consumers.A data service encapsulates these details. It's easier to evolve
these details inside the service without affecting its consumers. And it's easier
to test the consumers with mock service implementations.
9.Lifecycle hooks
- Do implement the lifecycle hook interface because lifecycle interfaces prescribe
typed method signatures. use those signatures to flag spelling and syntax
mistakes.
10.Editor/IDE For Angular 2/4
- Do use codelyzer to follow the angular Style guide/best practices.
- Do use file templates or snippets to help follow consistent styles and patterns.
Here are templates and/or snippets for some of the web development editors
and IDEs.
- Consider using snippets for Visual Studio Code that follow these styles and
guidelines.
- Consider using snippets for Atom that follow these styles and guidelines.
11.Microsoft Typescript Guidelines
11.1 Names
- Use PascalCase for type names.
- Do not use "I" as a prefix for interface names.
- Use PascalCase for enum values.
- Use camelCase for function names.
14
15. - Use camelCase for property names and local variables.
- Do not use "_" as a prefix for private properties.
- Use whole words in names when possible.
11.2 Components
- 1 file per logical component (e.g. parser, scanner, emitter, checker).
- files with ".generated.*" suffix are auto-generated, do not hand-edit them.
11.3 Types
- Do not export types/functions unless you need to share it across multiple
components.
- Do not introduce new types/values to the global namespace.
- Shared types should be defined in 'types.ts'.
- Within a file, type definitions should come first.
11.4 null and undefined
- Use undefined. Do not use null.
11.5 General Assumptions
- Consider objects like Nodes, Symbols, etc. as immutable outside the
component that created them. Do not change them.
- Consider arrays as immutable by default after creation.
11.6 Classes
- For consistency, do not use classes in the core compiler pipeline. Use function
closures instead.
11.7 Flags
- More than 2 related Boolean properties on a type should be turned into a flag.
11.8 Comments
- Use JSDoc style comments for functions, interfaces, enums, and classes.
11.9 Strings
- Use double quotes for strings.
- All strings visible to the user need to be localized (make an entry in
15
16. diagnosticMessages.json).
11.10 Diagnostic Messages
- Use a period at the end of a sentence.
- Use indefinite articles for indefinite entities.
- Definite entities should be named (this is for a variable name, type name, etc..).
- When stating a rule, the subject should be in the singular (e.g. "An external
module cannot..." instead of "External modules cannot...").
- Use present tense.
11.11 Diagnostic Message Codes
Diagnostics are categorized into general ranges. If adding a new diagnostic message,
use the first integral number greater than the last used number in the appropriate
range.
- 1000 range for syntactic messages
- 2000 for semantic messages
- 4000 for declaration emit messages
- 5000 for compiler options messages
- 6000 for command line compiler messages
- 7000 for noImplicitAny messages
11.12 General Constructs
- Do not use ECMAScript 5 functions; instead use those found in core.ts.
- Do not use for..in statements; instead, use ts.forEach, ts.forEachKey and
ts.forEachValue. Be aware of their slightly different semantics.
- Try to use ts.forEach, ts.map, and ts.filter instead of loops when it is not
strongly inconvenient.
11.13 Style
- Use arrow functions over anonymous function expressions.
- Only surround arrow function parameters when necessary.
- For example, (x) => x + x is wrong but the following are correct:
○ x => x + x
○ (x,y) => x + y
○ <T>(x: T, y: T) => x === y
- Always surround loop and conditional bodies with curly braces. Statements on
the same line are allowed to omit braces.
- Open curly braces always go on the same line as whatever necessitates them.
- Parenthesized constructs should have no surrounding whitespace.
- A single space follows commas, colons, and semicolons in those constructs. For
16
17. example:
○ for (var i = 0, n = str.length; i < 10; i++) { }
○ if (x < 10) { }
○ function f(x: number, y: string): void { }
- Use a single declaration per variable statement
- (i.e. use var x = 1; var y = 2; over var x = 1, y = 2;).
- else goes on a separate line from the closing curly brace.
- Use 4 spaces per indentation.
12. Prod/Dev Environment Variables
- Use environment.ts file to store development environment variable.
- use environment.prod.ts file to store production environment variable.
13. Generating and serving an Angular project
- Use angular Cli command to Generate components, routes, services and
pipes.
- Use angular Cli command to serve the angular project.
- use Ahead-of-Time Compilation to generate production build.
14. Best Practices for Handling External Libraries
- Use MIT licensed in packages.
- Use AOT compilation supported packages
15. Project version control (GIT)
- Create Branch from master for every new features and bug fixes.
- Update application version number using NPM and Tag your Application for
the stable release of the project.
- Use standard branch naming convention rule for creating new branch.
Branch naming conventions:
1. Use grouping tokens (words) at the beginning of your branch names.
2. Define and use short lead tokens to differentiate branches in a way that is
meaningful to your workflow.
3. Use hyphen to separate parts of your branch names.
4. Do not use forward slash (/) to separate parts of your branch names
5. Do not use bare numbers as leading parts.
6. Avoid long descriptive names for long-lived branches.
7. Create release note in git after each release.
17
18. 16. Deployment
- Remove All console.log and debuggers from Projects files
- Enable Angular Production Mode before taking build.
- Use AOT compilation build.
17. External References
https://angular.io/guide/aot-compiler
https://angular.io/guide/styleguide
https://wikipedia.org/wiki/Single_responsibility_principle
https://docs.npmjs.com/cli/version
https://stackoverflow.com/questions/273695/git-branch-naming-best-practices
https://cli.angular.io/
https://medium.com/beautiful-angular/angular-2-and-environment-variables-5
9c57ba643be
https://github.com/johnpapa/angular-styleguide/blob/master/a2/README.md
https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines
https://blog.angular-university.io/getting-started-with-angular-setup-a-develop
ment-environment-with-yarn-the-angular-cli-setup-an-ide/
https://gist.github.com/digitaljhelms/4287848
https://code.visualstudio.com/?wt.mc_id=vscom_downloads
https://www.npmjs.com/package/codelyzer
https://medium.com/@tomastrajan/6-best-practices-pro-tips-for-angular-cli-bet
ter-developer-experience-7b328bc9db81
https://gist.github.com/revett/88ee5abf5a9a097b4c88
18