Angular’s new component structure

With all the new features coming in Angular, the structure of the component (which are the building blocks of an Angular app) is, in my opinion, changing from what it use to be.

Before the introduction of standalone components and Signals, a typical Angular component would be made up of:

  • A TypeScript file
  • A HTML template
  • A CSS/SCSS file

Each part of the component, nicely separated in it’s own file and each component belonging to it’s own module. This approach has worked for many projects and is still used in a lot of Angular projects. It’s great, but things have moved on. More modern web frameworks have taken a slightly different route and the Angular team have worked hard on giving Angular developers the option to write their apps using this new, modern approach.

So from Angular 15+ the Standalone component was introduced, allowing us as Angular developers to create components like this:

import { Component } from '@angular/core';
import { RouterLink } from '@angular/router';

@Component({
  selector: 'app-home-page',
  standalone: true,
  imports: [RouterLink],
  templateUrl: './home-page.component.html',
  styles: ``,
  template: `<h1 class="text-3xl font-bold underline">Hello world!</h1>
    <button
      [routerLink]="['/contact']"
      routerLinkActive="router-link-active"
      class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
    >
      Add User
    </button>`,
})
export class HomePageComponent {}

In this example, we have everything in the single file. The TypeScript code, though not much of it here, the HTML template and a place for the styles. Also any imports are clearly listed in the imports array, everything is just there. Easy to see and read what is happening in this component.

Comparing with Vue

Not only have I worked on Angular projects, I’ve also spent sometime working with VueJS which is a fantastic framework, with a lot of great features and support.

One thing I did like about Vue was it’s approach to single file components, which at the time were not part of Angular. This is how a Vue component looks:

<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router'
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
  <header>
    <img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />

    <div class="wrapper">
      <HelloWorld msg="You did it!" />

      <nav>
        <RouterLink to="/">Home</RouterLink>
        <RouterLink to="/about">About</RouterLink>
      </nav>
    </div>
  </header>

  <RouterView />
</template>

<style scoped>
header {
  line-height: 1.5;
  max-height: 100vh;
}
</style>

Again everything is in the single file and clear to see. I like how in the Vue version the parts of the component are separated into <script>, <template> and <style> sections, making it easier to see the different parts of the component (this is great if your component has a lot of HTML or TypeScript code).

After working with Vue for a bit and enjoying the single file component structure, when I came back to working on an Angular project I missed the simplicity of the SFC (single file component) that Vue uses. But now with SFC components part of the new Angular I think we will start to see more and more Angular projects take advantage of the SFC architecture.

What are the advantages of the SFC approach

As I see it there are a few advantages to the SFC approach that as Angular developers we can now take advantage of, they include:

  • Easier to read code – now with everything in one file it’s easier to get a complete picture of what the component does and how it works. Ideal for when you are taking over an existing project.
  • Easier to maintain – the code for the component is there in one file, changes are easier to keep track of and refactor when in one file rather than jumping between multiple files
  • It’s easier to explain the code base to another developer – going through the code component by component makes it easier to explain how an application works, rather than going through multiple files trying to explain how the app works.
  • It is easier to test – with modules not being such a core part of Angular now, testing and the mocking for tests are more straight forward to write. Removing a lot of the negative reasons why tests are not written. With less to mock it’s easier to write tests and so there is no reason not to write them.

SFC allow cross framework understanding

One of the main advantages I see to SFC’s is it allows developers from other frameworks to pick up Angular easier – before SFC if you showed a React developer or a Vue developer the codebase of an Angular application it can be overwhelming with the amount of files and listing that this TypeScript file belongs with that HTML file. Now a developer with experience of either React or Vue can understand and relate to this new approach in an Angular project. Also the opposite applies, as an Angular developer who has worked with this SFC architecture when I see a Vue or React code base I find it far easier to relate back to what I already know when looking at the code. I think this will mean that as web developers we can work on multiple projects no matter what the framework used, with SFC the architecture is similar in all cases and we all know HTML, CSS and JavaScript which are the building blocks for all web frameworks.

Thinking of converting your Angular app to use SFC

If you, or your company needs help converting your Angular project to using the new SFC architecture feel free to contact me I can help upgrade your Angular apps to use this new architecture.

Update your package.json file for better tests

By default Angular gives you a couple of commands to run:

npm run start
npm run build
npm run watch
npm run test

These commands get you up and running, you can run the app in the browser, build the final version and run tests in run once.

I like to add a few more commands to my package.json file, these extra ones are:

npm run test:watch
npm run test:coverage
npm run test:ci
npm run lint

These commands give me more options for running my tests, in watch mode, with code coverage and in both watch mode with code coverage. There is also a linting check, which is always helpful for code quality checks.

