Importing JavaScript Libraries in Angular

February 24th 2017 TypeScript Angular

Angular makes heavy use of ECMAScript 2015 modules. All components and other Angular objects are modules themselves, therefore the tutorials explain early on, how to import and use them. However, how does one import a third party library which still exports legacy CommonJS or AMD modules?

Even the simplest component in Angular imports at least some declarations from other modules:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-my',
  templateUrl: './my.component.html',
  styleUrls: ['./my.component.css']
})
export class MyComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

In the above snippet Component decorator and OnInit interface are explicitly imported from @angular/core module, which has exported them. Alternatively, one could import all exported declarations from a module:

import * as core from '@angular/core';

@core.Component({
  selector: 'app-my',
  templateUrl: './my.component.html',
  styleUrls: ['./my.component.css']
})
export class MyComponent implements core.OnInit {

  constructor() { }

  ngOnInit() {
  }

}

In this case, it is required to define a variable into which they will be imported to avoid conflicts. To reference the imports in the code, they now always have to be prefixed with that variable name. It's usually better to explicitly import the declarations that are needed, as this allows the build process to exclude unused exports from the final bundle (so-called tree-shaking).

Absolute module name as used in both above examples tells the compiler that the module is actually an NPM package. To import a module from a source code file directly, the path should start with ./ or ../ to indicate current or parent directory respectively:

import { AppComponent } from './app.component';

When importing legacy AMD or CommonJS modules, import statements can still be used, however it's only possible to import complete modules. This is how one would import lodash, for example (assuming npm install lodash was called before):

import * as _ from 'lodash';

This would make all lodash functions available with the usual _ prefix. The _ variable would be declared as any, i.e. no type checking would be available because type definitions are not included in the package. They need to be installed as a separate NPM package:

npm install @types/lodash

Many JavaScript libraries that don't include type definitions, have them available as packages in @types scope. They are automatically published there from the DefinitelyTyped repository.

If your JavaScript library is not packaged as a module at all, you'll need to use the third syntax for the import statement:

import 'rxjs/add/operator/map';

You're not likely to encounter many of those. The example above is for RxJS, which requires you to individually import each operation, as they are not included in the core Observable interface from the rxjs module.

Copyright
Creative Commons License