Nalaka Jayasena
Posted on August 22, 2020
This article is the first step in a brief tour of the Angular framework for experienced web developers- specially those coming from another framework like React, Vue, or Ember.
With a decent grasp of HTML, CSS, TypeScript, HTTP and NodeJS, you should be able to easily follow along, and at the end of the series, have a good idea of how Angular works and how to go about using it to build modern web applications.
This article was last updated on 22nd August 2020.
Table of Contents
- Preamble
- Web apps
- Web frameworks
- Angular vs React
- A history lesson
- Getting started with Angular
- The layout of an Angular workspace
- An Angular project
- What next?
Preamble
Two years after the initial announcement at NgConf 2014 Europe, in the September of 2016, Angular version 2 was finally released. It was a massive overhaul of the framework that greatly improved the internal architecture and overall developer experience. Unfortunately, all those benefits came at a cost.
Version 2 was not at all backwards compatible with version 1, and at the time, there was no clear upgrade path. Version 2 was, for all practical purposes, a new framework! This caused some developers to jump ship to other frameworks such as React, Vue and Ember, or hold out from upgrading altogether.
Now contrast this to what happened on the February of 2020 when version 9 of Angular was released. Similar to how Angular moved from using the template engine to view engine with version 2, the rendering engine was replaced again, with version 9 moving to Ivy as the default. But this time, the developer experience was quite different. There were no angry tweets or posts about how difficult it is to upgrade- in fact, it was an uneventful, unremarkable, and downright boring upgrade experience.
So let me start this brief tour by saying that, Angular, with its already comprehensive feature set, great community, and now with a very boring upgrade story is a framework that gives very little reason for developers to stay away from!
Back to TOC.
Web apps
Let's take a step back and look at the big picture behind what we do as web developers.
A web app, by definition, lives at a particular URL and is loaded by and executed inside a web browser.
When the browser accesses this URL, it obtains the initial HTML code for the web app. This HTML code links to the CSS, JavaScript, and other asset files it needs.
The browser loads these files as well and renders the user interface of the web app on to the users' screen. During this process, an in-memory representation of the web page, a.k.a. web document is constructed by the browser and is maintained throughout the execution lifetime of the web app.
This in-memory representation of the web document is exposed to the web app's JavaScript code for manipulation via the DOM API. The Document Object Model is organized as a tree of nodes and logically sits between our applications' JS code and the view the user sees.
Each tag in the HTML file results in a corresponding node in the DOM tree. Each of these nodes correspond to a particular slice of the rendered view. When the user interacts with the view, the browser fires events, which the DOM API allows our JS code to listen to.
So, a web app is programmed by:
- HTML code to define the initial structure of its user interface
- CSS code to define the initial styling of its user interface
- JavaScript code that:
- Uses the DOM API to manipulate the structure and styling of the user interface
- Uses other Web APIs for things such as accessing the network and saving data locally
- Implements the actual business logic and deliver value to the user
Although manipulating the DOM using the DOM API directly is very powerful, it is more convenient to use abstractions on top of that. This is where libraries like jQuery & React, and frameworks like Angular, Vue, and Ember comes in.
Back to TOC.
Web frameworks
The first library to enjoy widespread adoption was jQuery, which appeared around 2006 and addressed the problem of incompatibilities in how the Web APIs were implemented across the major web browsers. It also gave a simple, elegant API on top of the original DOM API for accessing and manipulating the DOM.
The next challenge was to have an easier way for our web apps' data and logic, typically organized as JS classes and or functions, to drive the user interface behind the DOM API. This question was addressed by multiple efforts that started to appear around 2010- such as, Knockout.js, Backbone.js, SproutCore, and AngularJS. These were followed by EmberJS which sprang out from SproutCore in 2011 December.
React launched in 2013 with its virtual DOM and component based approach to UI composition that challenged the mostly MVC based approaches of its predecessors. And Vue.js appeared in 2014 combining features of both AngularJS and React.
In 2016 Angular was released, a complete reboot of Angular, which ditched the MVC based approach of AngularJS in favor of a component based approach.
Back to TOC.
Angular vs React
Angular is often compared with React.
The first thing to note is that React is a library for building user interfaces whereas Angular is a framework for building applications. Given that applications certainly need user interfaces, it follows that Angular covers a much bigger scope than React. This unfortunately also means that Angular has a much bigger learning curve than React so developers are quicker to get productive in React than in Angular. So for simple apps, React seems to be a better choice.
But the proper comparison is to compare Angular with React core + React ecosystem. With React, most of the pieces that Angular provides as part of the framework needs to be picked and chosen from a large buffet of community offerings. This is a good and a bad thing. It is good because it gives more options to the developer so she can put together a highly customized solution. And it is bad for exactly the same reason. Too much choice is often problematic, specially for those beginners who looked at Angular, thought it had too much of a learning curve, gave up and instead picked React. They breeze through the core React concepts in a few weeks and then realize that building their apps requires quite a few more tools than what the React library provides.
So for complex apps, specially CRUD style enterprisy ones, arguably, Angular has a smaller total learning curve and a better return on intellectual investment than React.
Angular is a well architectured comprehensive application framework. So as you build bigger applications and maintain them for longer, you realize that the upfront learning cost of Angular is offset by the developer productivity that Angular continues to give over the full lifecycle of the web application.
Once developers get through the core concepts that underlies the Angular framework, they realize that the going gets much more easier and that they have in their possession a much more powerful toolbox with a set of cohesive tools to wield at many application development challenges.
That was how Angular compares to React at a framework level. There is also a fundamental difference in the way the UI library parts of the two frameworks handle DOM manipulation.
Though both Angular and React puts components front and center, as the building block for composing user interfaces out of, React uses what is known as a virtual DOM for manipulating the DOM whereas Angular works with the real DOM.
The virtual DOM is basically an in-memory representation of the real DOM so that when detecting changes, React does not have to touch the real DOM. That makes change detection faster.
Angular has adopted a totally different approach where the Angular compiler augments our app code with framework code. Then this hybrid code operates directly on the real DOM. The extra code is responsible for binding data between our "apps' objects" and "DOM objects" as well as handling DOM events from inside our apps' methods. The compiler tree-shakes unused framework and application code so as to produce leaner code bundles.
Both approaches have pros and cons- and each framework inspires the other to innovate. So assertions about each framework that was true few years ago may not hold today. As developers, our responsibility is to understand the task at hand and the pick the right tool for that particular job.
Back to TOC.
A history lesson
On 2020 October, Angular will be 10 years old. Over the last decade, Angular has helped transform the way we architecture and build web applications and in turn had transformed itself in lockstep with the evolution of the web platform. Let's take a look back at how Angular evolved over the years.
AngularJS was announced by Miško Hevery in 2009 and version 1 was released in 2010.
It came into a world looking for a better way to build web applications- and it really took off.
When v2 was released in 2016 September. It was a complete rewrite and was branded Angular instead of AngularJS. Most people felt that it was a completely different framework that happened to be done by the same team under almost the same name. In some senses it was, for example the template engine at the core of Angular was replaced by the view engine and the MVC architecture was replaced with a component based one.
There was no v3 of Angular because the Angular Router for Angular v2 had already been released as v3. Angular v4 was released 2017 March and v5 in 2017 November.
Angular v6 was released 2018 May. It focused on synchronization of the Angular toolchain- core, compiler, CLI, material, CDK, and a commitment was given to the community to keep things in sync going forward. A way to help users update their applications to newer versions of Angular was introduced in the form of a new CLI command called update
. Another new CLI command add
was introduced to help generate common application parts such as components.
Angular v7, released in 2018 October, introduced schematics, a mechanism for customizing the files CLI generates with the add
command.
In 2019 May, Angular v8 introduced differential loading, which allowed the generation of smaller apps (often 7 to 20 percent smaller) by creating two separate bundles- one for evergreen browsers and one for legacy browsers. Version 8 also introduced builders, which allowed the customization of the tools used and the order in which they are run by the compiler.
Angular v8 was released in 2020 March. The new rendering engine, Ivy, that replaces the template engine used since v2 was available as an opt-in. Ivy was subsequently made the default for Angular at version 9, which was released in 2020 February.
Version 10, that came out on 2020 June, is the latest major release. It introduced few more features aimed at producing leaner and more maintainable Angular apps. For example, the CLI now warns when a dependency is packaged with CommonJS. A strict
option for the ng new
CLI command was added which enables strict mode in TypeScript and strict type checking in templates. The apps are now configured as side effect free, which makes them more tree shakable thus leading to smaller bundles.
Back to TOC.
Getting started with Angular
With a current release of NodeJS already installed in your system, install the @angular/cli
package globally:
npm install -g @angular/cli
Now you should be able to access the Angular CLI with ng
command: Try running ng version
and ng help
.
Open a shell and change directory to wherever you save your coding projects and use the ng new
command to generate a new Angular workspace:
ng new into-angular \
--strict --create-application="false"
An into-angular
directory gets created with the workspace files and a Git repository gets initialized.
The strict option, introduced in Angular 10, enforces a set of best practices such as stronger type checking and making parts of the application self-contained and side effect free.
Let's add a web application project to our workspace:
ng generate application hello \
--strict --inline-template --inline-style
Change into the generated workspace directory and use the ng serve
command to build the hello
project and run in the development server with live reload enabled.
cd into-angular
ng serve hello --open
The --open
option opens the default web browser at the URL exposed by the development server.
We can run the unit tests with:
ng test hello
And the end-to-end tests with:
ng e2e hello
We can do a production build with:
ng build hello --prod
The production build is generated in the into-angular/dist/hello
folder, and the output sizes are quite small- no unreasonable overhead from the framework!
535B index.html
0B styles.3ff695c00d717f2d2a11.css
1.5K runtime.e227d1a0e31cbccbf8ec.js
36K polyfills.9e86b32c42185429d576.js
102K main.77129eaa6e421d8e7131.js
13K 3rdpartylicenses.txt
948B favicon.ico
To serve the production build locally, install the serve
utility and "serve" this directory:
npm install -g serve
serve into-angular/dist/hello
Back to TOC.
The layout of an Angular workspace
The generated Angular workspace directory contains configuration files that applies to all projects.
All projects in a workspace share NPM dependencies. So even if you have ten projects inside the projects
directory, you would have only one node_modules
directory- the one at the workspace level.
The tsconfig.base.json
declares the base options for the TypeScript compiler. These get extended by project level tsconfig files.
The workspace level tsconfig.json
file is for code editors to pickup . So is the .editorconfig
file, which declares coding style options like indenting, quotes, brackets, tabs/spaces.
The angular.json
file is where we configure the behavior of the Angular compiler.
"defaultProject": "hello",
"newProjectRoot": "projects",
"projects": {
"hello": {
"projectType": "application",
"root": "projects/hello",
"sourceRoot": "projects/hello/src",
"prefix": "app",
"schematics": {},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {},
"configurations": {
"production": {}
}
},
"serve": {},
"test": {},
"e2e": {},
Since the defaultProject
is set to hello, in ng
commands, we can drop the project name and still have the command act on the default hello
project. So, we can just do a ng serve
and get the hello project served.
In our hello
project, we have the projectType
set to application. The other option here is library. Later in our tour, we will see how to create a library project and reuse it in multiple application projects.
Soon we will be generating components and other directives- these have a selector that is used inside HTML templates to activate the directive. The string we specify in the prefix
option is used as a prefix for the selector when we generate the directive with ng generate directive
or ng generate component
.
Schematics are the blueprints for the artifacts that the Angular CLI generates with ng generate
command- applications, libraries, components, generic directives, services, pipes, and so on. Options for these go under the schematics
section. The architect
section is for configuring the Angular CLI build pipeline. Angular let's us customize both of these aspects- what the various generators output (with custom schematics) and what the build pipeline does (with custom builders). Later in this tour, we will see how!
Back to TOC.
An Angular project
The generated web application project, hello, looks like this:
The .browserslistrc
file declares browsers supported by this project. Angular uses this information to adjust the CSS/JS output of the compiler.
Angular uses Jasmine for writing unit tests and Karma, configured with thekarma.conf.js
file, for running them.
There are two tsconfig files- one for the application code, and one for the unit test code. These are for configuring the TypeScript compiler. The tslint.json
file configures the TypeScript linter, TSLint. All three files extend their parents from the workspace directory.
The src
folder contains all the source code for the application including unit tests. The e2e
folder contains all the end to end tests. Let's dive into what they contain.
Protractor, configured with protractor.config.js
, is used for writing end to end tests. The app.po.ts
file is a "Page Object" for the our app's landing page. This has convenience methods for use in the actual end to end test file, in this case, app.e2e-spec.ts
.
The index.html
file is the main template. This is where the root component of our app's component hierarchy gets referenced. Entry point for application code is the main.ts
file. For running unit tests, the entry point is the test.ts
file.
Styles shared across the app are in the styles.css
file. Later we will see that components can define their own private styles.
The app
directory is named after the name of the code module it holds- in this case, app. The AppModule
class is found in app.module.ts
. This is the default module for holding our applications’ parts- components, other directives, services, pipes and so on. As we build bigger applications we will need more modules so that we can divide up the app into more manageable sections and load each section lazily when needed.
The app.component.ts
declares the AppComponent
and app.component.spec.ts
contains unit tests for it. AppComponent
sits at the root of our apps' component hierarchy. This is the component that get referenced in index.html
causing our whole app to recursively get loaded.
Back to TOC.
What next?
In the next article we will take a closer look at the primary building block of an angular application, the component. Then we will see how to create services that interact with the world outside our component and how to inject them where they are needed. On subsequent articles, we will continue our tour by looking at routing, forms, material styling, animation, internationalization, accessibility, testing, and keeping the application up-to date as Angular itself improves.
Back to TOC.
Posted on August 22, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
August 31, 2024