The full commands in package.json look like this:

"test:watch": "ng test --watch",
"test:coverage": "ng test --code-coverage",
"lint": "ng lint",
"test:ci": "ng test --watch=true --browsers=ChromeHeadless --code-coverage"

Out of all four new commands the most essential one is the test:ci one, which runs my tests in headless mode (which is great as I don’t want to have the Karma runner opening the browser all the time) gives me an overview of all the code covered by tests.

While something like NX will give you more options and use Jest, being able to run these commands in a Angular CLI based project does make running tests easier leaving no reason not to write tests.

Contractor Chronicles 2

This week, carried on with existing client work. Fixing bugs on a complex Angular application that has been worked on by a number of others developers over the years. So it’s always interesting to take something written by someone else, work out how it works and then fix issues without making more bugs. This is a whole topic on its own, which I might write about

Also spent time looking into TypeScript libraries with the aim to work on some open-source development as a way to improve my TypeScript. I’ve been looking at TypeScript-ESlint, the linting library for TypeScript, a great project run by Josh Goldberg Its aim is to add support for ESLint to your TypeScript code. It will check your code for issues and bad practices and warn you of these issues.

Another thing that happen was there was a new budget in the UK, nothing really helpful for small business owners like myself just more ways of taxing people and trying to encourage people who have retired back to work (if I had retired and was playing golf every day I don’t think I’d be keen to go back to work).

The plan for next week is, to continue exploring open-source TypeScript development, working on client work and preparing for the next tax year.

Using third party libraries are useful as long as they are maintained

There’s no denying that the open-source movement has helped move web development forward. Before open source was so prevalent on the web everything had to be built from scratch, there was no searching on NPM for a library that could help fix an issue you had or a framework to structure your application.
But one of the downsides I see with using third-party libraries in your application is if this library is no longer maintained or updated and your work relies heavily on this library it can easily become a maintenance nightmare.

I’ve worked on a few Angular apps now and many are using third-party libraries every time a new version of Angular is released I have to check if these libraries work with the latest version, which on the whole they do. But if one of these libraries is no longer maintained or worked on, then you are stuck with the choice of either not upgrading your Angular version (something I don’t recommend) or refactoring your code to remove this dependency (something I do recommend).

So when it comes to adding third-party libraries to our codebase we need to make a few decisions. First, is it regularly maintained? Checking the history of the library on GitHub can answer that. If there have been no updates within the last year I get worried. Second, if it is maintained how crucial is this library going to be in my application? If it’s core to how the app works how would I maintain the app if later this library is no longer updated? Will it break my application? Can I easily refactor my code to remove this dependency if I need to? These are all questions that need to be considered before just adding a library.

One tip I have used is if you are using a third-party library or component in your application to wrap it within your own library or component then use this ‘wrapper’ throughout your codebase. So if you need to remove the outdated component/library all you need to do is refactor your ‘wrapper’ to either use another third-party library/component or your own version.

Open source is fantastic, it provides so much but I think that in large-scale applications we need to be defensive in how we use open-source code. Third-party libraries are created by some excellent and hardworking developers, many of whom do this work on top of their own, so I think we should be thankful for their work, but just be aware of how much we are using these libraries.

Writing good Pull Request descriptions

As developers, we like to get work done quickly. There is a feeling that if we finish fixing an issue or completing an issue as quickly as we can, then is obvious to the other team members, who may not be developers, that we are good at what we do because we get things done quickly.
This is dangerous, it can lead to bad practices slipping into your teams’ processes, where developers are trying to cut corners and get that Pull Request (where a developer asks the rest of the team to ‘pull’ their code into the main codebase of an app) ready as soon as possible.
One area where this cutting corners can happen is in PR (Pull Request) description messages, where the developer explains what this PR is about. If this is not completed then all the other member of the team who is reviewing the PR (where a second developer looks at the code changes made, and checks for any problems or can suggest ways that something might be done in a more efficient way), this second developer will just be shown a list of files, with the code changes highlighted.
From that, they need to work out what this PR is trying to either fix or add to the app’s codebase. Usually, without this context, the second developer will look at the changes, and think ‘well the syntax of the code looks fine, there are no obvious problems with how it’s written, I’ll Approve it’. Then this new PR is added to your app’s codebase, it all works and everything is fine.
But a few weeks later your users are complaining that the app has a strange issue when they use it. So you ask your developers to look into the cause of the problem. It could be due to something that has gone in the latest version of the app. So as any good developer should, they look through all the PR’s that went into that last release of the app.
This is where having a good description of what was done for a PR is so important. Yes, you can find a branch number that matches the list of the branches of code that went into a release, but if there is no description or no context of what work was completed as part of the PR, then it all becomes a guessing game.

