The NgModule ‘forRoot()’ Convention

The NgModule forRoot Convention Hero Image

Derived from photo by Boris Tassev / flickr.com, CC BY-SA

The NgModule forRoot() convention is a curious one. The naming explains how to use it but not what it is or more importantly why it's necessary to import an NgModule in this way.

This post peeks beneath the API to help you understand this design and get the most out of the convention.

The NgModule forRoot() Convention

There comes a point when developing in Angular when an NgModule requires a call to its forRoot() method when importing. The most notable example of this is with the RouterModule. When registering this module at the root of an Angular application, importing the RouterModule looks like this:

import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
    { path: '',   redirectTo: '/index', pathMatch: 'full' }
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes)
  ],
  ...
})
export class AppModule { }

This convention is also used in ngx-bootstrap and was previously used in Angular Material. The convention implies that a given module must be registered with the root NgModule of an application while invoking the forRoot() method. What is so special about this method that it needs to be called at the root of an application as opposed to any other NgModule?

For starters, what does the forRoot() convention return? Generally, the return type for this method is an object conforming to the ModuleWithProviders interface. This interface is an accepted NgModule import and has two properties:

interface ModuleWithProviders { 
  ngModule: Type<any>
  providers: Provider[]
}

Put simply, the forRoot() method returns an NgModule and its provider dependencies. What does this have to do with the root NgModule? Maybe nothing. In fact, while this convention implies that it must be imported at the root of the application, in many cases you can import it in a non-root NgModule and it will work – GASP!

Putting that aside for a moment, this is how the ModalModule in ngx-bootstrap uses the forRoot() convention:

import { NgModule, ModuleWithProviders } from '@angular/core';

import { ModalBackdropComponent } from './modal-backdrop.component';
import { ModalDirective } from './modal.component';
import { PositioningService } from '../positioning';
import { ComponentLoaderFactory } from '../component-loader';

@NgModule({
  declarations: [ModalBackdropComponent, ModalDirective],
  exports: [ModalBackdropComponent, ModalDirective],
  entryComponents: [ModalBackdropComponent]
})
export class ModalModule {
  public static forRoot(): ModuleWithProviders {
    return {ngModule: ModalModule, providers: [ComponentLoaderFactory, PositioningService]};
  }
}

Notice how the ModalModule does not declare any providers in the @NgModule decorator but does so in the static forRoot() method.

Why is the Root NgModule Important?

Even though importing the additional providers of the forRoot() method theoretically works in child NgModules, registering it at the root of the application helps in a number of ways.

First, consider how Providers are injected differently than components and directives. Typically, when decorating a class with @Injectable and registering as a provider in an NgModule, this class is created once and that one instance is shared amongst the entire application. When Angular bootstraps the root NgModule, all available imports in all NgModules are registered at that time and made available to the whole application – they are global. This is why providers registered in a child NgModule are available throughout the whole application.

Components and directives on the other hand are instantiated multiple times, once per instance in the markup. In addition, these items are scoped to the NgModule in which they are imported to prevent naming conflicts where two components might have the same selector for example. Because of this difference in dependency injection (DI) behavior, the need to differentiate an NgModule containing components and directives from a ModuleWithProviders containing components, directives, and providers is helpful which is where the forRoot() method makes that distinction.

Dependency injection, however, doesn't always work this simply. There are times when all the application's NgModules are not available during the bootstrap process. Lazy-loading is such an example. When lazy-loading an NgModule during routing, the providers registered in the lazy-loaded NgModule and its children aren't available during the bootstrap process and Angular is unable to register them at that time. Therefore, they are added as providers only when the route is loaded and furthermore they are scoped to be injected starting at the lazily-loaded NgModule and its children. If there are multiple lazy-loaded NgModules attempting to register the same providers, each of these nodes of the NgModule tree end up with different instances. By importing the providers at the root, it helps ensure that all lazy-loaded NgModules get the same instance of the provider and is why forRoot() is named as such.

Be sure to read more about the nuances of Angular's dependency injection in the documentation.

When to Use the forRoot() Convention

As a consumer, use it when a library dependency requires it. Import the module at the root of the application and register with the forRoot() method to import the providers globally. In other NgModules, use the appropriate non-root form of the import when necessary to import the components and directives.

In the case of both Angular Routing and ngx-bootstrap, this convention helps share providers amongst multiple instances of directives and components to achieve a global concern for the application. For example, ngx-bootstrap uses this convention for the modal dialog component. While there may be many modal instances defined in the markup of an application, the modal takes over the entire UI hence all instances of the dialog should understand how they affect this global concern.

In the case of routing, there is only one window.location for the application so even though there may be child routes and various instances of router-outlet components, they all need that one global dependency of the window's location so that they can work together.

In both cases, the consumer of the modal dialog or router does not need to know how these items communicate and manage shared concerns. In this way, the forRoot() method abstracts away the necessary provider registration.

In short, consider using the convention when you have multiple custom components or directives that all take a dependency on a global UI concern and need to work together to manage this global state. To be clear, the forRoot() convention is a form of coupling which should only be used after careful design consideration.

