AngularJS and the Origins of Angular
AngularJS made its debut in 2010, marking one of Google's initial forays into open-source front-end frameworks. The framework remained open source and enjoyed a 12-year lifespan before reaching its end-of-life milestone in 2022.
With AngularJS came a novel approach to writing HTML templates. Directives such as "ng-for" and "ng-if" introduced fresh concepts that would go on to influence numerous other frameworks and rendering engines that followed.
The AngularJS team soon recognized the challenges inherent in maintaining a substantial JavaScript codebase. This realization led to the announcement of Angular—a complete rewrite—in 2014.
Selecting the Right Tools
Angular has earned a reputation for thoroughly evaluating existing technologies before committing to the most suitable option. Here's a look at the tools the Angular team has adopted throughout the years.
Past Approaches
During the initial phases of Angular's development, the team opted for TypeScript—a language still in its infancy back in 2014, and one that drew criticism from many quarters. Some developers rejected the choice entirely, turning to alternative frameworks that permitted plain JavaScript.
Time has vindicated that decision, however. The advantages of TypeScript have become widely apparent, and today most developers actively prefer it over standard JavaScript.
Build tooling for JavaScript was just beginning to emerge in 2014. Tools like Grunt and Gulp were common at the time. Early Angular releases (2.0) relied on SystemJS, requiring developers to handle all configuration manually. With the arrival of Angular 4.0, the team introduced Webpack and the CLI, shielding developers from configuration concerns. Webpack proved remarkably reliable over the years, earning the trust of both developers and other frameworks.
At one point, the Angular team explored adopting Bazel as their build solution. While Bazel is a capable tool, its complexity presented significant challenges, and the team ultimately decided against pursuing that direction.
Current State
Angular continues to employ Webpack, while also providing experimental support for esbuild. The team recognizes the need for change and is evaluating alternatives that outperform Webpack.
The CLI has seen substantial refinement, particularly in easing version migrations. Visit https://update.angular.io/ for migration guidance.
Looking Forward
After assessing various build solutions, Angular will direct its investment toward esbuild for building applications.
You might wonder about vite, the current crowd favorite. The team examined it but determined it wasn't suitable as the primary build tool for Angular applications—though it will remain available for projects that use it during development builds.
Rendering Engines
Angular relies on a compiler to construct the final build output, which moves through several stages. The rendering engine is one such component, and the Angular team has refined it repeatedly. Ivy represents the current generation, opening the door to significant features like the Standalone component.
Reactivity Focus
Past
From its inception, Angular pushed developers toward reactive programming patterns. The framework adopted RxJs, the premier library available at the time. RxJs powered internal APIs including HTTP and Router, and even EventEmitter was built on an RxJs Subject.
Present
RxJs adoption has expanded considerably, with a growing developer base embracing this robust library. Yet, voice from the community has also pushed for Angular experiences that don't require RxJs, while others have requested deeper, more seamless RxJs integration.
Future
The Angular team is currently exploring Signals, with a concrete public RFC anticipated. Signals aim to flatten the learning curve that RxJs demands, while simultaneously exposing APIs that improve RxJs integration.
Change Detection
Past
Every framework must handle change detection carefully, and Angular is no exception. The team integrated zone.js in the early days to manage this process.
Present
Angular retains zone.js to this day, but performance challenges emerged for large-scale applications, forcing developers to pursue optimization strategies. The OnPush change detection strategy is now broadly adopted to boost performance. Libraries such as RxAngular provide ways to disable zone.js, albeit requiring some refactoring effort.
Future
The momentum is shifting toward letting developers prioritize code quality over change-detection mechanics. This is the deliberate philosophy Angular has embraced. With Signals on the horizon, zone.js will become optional, and concern over change-detection strategies will fade.
A Commitment to Inclusivity
Angular adheres to a six-month release cadence, meaning a new major version arrives twice a year. Each release carries an 18-month support window. If you remain on a given Angular version beyond that, support likely no longer exists.
Angular mitigates that risk, though. Every new release is accompanied by automatic migration tooling through the Angular CLI. A simple invocation of ng update handles the heavy lifting.
The documentation details how to update Angular across multiple versions.
ng update
A Rich Feature Set
Over time, the Angular team has deepened its engagement with the community, producing a series of excellent features.
The inject Function
Dependency Injection (DI) stands as one of Angular's most cherished capabilities, and the introduction of the inject function has further elevated the developer experience.
A comparison between the old and new approaches follows:
@Component({
selector: 'app-employee-details',
templateUrl: './employee-details.component.html',
styleUrls: ['./employee-details.component.scss'],
})
export class EmployeeDetailsComponent {
modes$ = this.route.queryParamMap.pipe(
map((params: ParamMap) => params.get('mode'))
);
userName$ = this.route.paramMap.pipe(
map((params: ParamMap) => params.get('username'))
);
employeeId$ = this.route.paramMap
.pipe(
map((params: ParamMap) => params.get('employeeId'))
);
constructor(private route: ActivatedRoute) { }
}
Using the inject function
@Component({
selector: 'app-employee-details',
templateUrl: './employee-details.component.html',
styleUrls: ['./employee-details.component.scss'],
})
export class EmployeeDetailsComponent {
modes$ = inject(ActivatedRoute).queryParamMap.pipe(
map((params: ParamMap) => params.get('mode'))
);
userName$ = inject(ActivatedRoute).paramMap.pipe(
map((params: ParamMap) => params.get('username'))
);
employeeId$ = inject(ActivatedRoute).paramMap.pipe(
map((params: ParamMap) => params.get('employeeId'))
);
constructor() {}
}
Template:
<h1>
Employee Details for EmployeeId: {{employeeId$ | async}}
</h1>
<h2>Current Mode: {{ modes$ | async }} </h2>
Standalone components
The Angular community has long awaited a version of the framework that does not rely on Angular Modules. While modules still play a valuable role in application architecture, they are often unnecessary and add extra complexity to the learning process. The introduction of Standalone Components addresses this by allowing components to exist without module registration. These components remain fully compatible with the existing module-based system, so they can be integrated into an Angular Module whenever needed.
import { Component, OnInit } from '@angular/core';
import { MatTableModule } from '@angular/material/table';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSortModule } from '@angular/material/sort';
@Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.scss'],
standalone: true, // Standalone flag to differentiate between component with module
imports:[
MatTableModule,
MatPaginatorModule,
MatSortModule
] // you can import Angular Module, Standalone Component/Directive/Pipe here
})
export class UserComponent implements OnInit{
constructor() {
}
}
Standalone APIs
To further enhance the standalone component experience, Angular has rolled out Standalone APIs. Support for these APIs already exists in the Router and HttpClient, and external libraries such as NgRx have adopted the pattern as well.
Here is a code example showing how to utilize the Standalone APIs for HTTP and routing:
providers: [
provideHttpClient(),
provideRouter(
routes,
withDebugTracing(),
withEnabledBlockingInitialNavigation() //required for SSR
withHashLocation(),
withPreloading( PreloadAllModules),
withRouterConfig({
onSameUrlNavigation: 'reload',
})
),
]
Standalone Component Migration
Considering the effort required to convert your entire codebase to standalone components? The Angular team has provided a straightforward solution. Running a single command will automatically migrate all your components, directives, and pipes to the standalone format. Happy migrating!
ng generate @angular/core:standalone
Functional guards
Router guards have been a staple, but they previously required the boilerplate of a service class. The arrival of functional guards has changed that paradigm. Now, a guard can be written simply as a function, eliminating the need for a dedicated class.
const authGuard: CanMatchFn = () => {
const authService = inject(LoginService);
const router = inject(Router);
if (authService.isLoggedIn) {
return true;
}
return router.parseUrl('/login');
};
New Image Directive
In 2023, images remain a major culprit behind poor LCP (Largest Contentful Paint) scores. With the NgOptimizedImage directive, this is no longer a concern you need to manage manually.
Optional ZoneJS
For any Angular developer, zone.js is a familiar name. It is the library that powers Angular's change detection magic.
However, in large enterprise applications—Angular's primary stomping ground—it begins to introduce noticeable performance overhead.
The good news is that zone will soon become optional for our applications. The introduction of Signals is making this a reality, and thanks to backward compatibility, you can keep your existing zone-based app running while adding these new signal-based components side by side. While there were previously ways to disable zone.js, none of them were very straightforward.
In the following example, the signals: true property is expected to land soon, but it is not yet available in version 16.0.0-next.7:
import { Component, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-counter',
standalone: true,
signals: true, // you can still try this code by commenting this line
imports: [CommonModule],
templateUrl: './counter.component.html',
styleUrls: ['./counter.component.scss']
})
export default class CounterComponent {
count = signal(0);
increment() {
this.count.update(n => n + 1);
}
}
<p>counter works!</p>
{{ count() }}
<button (click)="increment()">Increment</button>
Signals will bring benefits far beyond just making zone.js optional. You can learn more in the related RFCs:
https://github.com/angular/angular/discussions/49685
https://github.com/angular/angular/discussions/49684
https://github.com/angular/angular/discussions/49682
https://github.com/angular/angular/discussions/49683
https://github.com/angular/angular/discussions/49681
SSR and hydration
Server-Side Rendering in Angular has had its fair share of difficulties and has traditionally lagged behind SSR frameworks from the React or Vue ecosystems. To address this, the Angular team has begun a series of improvements, starting with the release of its first major feature.
Typed Forms
Angular offers two kinds of forms: Reactive Forms and Template-Driven Forms. The community had long requested type safety for these forms, and this feature finally arrived with Angular 14.
Indeed, you can now build typed forms, and you are likely already taking advantage of them.
form: FormGroup = this.fb.group({
name: new FormControl<string>(''),
salary: new FormControl<number>(0),
age: new FormControl<number>(0),
dob: new FormControl<Date>(new Date()),
});
constructor(private fb: FormBuilder) {}
This article aimed to cover the exciting features that Angular has in store for developers. My perspective is optimistic about the future of investing in Angular, just as it was six years ago when I made the jump from a .Net developer to an Angular developer.
That investment of time in learning and supporting the Angular framework paid off in the past, continues to hold strong in the present, and with upcoming features like Signals, its future looks exceptionally bright.
