Opinionated Angular Setup

Kai Schönberger
Jan 24 · 11 min read
Image for post
Image for post
Photo by Marvin Meyer on Unsplash


This is my opinionated guide on how to set up a new Angular Project. Below, I described all of the steps that I usually take whenever I set-up a new Angular Project. This was originally meant to be a checklist for myself, but then I decided to write it down in the format of an article. I hope someone can benefit from this. If you are a newbie and just want to learn Angular, you should not care much about this setup. But if you want to set up a serious project and need to make some decision on e.g. testing, formatting, or ChangeDetection then this guide may be useful for you. I additionally tried to add some context and explain my decisions. If you are in a hurry just read the bullet points or jump right to the section you are interested in.

At the time of writing this post, the latest version was . I used this version to generate the project. Since the project structure changes sometimes, the below steps may vary a little bit depending on your CLI version. You can use your favorite editor and follow along with the steps. I used VS-Code with the plugins Angular Language Service, TSLint, Prettier, and SCSS Formatter. They are all optional and just a recommendation.

You can find the final result on my GitHub. Take a look at the commit history to see every single step as a granular commit.


  1. Generate a new Angular project
  2. Change Detection Default
  3. Think of a Component and Directive Prefix
  4. Setup Prettier
  5. Replace Karma/Jasmine with Jest
  6. Replace Protractor with Cypress
  7. Add PWA Features
  8. Add Angular Material (Optional)
  9. Use a System Font Stack (Optional)
  10. More Ideas

1. Generate a new Angular project

The first step we must take is to generate a new Angular project. This is usually done by using the CLI. If you haven’t done it yet, go to https://nodejs.org/en/ and install the LTS version. After doing this you should have the package manager NPM available. Open your favorite terminal and type . This will install the Angular CLI globally so that you can use the command everywhere. Run to check if everything went well. If it was already installed, you can use the same command to update to the newest version. Using the tool, we can now generate a new project. Navigate to the folder where you want to create the project. Type to generate a new project called . The CLI will now ask you a few questions. These are my preferred answers:

  • Strict type checking and stricter bundle budgets? -> Yes
  • Routing? -> Yes
  • Stylesheet format? -> SCSS

Everything can be changed later. Strict type checking is always a good idea to prevent any errors that may result from loose typing — like Null-Pointer and many others. It’s out of the scope of this post to discuss this topic. Routing is needed in almost every bigger SPA. You have to decide on your own if your SPA needs it or not. The last question is about the format of your Stylesheets. I prefer to write Scss since it is a superset of CSS, which is not the case for Sass. Choosing Scss over Less is just a personal preference. Choose whatever you are the most familiar with.

2. Change Detection Default

The following section is a bit more complicated to understand as a beginner. Basically, there are two Change Detection Strategies in Angular. One is called and the other is called . The default applies if you do not override the Change Detection at the Component level. If you take a look into an already generated Component e.g. , you see that there is no property inside the configuration of the Component Decorator.

Default Change Detection is a little bit easier to implement but is less performant. What this means is that every time Angular runs its Change Detection, all bindings are checked. This is costly and can become a bottleneck in more complex applications. What I prefer is always switching to On-Push. It is more performant since a Change Detection Cycle does only check the Bindings of Components that are marked as dirty. A Component will be marked as dirty when (a) an Input of the Component changes, (b) an event is emitted from this Component, (c) you use the Pipe inside the template or (d) you manually mark it as dirty. There are plenty of good posts about this topic out there. I really recommend you to conduct a quick Google Search and dive deeper into this topic if you are interested.

You can enable the Angular Debug Tools to profile how fast Angular runs a Change Detection Cycle with each of the strategies. You will see that there is a huge difference. The tradeoff is that you may have to write a little bit more code sometimes to run the Change Detection at the right moment. If you structure your code well in reactive style and leverage tools like RxJS and the AsyncPipe then your application will automatically be compatible with the OnPush strategy.

What we do now is set the OnPush strategy as default for the schematics. Every time you generate a new Component using the Change Detection will be set correctly.

  • Open the and add a property inside with the value
  • Refactor your to use the correct strategy.

3. Think of a Component and Directive Prefix

It’s suggested to use a prefix for all your components and directives. You can read more about the reasons inside the Angular coding style guide. There is a section about Component Prefix and Directive Prefix. The default prefix in our newly generated project is . Angular picks up this prefix when generating new components. To enforce this style there exists a custom tslint rule which comes with the package.

  • Open the and change the property to your own prefix.
  • Open the and replace with your own prefix inside the and rule configuration.
  • Refactor your to use the correct prefix. Don’t forget about the .

As TSLint is officially deprecated I assume that this section will change slightly in the future and TSLint will be replaced with ESLint.

4. Setup Prettier

TSLint already does a lot for us but it is not meant to be a full-fledged formatter. For that reason, it’s a good idea to add a formatter to enforce a consistent code style across all developers. Since the line between linting and formatting seems to be a little bit blurry, there are areas where the tools overlap. For example, both tools care about the maximum line length or quotes. This means that we need consistency in our configuration, otherwise the linter will complain if run after the formatter and vice-versa. I decided to use Prettier for formatting since it is widely adopted (12.148.717 weekly downloads on npm at the time of writing this post) and opinionated. Opinionated means that we do not have much to configure, which is great. I like the defaults and do not care much about how the formatting looks. My main goal is consistency. There are many different ways to configure Prettier. My preferred way is to put the configuration inside the .

  • Install the NPM package
  • Open the and add a key . Use the following config object:
  • For convenience add a script in your to apply the formatting:
  • And one to check the formatting: which is useful for the CI Pipeline.
  • To run it from your Editor, download the appropriate Editor Integration https://prettier.io/docs/en/editors.html