It's best to avoid using this convention with third-party libraries. For instance, don't try to bubble up all the NgModule dependencies of the application using this convention. The providers returned by the forRoot() method should be internal dependencies that work exclusively with the other components included in the ModuleWithProviders. Third-party dependencies should be treated like npm peerDependencies and imported and registered in the root NgModule directly so that other components can more easily share the same dependencies and help ensure all consumers reference the same package version when npm versioning resolves.

Takeaways

In summary, the forRoot() convention represents a way to import an NgModule along with its providers using the ModuleWithProviders interface.

When a feature NgModule exports components and directives that require sharing the same custom provider instances, consider registering these providers in the root NgModule with a forRoot() method. This can help ensure that all child NgModules have access to the same provider instances without requiring the consumer to handle the provider registration explicitly.

For more information on implementing the forRoot() convention, there are some additional implementation ideas found in the Angular documentation.

Please leave a comment below sharing your experiences using the forRoot() convention.

When to Use ES2015 Modules Instead of Angular Dependency Injection (and When Not to)

When to Use ES2015 Modules Instead of Angular Dependency Injection Title Image

Derived from photo by fdecomite / flickr.com, CC-BY

This post discusses some of the nuances between ECMAScript 2015 module dependencies and Angular's dependency injection system. These are design considerations and while you may decide not to use the approaches discussed, the goal is to provide you with a context in which to make more thoughtful decisions about how to use dependencies throughout your Angular application.

A Tale of Two Dependency Systems

When building an Angular application, there are two main dependency systems at play. The first is EcmaScript 2015 (ES2015) modules. This is the system used when creating an import statement or exporting an object. This system uses string identifiers to obtain dependencies via URL or npm package name.

import { platformBrowser } from '@angular/core';

The other dependency system is Angular's dependency injection (DI) system which is built on top of the ES2015 module system. Unlike the static nature of ES2015 dependencies, these dependencies are configurable when the application bootstraps. They are typically defined as a provider in an NgModule.

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [
    ShoppingCartService
  ],
  bootstrap: [ 
    AppComponent 
  ]
})
export class AppModule {

}

While not entirely a one-to-one relationship, consider the idea that ES2015 module dependencies are hard dependencies meaning they cannot easily change upon running the application. On the other hand, Angular provides a more loosely-coupled dependency structure that is more easily configured at runtime.

Note: There are in fact more than two dependency mechanisms if you consider npm module resolution where version numbers can influence the resolution of ES2015 modules or a bundler like webpack which can conditionally swap ES2015 dependencies based on configuration. This would be tooling-based configuration whereas this post focuses on code-based configuration.

Angular Dependency Injection (DI)

At a high level, Angular reads the NgModule metadata during the bootstrap process and creates an injector capable of providing these dependencies through the class constructor of components and services throughout the application. Please read more about Angular's dependency injection in the documentation to understand the full details. This post refers to Angular dependency injection at a high level.

To look at an example, consider an e-commerce application with a digital shopping cart. Imagine a mini-view of the cart while the user is browsing product pages and a separate, detailed view when it's time to check out. The logic to calculate the quantity of items in the cart is the same for each view. Therefore, both pieces of the UI may depend on a ShoppingCartService to calculate the total quantity of items in the cart. This service is provided to the components through dependency injection.

shopping-cart.service.ts

import { Injectable } from '@angular/core';
import { CartDetail } from './shopping-cart.model';

@Injectable()
export class ShoppingCartService {
  getTotalQuantity(cartDetails: CartDetail[]): number {
    if (!cartDetails) {
      return null;
    }

    const total = cartDetails.map(carDetail => carDetail.quantity)
      .reduce((previous, current) => previous + current, 0);

    return total;
  }
}

shopping-cart.component.ts

import { Component } from '@angular/core';
import { CartDetail } from './shopping-cart.model';
import { ShoppingCartService } from './shopping-cart.service';

@Component({
  selector: 'app-shopping-cart',
  templateUrl: './shopping-cart.component.html'
})
export class ShoppingCartComponent {

  shoppingCart: CartDetail[] = [
    { productName: 'Hammer', quantity: 1 },
    { productName: 'Purple Shorts', quantity: 26 },
    { productName: 'Web Shooter', quantity: 2 }
  ];

  totalCartQuantity = this.shoppingCartService.getTotalQuantity(this.shoppingCart);

  constructor(private shoppingCartService: ShoppingCartService) { }
}

Consider the number of steps involved in registering and using this dependency in a component through Angular's DI:

  1. Create the ShoppingCartService class
  2. Import and decorate the dependency with the @Injectible() decorator
  3. Import the dependency into the appropriate NgModule
  4. Register the service as a provider
  5. Import the dependency in the component's ES2015 module
  6. Add it as an argument in the component's constructor
  7. Use the dependency

That's quite a bit of code to implement the default DI recommendation. This isn't a criticism, just an observation. Because this implementation uses the ES2015 module standard and includes the added TypeScript benefits, these steps are reasonable in pursuit of loosely-coupled dependencies.

Note: The Angular CLI can help you avoid having to write some of this code by hand.

While Angular's dependency injection implementation comes with many benefits, it's worth considering an alternative.