So what goes into a good description?

There are a couple of things I think should go in a PR description:
1. Ticket number and title
2. A brief explanation of work completed
3. Bullet list of changes made

Adding a Ticket Number and Title

The title of a PR can have a lot of different variations, I’ve seen some places where the title is used to show a log of the changes made. From the PR’s in a release a log showing all the titles was used to show a report of what went into a release. This is helpful, but it meant that all the PR titles needed to be in a certain format and this format wasn’t particularly reading for humans.
Having the title of the ticket and the title number in the description as the first line makes it possible for a developer to see what was the corresponding ticket (if we’re using Jira) and what the name of the ticket was. Then the developer can search for that ticket and get an overview of what the PR was trying to do.

A brief explanation of work carried out

Next, I would add a brief, a few paragraphs, not an essay, an explanation of what work was carried out, what was added or fixed and how this was done. So someone could read this and get a sense of what was completed in the PR.
This doesn’t have to be too much, just enough so anyone knows what work was carried out.
A description is not only useful to other developers who may have to work on an old PR but also the original developer, to remind them of what they did for the PR.

Bullet list of changes

This is where you just list the changes you made. Maybe list each amended or new file and list what changes were made. Something like:

  1. Add new sort function to account service
  2. Removed commented out code from the interface
  3. Add unit test for main login service

Along with the title, brief description and bullet list of changes it is clear what went into a PR. Making it easier for developers in a team to be able to see what went into a PR.

Some developers in your team might say that this is a was of time, and if you need an explanation of what some code does then it’s not well-written code, but I think that’s laziness on the developers’ side. No one’s code is that easy to read, especially after a few months. Having your developers follow the good practice of adding a description to any PR they make will no doubt help the team. The more the team know what’s been added to the code base the quicker a fix for an issue with an app can be fixed, the faster the fixed app can be released to your users.

If your team aren’t using descriptions in their Pull Request’s then maybe its time to ask them why, and if they say it takes to long then make sure this effort is included in the estimates they give. It’s work the time in the long run.

When enough is enough,

There is a time when writing code that you need to say to yourself, enough is enough. I’m not talking about giving up coding, what I’m talking about is when you’ve been adding so many features to a section, that the code is unmanageable. There is a point where cramming in another feature to a section, means that the code behind will need to be re-written in order to make it easier to read, easier to manage and easier to test.

One of the big problems with AnglarJS, when it first became popular was developers didn’t know the best practices for how to write good clean AngularJS applications. The main problem was with the controller. The controller is a great concept, having a JavaScript file that sits behind your HTML template, which has access to all the elements in the template was amazing, but soon developers started to go crazy writing everything in one controller, at the time there wasn’t a ‘style guide’ that showed us a better way. Slowly over time, better practices were shared in the community, there were more examples of how to structure our AngularJS apps.

Recently I’ve had to work with an AngularJS project that has a controller where the structure of the controller has become unmanageable. Currently, the file has over 1200 lines of code, it is full of functions all doing different things, nothing grouped together in a logical structure, the use of both $scope and VM models is throughout the file instead of using one approach consistently. It is hard to work with this controller, and it is important of the functionality of the application.

Now I can see how this controller has gotten into this situation. It’s clear that at the beginning of the development this core piece of functionality that the controller manages was not fully planned. So the developer probably thought, this section doesn’t have a great deal of functionality I can keep it all within one controller.
Soon the features for this section grew and became more and more complex, the demand to get them delivered also grew, so the time for refactoring was not available. Now we are in a situation when we have a 1200 line controller that is hard to work with, nearly impossible to add new features too and is still buggy.

In order to stop this type of situation, developers need to be able to say to the PMs and stakeholders of a project, that they need to spend some time, refactoring the existing code in order to make it so new features can be added easily.

When a team successfully uses Scrum there is this time to raise issues like this, to let the PMs know that a bit of time is needed in order to tidy up the code before tackling a new feature. As part of the standard sprint planning, this can be raised. Without it the team just keep ploughing on building onto of existing code, adding feature after feature until everything is nearly unmanageable.

So what can developers and teams do in order to stop this happening:

  • Have regular sprint planning meetings to discuss the work coming up and not keep ploughing along without reviewing
  • Set out from the beginning a style guide, how the team will approach the development of the application
  • In PR reviews, don’t just have a quick look over the code and accept it, discuss with the developer if there are problems or code smells and how they can restructure their code to avoid these types issues later
  • Teach the more junior developers good practices on structuring code
  • Tell the managers and stakeholders why having good code quality is important to their project, why cutting corners, will only come back to haunt a project later on