5. Replace Karma/Jasmine with Jest

Angular comes with a default framework for Unit-Testing. They use Karma as a Test Runner and Jasmine is the JavaScript Testing Framework they use for other things like assertions. Both are good tools that work well. However, I ultimately decided to use Jest. There are tons of good articles out there where you can read about Jest vs Karma. I made my decision because of two key reasons. First, Jest has a much bigger community around it. Since it comes from the React ecosystem, it is widely used and loved by millions. At the time of writing it has about ten million weekly downloads on NPM compared to less than two million for Karma. This is a huge benefit in my opinion especially when you browse the web for solutions to tricky problems. The other reason is its architecture. The architecture is fundamentally different compared to Karma. Jest uses jsdom to simulate the DOM instead of running a Browser like Karma. This improves performance and is in my opinion the right way to go. Jest is built on top of Jasmine, its API is mostly compatible. After following the below steps you can run the test we already have and it will work without any changes to the code.

  • Run to remove all Karma and Jasmine dependencies
  • Delete and
  • Open and remove the whole block.
  • Run to add all dependencies we need for Jest
  • Open and replace the types with
  • Add a file called in the project root directory with the following content
  • Add a file called in the project root directory and put the following code inside:
  • Inside the replace the old script with
  • Update the documentation inside the

If you want more details regarding what happened here, check out this excellent Blogpost for more information and useful tips.

6. Replace Protractor with Cypress

Angular’s default solution for End-to-End-Testing is Protractor. It is developed by the Angular Team. I am going to remove Protractor and replace it with Cypress. I suggest you search the web if you are looking for more information about the comparison of Protractor with Cypress. But again there are two main reasons why I prefer Cypress over Protractor. First, it has a big community and is very well maintained. They are pushing new releases and the Changelog is always huge, full of improvements, bug fixes, and new features. I started using it with version 3.3.0 and it has since then constantly getting better and more stable. The second reason is that the architecture is fundamentally different from Protractor. Cypress is executed in the same event loop as the application tested and that allows it to be much more stable and not as flaky as traditional E2E testing frameworks. To set up Cypress and remove Protractor we will use an awesome Schematics made available by Briebug.

  • Run and choose yes to remove Protractor.
  • Add and to your
  • Update the documentation inside the and
  • Run to verify that everything's working correctly

7. Add PWA Features

In Angular, there is this really nice Schematics to turn your application into a PWA with just one command. It creates a file, adds the necessary configuration to use Service Workers, and adds some dummy icons. Almost every application can benefit from Service Worker support. Your application does load faster now and you can use features like A2HS and show a Splash Screen.

  • Run

8. Add Angular Material (Optional)

In the next step, I want to add a component library. This step is totally optional, but in almost any project you choose some sort of UI library to speed up the development of your application. There are a lot of very good libraries out there like NG-ZORRO, PRIMENG, or ng-bootstrap. A more comprehensive list can be found in the official Angular Docs. Whenever possible I choose Angular Material Components. It’s a set of components for Angular that follows Google’s Material Design specification. The assortment of components is not the largest but they are all really high quality. I have personally used them a lot and have never experienced any issues. The following steps will be specific to this library. See the installation guide.

  • Run in the root of your project.
  • Q: Choosing a Theme -> Custom
  • Q: Setup global typography? -> Yes
  • Q: Setup browser animations? -> Yes

Of course, you can answer the question depending on your needs. I only wanted to give you the options I typically pick.

PERF TIP: Below I want to show two optimizations I typically apply to improve the application performance a bit. They may be considered to be “premature optimizations” so avoid them if you do not know that you need them.

  • Instead of including the whole theme , we can customize and only include the CSS for components that we want to use e.g.
@include mat-core-theme($theme);
@include mat-button-theme($theme);
@include mat-icon-theme($theme);
  • Instead of loading the whole icon font, I prefer to manually include the SVG’s of Icons that I use and embed them in the code. Remove the icon font include from the and register the SVG's in your . Take a look at the MatIconRegistry docs for more details.
export class AppModule {
constructor(iconRegistry: MatIconRegistry, sanitizer: DomSanitizer) {
<svg xmlns="http://www.w3.org/2000/svg">
<svg id="close" width="24" height="24" viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
<svg id="menu" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/></svg>

9. Use a System Font Stack (Optional)

If the design of your UI allows it, I prefer to use a System Font Stack. The main reason why I do this is that I avoid loading a font file and save a lot of bytes. Below, I will use the System Font Stack which is used by GitHub.com. The following steps are specific to Angular Material. If you have chosen a different component library there may be other ways to do it.

Define your custom typography and pass it as an argument to the include. That's it.

$custom-typography: mat-typography-config(
$font-family: "-apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji"
@include mat-core($custom-typography);

In the Angular Material docs, you can find more about typography customization.

10. More Ideas

These were the key steps I usually take when setting up a serious Angular project. Of course, you can also code right away and do any of these steps at a later point in time. Before I leave you alone to start coding, I want to give you a quick list of a few more things that came to my mind. These were topics I first wanted to include but then left out since I think they make less sense to set up right at the beginning of a project.

Thanks for Reading

I hope this post was at least a little bit useful for you. Please feel free to reach out with any questions, comments, or feedback.

Kai Schönberger, 2021/01/24

The Startup

Medium's largest active publication, followed by +771K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store