Using ECMAScript 2015 (ES2015) Module Dependencies

Instead of creating a class and registering it with an NgModule, consider writing a more generic piece of code that can map and calculate a total from an array of objects. Create a function called mapArraySum in its own ES2015 module. Look at the steps for using this function in a component:

  1. Create the mapArraySum function
  2. Import the dependency in the component's ES2015 module
  3. Use the dependency

mapArraySum.ts

export function mapArraySum<T>(array: T[], mappingFunc: (item: T) => number): number {
  if (!array) {
    return null;
  }

  const total = array.map(mappingFunc)
    .reduce((previous, current) => previous + current, 0);

  return total;
}

shopping-cart.component.ts

import { Component } from '@angular/core';
import { CartDetail } from './shopping-cart.model';
import { mapArraySum } from './mapArraySum';

@Component({
  selector: 'app-shopping-cart',
  templateUrl: './shopping-cart.component.html'
})
export class ShoppingCartComponent {

  shoppingCart: CartDetail[] = [
    { productName: 'Hammer', quantity: 1 },
    { productName: 'Purple Shorts', quantity: 26 },
    { productName: 'Web Shooter', quantity: 2 }
  ];

  totalCartQuantity = mapArraySum(this.shoppingCart, item => item.quantity);
}

Wow, this is a much simpler approach. Furthermore, the dependency is completely decoupled from anything Angular-specific like @Injectable. Which implementation should you use? There are several considerations that should factor into this decision.

When to Consider Using ECMAScript 2015 Modules

The reason the ShoppingCartService is probably not a good candidate for straight ES2015 module dependency management is twofold. First, the UI of a shopping cart is generic enough where you may want to re-use the shopping cart UI components in multiple applications. These applications may employ different shopping cart logic. Second, the checkout process is prone to business changes and totaling a cart may change very much depending on promotions, shipping rates, or other business rules. You may find that calculation can no longer be done on the client and must involve a call to the server.

Potentially, it makes sense to employ both implementations where the ShoppingCartService exists as a loosely-coupled dependency yet its implementation leverages the generic mapArraySum function.

shopping-cart.service.ts

import { Injectable } from '@angular/core';
import { CartDetail } from './shopping-cart.model';
import { mapArraySum } from './mapArraySum';

@Injectable()
export class ShoppingCartService {
  getTotalQuantity(cartDetails: CartDetail[]): number {
    const total = mapArraySum(this.shoppingCart, item => item.quantity);
    return total;
  }
}

Before detailing what criteria indicates a potential candidate for ES2015 dependency management, remember that when in doubt the safer choice is to use Angular's dependency injection. In the end, it provides much greater flexibility if you ever need it.

These criteria potentially identify code suitable to use ES2015 dependency management:

  1. Pure functions with stateless logic (e.g. calculations, validations, mapping data structures)
  2. No external dependencies (e.g. HTTP requests)
  3. Generic functionality (e.g. language-level functionality, contract-based data mapping)
  4. Throw-away code for prototyping purposes

Given these criteria, and other than rough prototypes, what type of code specifically does this cover? This type of code can go by many names, but falls into the category of utility functions. This is code that helps you do things that you repeatedly do in any JavaScript application. It's the code you get sick of writing over and over. A simple example is a function that checks if an object is null or undefined.

export function isNullOrUndefined(value: any) {
    const isNullOrUndefined = value === null || value === undefined;
    return isNullOrUndefined;
}

This is a one-liner, but consider building on it:

export function isAnyNullOrUndefined(values: any[]) {
    // this would be more lines without support for .some()    
    const isAnyNullOrUndefined = values.some(value => isNullOrUndefined(value));
    return isAnyNullOrUndefined;
}

// another common example
export function isEmptyString(value: string) {
    const isEmptyString = !isNullOrUndefined(value) && value.length === 0;
    return isEmptyString;
}

What about a function that adds all the numbers in an array and rounds to a specific number of decimal places? This logic is prone to errors or inconsistencies in implementation. Do you round before or after you add? How do you guard against precision errors? These are all things a developer shouldn't have to keep revisiting while building an application. How do you perform a deep clone or a deep compare of two objects? These are all examples of common logic that developers use again and again.

Could you still put this logic in an Angular service and inject it into a component? Absolutely. The point is that you have another option that might prove more simple, elegant, and/or re-usable. Ultimately, choose what's best for your team and your project.

Use ES2015 Modules to Abstract Hard Dependencies

You may have been thinking during the last section, "Aren't there utility libraries to use for these types of utility functions?". There are and developers use them every day. The question is, should your application take a hard dependency on these libraries?

Based off the information thus far, this functionality can probably safely exist as an ES2015-based dependency. However, you can partially ease the coupling by abstracting the specific framework or library reference to within a library under your control. In this way, if you decide for examples that lodash's deep compare function is no longer required because of an emerging ECMAScript standard, you can easily replace it in one place without affecting the rest of the application.

Consider an isEqual module:

isEqual.ts

import * as _ from 'lodash.isequal';

export function isEqual(target: any, comparison: any) {
    const isEqual = _.isEqual(target, comparison);
    return isEqual;
}

app.component.ts

import { isEqual } from './app-utility/isEqual.ts';

@Component({
    selector: 'my-app',
    template: './app.component.html'
})
export class AppComponent {
    foo: any;

    onSomeEvent(newFoo: any) {
        if (isEqual(this.foo, newFoo)) {
            return;            
        }

        console.log('foo is new');
        this.foo = newFoo;
    }
}

So instead of repeatedly coupling your components to third party libraries, depend on your own utility library where you can replace or remove third-party utility libraries as necessary.

Conclusion

Again, this post is intended to help you think more deeply about the dependencies in your Angular application. There are many different approaches to handling these designs. What approaches do you use to manage dependencies in your applications?

Get Your TypeScript Definitions from NPM

Get Your TypeScript Definitions from npm

Derived from photo by raumrot.com, CC-BY

If you use TypeScript, you appreciate what the type system provides with IntelliSense and easier refactoring. This experience is quite seemless with code you have written. However, using third-party libraries has left many struggling with complex configurations.

With the advent of ECMAScript 2015 (ES2015) modules and the rise of npm as the defacto JavaScript package manager, configuring your type definitions has gotten more complicated. Not only did you have to ensure that your import statements resolved to the correct scripts but now also the correct type definitions.

Thankfully, the community is standardizing third-party type resolution similar to how it is standardizing on ES2015 modules and npm.

Once Upon a Time

Back in the early days of TypeScript, you used to reference type definitions at the top of the .ts file like this:

/// <reference path="../lib/my-favorite-library.d.ts" />

Also you probably got the type definitions from a dedicated registry somewhere like DefinitelyTyped and maybe even used command line tools to setup and configure these type definitions like tsd or typings.

There were shortcuts and optimizations but ultimately it was a whole other set of configuration and package management to get third party libraries compiling with TypeScript.

Relative Path Module Resolution

While you can still write your comment-based type references, the industry has adopted the ES2015 module standard and so has TypeScript.

By adopting this standard, each JavaScript (or TypeScript) file essentially represents a module with its own scope. Any dependencies that this module requires are imported directly from another module by the module's URL. In the future, browsers will understand how to parse this syntax and load each module as needed from the server. Today, TypeScript transpiles these import statements into a configurable module loader syntax such as AMD, UMD, or CommonJS.

Take for example the fact that your GrooveService takes a dependency on your FunkService. Because you wrote your FunkService in TypeScript, both the scripts and the types are found at the same location.

import { FunkService } from './funk-service';

On the other hand, what if you are using angular in Angular 1.x? Initially, you might think to reference it by relative path:

import * as angular from './node_modules/angular/index.js';

This makes sense because this location is where the scripts reside and the browser will load the correct library. However, TypeScript complains that it can't find angular. Well, it turns out the angular library doesn't include TypeScript definitions in the package. TypeScript tried to find the type definitions at the relative path, but they weren't there and you got the dreaded red squiggle..

Angular IntelliSense Squiggle

Traditionally, this is where tsd or typings came into the picture. These repositories contained packaged type defintions for many popular libraries independent of the library provider. And while these repositories solved a real problem in obtaining type definitions, they weren't easy to setup and configure. After all, who wants to maintain two sets of packages managed by two different tools with two different configurations just for the ability to reference one library using TypeScript?

There's another problem with taking a relative path reference to an npm module, what if your code is distributed as an npm package? If you have spent time reading up on npm dependency resolution, you know that you can't guarantee the location of your dependencies in npm. They may be dropped at different levels of the folder structure and therefore attempts to reference npm modules by relative path are fragile.

Node Module Resolution

In order to solve the npm module resolution problem, the folks at TypeScript decided to just follow the npm model. This solution makes it seamless to reference both the code and the types using the same syntax used in NodeJS.

import * as angular from 'angular';

Given this import statement, NodeJS understands that angular is equivalent to /node_modules/**/angular/index.js. It doesn't know exactly which directory it will be in but it knows how to find it.

As of TypeScript 1.6, the compiler understands how to look for type definitions in the same fashion. TypeScript looks for something roughly equivalent to /node_modules/**/angular/index.d.ts. This is great because it ensures that the code and the types can be found in the same npm package.

But what if the code and the types aren't in the same package? For instance, the Angular 2 libraries ship with type definitions included in the package but Angular 1.x does not. This introduces another great solution from the community. Instead of using tsd or typings for your third-party type defintions, now you can just use npm.

The @types organization is available on the public npm registry for the purpose of hosting third-party type definitions that don't ship with their repective package. So if there is a set of types available independent of the package's publisher, by convention you can find them on npm using @types/package-name. For example to download types for angular, you get them by installing the @types/angular npm package. Furthermore, TypeScript understands how to resolve types from the @types directory out of the box.

To ensure node module resolution for your project, set it in your tsconfig.json file:

{
    "compilerOptions": {        
        "moduleResolution": "node"
    }
}

Note: To read more about how TypeScript handles node module resolution, there are more details in the TypeScript documentation.

Bringing Node Module Resolution to the Browser

This all sounds great – less tooling dependencies, easier configuration. NodeJS runs everywhere – desktop clients, web servers, Linux, MacOS, Windows. But unfortunately, when the web browser tries to load scripts from angular you get a 404 result. The browser doesn't understand how to convert the npm package name into the URL for which the script resides.

This is the place where the node module abstraction breaks down. But think about it for a second. Yes, NodeJS doesn't run in the browser. Yes, you aren't necessarily writing a NodeJS backend. But what NodeJS has done is unify the runtime on which web developers run their client-side tooling. This is the environment on which you do your TypeScript compilation, combining modules, minifying – basically optimizing your code to be consumed by the browser. And so it still makes sense that npm would be the best solution for module resolution of both the scripts and the types.

There are a ton of different ways to prepare your application's npm modules for delivery to the browser and you can bet that there will be more coming in the future. For now, SystemJS is a good place to start. Many deveopers already use this library as a script loader and by adding some additional configuration, it's possible to map npm-based dependencies to a relative URL.

Without any additional configuration, the browser is going to see the import statment for angular and attempt to request /angular from the server. What should really happen is that the browser requests the code from the actual package folder like node_modules/angular/index.js. So using your SystemJS configuration file, add the following:

System.config({        
    packages: {
        '': {
            defaultExtension: 'js',
            map: {
                'angular': './node_modules/angular/index.js'
            }
        }
    }
});

This code configures the root of your application (at the path '') to always add a .js extension if one is not present and to also map the 'angular' path. Now when SystemJS sees the import statement for 'angular', it maps that to a request for node_modules/angular/index.js as defined in the configuration.

Automatic Typings Acquisition

If you've made it this far, you understand how this simplifies the process of acquiring and referencing type definitions. It's become simple enough in fact that the Visual Studio Code team is working to make it automatic in the editor. As of this writing, the feature is released but the team admits it still has rough edges. Even still, you can read more about it in the release notes and start trying it by downloading version 1.7.2 or later.

Keep in mind, the tooling may have drawbacks even when it is complete and it's helpful to know what the tooling is doing underneath the covers. Also, this tooling doesn't address the need for mapping npm package names to URLs in the browser like discussed with SystemJS.

The End

The point here is that node module resolution has become the defacto standard in the web development community and TypeScript is no exception. Now that @types is available on npm, you have one place to get your third-party libraries and type definitions – npm.

The tricky party is still configuring node module resolution for the browser but you see how it's possible to setup SystemJS to handle the mapping. Look for more tooling discussion in future posts.

Are you using ES2015 modules and node module resolution with TypeScript? What is your preferred method of mapping the module names to URLs for the browser?

Using EcmaScript 2015 Modules in TypeScript with SystemJS

TypeScript and SystemJS header

There are two powerful tools for Angular developers in TypeScript and SystemJS. They are both in the Angular 2 quick start and they work just as well with AngularJS 1.x for building maintainable Angular applications.

However, getting started using these tools can be tricky. You need to align both tools' configurations so they work together and having a basic understanding of what happens under the hood can save you hours of confusion and frustration. Once you understand the core concepts and setup the configuration, this workflow helps to make your code more decoupled and maintainable – and maybe even more fun.

This post walks through the basics of using SystemJS and TypeScript in Visual Studio for development. You learn the minimum configuration that matters, how it interacts with the rest of the system, and what to expect when compiling and running your application.

Before You Begin

If you want to skip right to the code, it is all on GitHub. The example is in Visual Studio 2015 (there's a free community edition) and is designed to run with minimal dependencies.

The example project is a component called ListMaker which allows the user to make a list by typing in a textbox and pressing ENTER. This component is made up of two child components AddItemTextbox and List, and includes basic CSS styles. The main script bootstraps the ListMaker component and everything is brought together in index.html.

Application structure

SystemJS is the only library used in the example. Adding dependencies with TypeScript and SystemJS, including Angular, is another level of complexity that is omitted here intentionally. There are enough pieces to understand using SystemJS and TypeScript together so watch for more posts on this topic.

Required Tools and Frameworks

This walkthrough uses the following tools and frameworks:

Visual Studio

The demo is built using Visual Studio 2015 Community. Visual Studio provides a seamless experience to compile and run your application on a development server. It also has first class support for TypeScript.

TypeScript Add-In for Visual Studio

This add-in enables TypeScript support in Visual Studio. The demo uses TypeScript 1.8.36. Install the add-in through Visual Studio's Extensions and Updates manager or from the web.

SystemJS

SystemJS is the JavaScript module loader. It's included in the project on GitHub. You can also obtain it from your favorite JavaScript package manager or as a release download from GitHub.

If you don't use Visual Studio, don't fret. You can port the code to another web project as there are no Visual Studio-specific dependencies. Be sure you know how to setup a development server and TypeScript support in your environment of choice.

Workflow Overview

When using these tools together, your workflow requires a compilation step. The Visual Studio TypeScript add-in automatically handles the compilation when you build or run your project. If you aren't in the habit of using front-end compilation tools such as TypeScript, this may be new to you. Here is an overview:

Diagram of TypeScript with SystemJS workflow

TypeScript Configuration

While the default TypeScript configuration in Visual Studio works, there are a couple options to discuss. First, you should consider adding a tsconfig.json file to your project. By default, you find the TypeScript properties in the Visual Studio project properties, however using a tsconfig.json file has advantages.

Most importantly, the project properties do not show all of the options that are available in tsconfig.json so if at some point you want to set other options, you will be limited by the tooling in the project properties. Also, the tsconfig.json file is a standard configuration for every editor and compiler that supports TypeScript. Therfore if someone joins your team that knows TypeScript, they will know where to look for the configuration no matter which tools they use.

Note: you should install the latest update of Visual Studio 2015. Earlier versions did not properly recognize the tsconfig.json file.

The first related configuration option is compilerOption.module. This option sets which module loader format the TypeScript compiler emits. Because SystemJS understands all of them, it's hard to pick the wrong one. Ultimately your choice here may depend on the other tooling you use for building your JavaScript. For now, choose "system" as it is the native format of the loader but you may find that "amd" provides greater compatibility with other compilation tools.

The other option is compilerOption.target. This option sets which version of the ECMAScript® standard to target when generating JavaScript from your TypeScript files. This value largely depends on which browsers you are targeting. The default value is "es3" which gives you the broadest range of browser support. It's worth noting that should you eventually want to emit native ECMAScript module syntax, this option will need to be set to "es2015".

Your tsconfig.json file should at least have:

Implement ECMAScript 2015 Module Syntax

Take a look at the ListMaker component without the ECMAScript 2015 module syntax:

The first thing to note is that ListMaker is in the global scope as it is meant to be re-used within a given application. The ListMaker implementation, however, is not in global scope and is instead wrapped in an immediately invoked function expression (IIFE). If you look closely, you also see that ListMaker depends on two other constructor functions not defined in this code: AddItemTextBox and List. These constructors are also defined in global scope and furthermore you have to ensure that AddItemTextBox and List are loaded in the browser before trying to create a ListMaker.

The fundamental mechanism for modules are import and export statements. The import statements define the module's dependencies and the export statements define the objects that are available to other modules. Take a look at how the ListMaker code changes when using ECMAScript modules:

The module's dependencies are clearly defined in the import statment and you can easily determine where to obtain the source code for these objects looking at its URL. Also, because module scope is separated from global scope by default, the use of an IIFE is unnecessary leading to less code and more readable code.

Finally notice the export statement and the use of the default keyword. While ECMAScript modules can define multiple exports, only one object is defined as the default export. Similarly, the import statements for this module are explicitly importing the default export from the target modules.

This post doesn't go into all the ways you can write your import and export statements. TypeScript supports various options for writing these definitions so read more about them here.

SystemJS Configuration and Reconciling Import URLs

This is likely the most important part configuring SystemJS and TypeScript to work together. Both SystemJS and TypeScript evaluate the import statements. When TypeScript looks at the import statement, it is looking for a TypeScript file so that the compiler can use the types defined in that file. Using import './Foo', TypeScript looks in the current directory for Foo.ts and then uses the information contained in that file for compilation and type checking.

SystemJS on the other hand looks at import './Foo' and then attempts to make a request to the server for <current-directory>/Foo and without any special configuration, this request will produce a 404 resource not found error. What SystemJS needs to request instead is <current-directory>/Foo.js.

Luckily, SystemJS has a configuration option to append a file extension to requests. You configure this by setting up a specific path in your application using the packages option. In the demo, all of the TypeScript files are in the components folder and SystemJS needs to add a .js extension to these requests.

Create a systemjs.config.js file in your application and add the following configuration:

You can optionally configure this behavior for the whole application by using an empty string '' to set the root of your application as the path. Also remember this configuration only applies to requests made by SystemJS and other requests still require explicit file extensions. There are many useful options in the SystemJS configuration so be sure to read up on its capabilities.

Bootstrap the Application

There is bootstrapping logic for the application in main.ts. The browser requests this file first and the script's purpose is to access the Document Object Model (DOM) and render the root component which in this case is ListMaker. It's important to understand using module loaders that the first module retrieved is the last one to execute its contents. For example, even though main.ts is the entry point of the application, all of the other dependent scripts execute prior to main.ts executing.

Once you determine the main script, you bring the configuration and bootstrapping together on the root HTML page. Reference SystemJS, followed by the SystemJS configuration, and then use the System.import syntax from SystemJS to load the post-compiled version of main, 'scripts/main'. Remember that even though the extension is not present, you have configured SystemJS to add the extension and request scripts/main.js.

Once main.js is loaded, all of the other import statements are evaluated and the target modules are loaded as well to compose the application. This diagram illustrates the dependencies and the order of execution when loading.

Diagram illustrating bootstrap process

At this point, you have configured enough for your application to run. Remember to compile the TypeScript first and all of the modules will run and execute in the correct order. Be sure to check out the complete project for all of the details.

Only the Beginning

This is the first step using ECMAScript 2015 modules with SystemJS and TypeScript and this workflow works quite well as a development workflow. Once you understand the configuration and basics of using the tools, you can get up and running rather quickly.

But you need more. As an Angular developer, you need to bring in third-party libraries and seamlessly integrate with your application code. This is the topic of the next post in this series.

At some point, you will want to bundle these scripts together into one request. You may even want to create several bundles that are loaded dynamically via a route change or a certain screen size. The good news is that by separating your code into modules that have explicit dependency references, you have made this configuration much easier to attain.

Finally, the documentation for both of these tools is well done. Be sure to read the TypeScript documentation and the SystemJS documentation for more information.

Stay tuned for more on this topic. If there is anything else you want to know about these tools or if you also have experience with them, please share in the comments below.

Understanding JavaScript Modules

Understanding JavaScript Modules Headers

One of the first pieces of JavaScript you write with Angular is a module. Modules have been around in JavaScript for a while and are not unique to Angular. However, the term is often used to mean different things depending on the context. Some developers refer to specific JavaScript coding patterns as modules, such as the ‘module pattern’. Some developers denote modules by using a popular module specification such as AMD or CommonJS. Maybe you have even heard of the upcoming EcmaScript® 2015 module specification. How do these concepts fit with Angular and its module system?

This is the first in a series of posts to demystify the term ‘module’ in JavaScript and Angular. The key to understanding JavaScript modules is that you can’t point to any one thing as a ‘module’. What developers are really doing is writing modular JavaScript and there are many different techniques and tools to achieve this goal. This post discusses the benefits of writing modular JavaScript and some of the general techniques and tools you can use to achieve these results.

Components Versus Modules

You will see the term component used throughout this post. While the terms component and module are often used interchangeably, this post uses the term component to refer to a piece of software encapsulating a single-responsibility. It is the what that you are trying to achieve. Using modules or writing modular JavaScript, is the how. Writing a module is the approach in which you achieve this composition. Because there are different ways to write modular JavaScript, the meaning of the term module changes accordingly.

A Note about Angular Modules

This module information focuses on pure JavaScript modules. There is information dedicated to Angular modules, specifically the Angular 1.x variety but there are two reasons to explore the wider world of JavaScript modules. The first reason is that there is a vast set of tooling available today for working with modular JavaScript that work well with Angular 1.x and extend the capabilities of the Angular 1.x module system. The second reason is that Angular 2 is aligning with the EcmaScript 2015 module standard in place of the module system for Angular 1.x. What you will see is that by increasing your ability to write modular JavaScript, you will increase the quality of your Angular code and workflow today and these skills will translate to Angular 2.

Benefits of Modular JavaScript

What developer does not want to work with more readable and maintainable code? This topic becomes the heart of many development team discussions. Writing modular JavaScript allows you to write code that is easier to maintain and debug. Here are some of the benefits:

Single Responsibility

If you are familiar with the SOLID principles, single-responsibility is important in code construction. Single responsibility means that your application’s components are each responsible for one purpose or function. By dividing your code in this manner and naming the components appropriately, you can more easily identify where code should be placed or where to begin to debug your code. Writing modular JavaScript allows you to create and separate these components from each other so that each module has a single responsibility.

Encapsulated Internals

Encapsulation is another important concept in software design meaning that your components may have data or functionality that is not meant to be accessed by other components. By encapsulating this information, you create a barrier preventing external components from calling these internal concerns. A popular way to implement encapsulation in JavaScript today is the use of closures. The EcmaScript 2015 module specification also defines ways to encapsulate pieces of JavaScript.

Avoids Global Scope

While this is similar to encapsulation, global scope collisions often occur at a higher level in an application. When libraries attempt to use the same global variables or two pieces of a large application are written to use the same global variables, this condition often causes problems. These types of collisions are becoming less frequent especially in popular third party libraries. Using module specifications further diminishes the likelihood of a global variable conflict.

Use Separate Code Files

Once your code is separated into individual components, separating that code into multiple files generally increases maintainability. Now changes to components are clearly identified in source control as changes to the associated files. The challenge is to ensure that all of the individual files are loaded into the browser correctly or combined into a single file. There are tools to help in this area including loaders and bundlers.

Manage Dependencies

Once you have code separated, you need to manage which pieces of code are dependent on another. There have been several specifications developed to help manage these dependencies. While these specifications differ in their syntax, they provide two fundamental pieces: a way to define dependent modules (imports) and a way to define pieces of a module that can be used in other modules (exports). Frameworks have developed around these specifications to intelligently load the necessary modules both in the browser and in NodeJS.

Achieving Modular JavaScript

Now that you know why you should write modular JavaScript, there are general techniques available to accomplish this. Here is an overview:

Patterns

There are numerous existing JavaScript patterns available to you today. You see these basic patterns in constructing your Angular controllers and services. If you ever use the ‘controller as’ syntax in Angular, you are essentially using the constructor pattern. EcmaScript 2015 introduces classes to JavaScript and you can use them to write controllers in Angular 1.x and components in Angular 2. If you are looking to deepen your understanding of current JavaScript patterns, check out Addy Osmani‘s book, Learning JavaScript Design Patterns. The other techniques for organizing JavaScript help but writing quality JavaScript code is the foundation on which you will build your application so don’t skip this step.

Module Specifications

Module specifications help manage dependencies in JavaScript. If you want to separate your code into components, how can you use (and re-use) these components throughout your application? You use a syntax to define the components available to your application (also known as exports) and a syntax to define which components are required as dependencies in another component (also known as imports). Having a specification helps ensure open source libraries work well together.

The main specifications in use today are Asynchronous Module Definition (AMD), CommonJS, and the upcoming EcmaScript 2015 module specification. The AMD specification is more often used in the browser whereas CommonJS is the spec of choice in NodeJS and NPM. The EcmaScript 2015 standard seeks to eventually become the standard supported by the major browser vendors and it has some nice options for defining imports and exports.

Bundlers

A straightforward way to load JavaScript files in the browser is to add a script element to the HTML page. However, there are several issues with this approach. First, there is performance overhead for sending individual requests to the browser for each file. Second, you have to manually add all of the separate script references on the page and make sure they are listed in the correct order.

By using a bundler, you can mitigate the performance problem by having a process run as part of a build (a Gulp task for instance) which combines all of the script files into one file. Thus, you can reference only one script in your page and the browser only has the overhead of making one HTTP request.

Furthermore, bundlers often minify your code as well making the variable names as small as possible and removing white space. Additionally, they create sourcemaps that you use to debug the code in the browser.

Finally, when you use a bundler in conjunction with a module specification, you no longer have to maintain a long list of scripts. The order of loading the scripts is inferred by the modules’ dependency tree. Browserify is a popular bundler that leverages the CommonJS module specification and JSPM works with EcmaScript 2015 modules.

Dynamic Loaders

Bundling every single JavaScript file together into one request may not make sense for very large applications. You may want to load a base set of libraries and then optionally load in other dependencies. You can accomplish this manually but you can also use a dynamic loader.

A dynamic loader is a JavaScript library that runs in the browser and helps your application download additional dependencies only when they are needed. They work in conjunction with module specifications so that you don’t have to manually call the loader’s API, the dependencies are inferred from the specified imports.

The choice to dynamically load scripts or bundle them is application-specific. Oftentimes, these tools are used in conjunction with each other to minimize page load times. Popular loaders are RequireJS using the AMD specification and SystemJS using EcmaScript 2015 modules.

Angular Modules

Specific to Angular 1.x is the Angular module system. This system provides you with much needed dependency injection in large JavaScript applications. However, it lacks the features you get combining loaders and bundlers with other module specifications. You can use Angular 1.x modules in conjunction with other module specifications to get the benefits of working with bundlers and loaders.

Angular 2 is moving towards using standards based module systems like EcmaScript 2015 making it much easier to use the latest module tooling.

JavaScript Compilers

With all the mentions in this post about EcmaScript 2015 modules, when will the browsers support them? Quite frankly, it doesn’t matter if you use a compiler (sometimes called a ‘transpiler’). JavaScript compilers understand future versions of JavaScript, and emit JavaScript that is compatible with today’s browsers. If you want to use EcmaScript 2015 today (JavaScript essentially is EcmaScript by the way), consider using a compiler. Popular JavaScript compilers are Babel, Traceur, and TypeScript.

In Summary

While the term JavaScript module might be difficult to define, the concepts are here to stay. Remember why writing modular JavaScript is important. You want components with single-responsibility and encapsulation. These components should stay out of the global scope. You also want the maintainability benefits of keeping your code in separate files and you want to leverage dependency injection to use components together in a loosely coupled fashion.

Once you understand why to write modular JavaScript, there are many tools you can leverage to write your modules. Take time to learn about today’s JavaScript patterns. Understand your options with module specifications and use bundlers, dynamic loaders, and compilers to put it all together in your application.

This post introduces a lot of topics and future posts will look at these concepts in more detail. If there is a concept in which you are particularly interested, please leave it in the comments.

Code Camp NYC 2015 Talks

Code Camp NYC 2015

I had the pleasure of giving two talks at Code Camp NYC 2015. It was a great experience and I met many smart and dedicated developers. Here are the talks’ descriptions, slides, and source repositories. I will explore these topics more on the blog in the weeks to come.

Intro to JavaScript Modules

If you are a web developer, you have encountered JavaScript modules and hopefully you are using them. But if you aren’t or you think you can be using them better, this talk will give you the lay of the land for using JavaScript modules effectively. You’ll learn about the most common players like CommonJS, AMD, SytemJS and how they relate to the EcmaScript 6 standard. In addition, you’ll understand how to use tooling for combining and loading modules. There are many options and the choices can be overwhelming. By the end of this talk, you’ll know which technologies and frameworks can help to incorporate better JavaScript modules in your code.

Examples on GitHub

Angular 2 Tooling Today with Visual Studio

Angular 2 is the next evolution in Angular and along with the framework comes a recommended set of tools to increase developer productivity. Whether or not you are ready for Angular 2, you can start using these tools now with your current Angular projects. Attendees should have a basic understanding of Angular 1.x concepts. This talk demonstrates the fundamentals for using tools and frameworks such as TypeScript, SystemJS, and EcmaScript 6 in an Angular 1.x application. Armed with this knowledge, you can prepare for migrating to Angular 2 and more importantly improve your developer workflow today!

Example on GitHub