How to create Angular library?

In our development work with Angular we are using many different libraries. Libraries like Angular Material, NGX Bootstrap, Prime NG2 Charts and many others save us lot of time and speed up our workflow. But what is library in Angular and how to create your own Angular Library? I’ll try to explain it in this article.

In computer science, a library is a collection of non-volatile resources used by computer programs, often for software development. These may include configuration data, documentation, help data, message templates, pre-written code and subroutines, classes, values or type specifications.
Wikipedia

Wikipedia definition of library can be little confusing for beginners. Much simpler definition is that Library is set of reusable resources. Those resources are mostly set of different functions. For example in most programming languages we have Math libraries which are sets of functions for different Math operations. In this case we don’t have to create our own functions to do Math operations but we can use those provided by programming language. If you are working on big complex applications it’s always good practice to put code into libraries so it can be reused later.

What is Angular Library?

Angular Library is collection of modules, components, services, pipes and interfaces. Depending on what is their function and on their content I divide Angular Libraries into two main types.

Component Libraries

Most of Angular Libraries are collections of different Angular components. Those Libraries speed up building of user interfaces by providing finished, ready to use, interface components. One of those is Angular Material Library, which comes packaged with ready to use Material Design components like Toolbars, Sidebars, Buttons etc.



Service Libraries

Service Angular Libraries are collections of services. For example one of those libraries is wp-api-angular library which is set of services providing functions for using WordPress REST API in your Angular Application.

How to create Angular library?

Before Angular 6

Since Angular 6

If you have ever tried to create Angular Library before release of Angular 6 then you know how difficult problem it could present. Every developer had his own approach. I used generator-angular2-library yeoman generator. It offered simple but at times complex way of generating Angular Library.

Angular CLI v6 comes with library support via ng-packagr plugged into the build system we use in Angular CLI, together with schematics for generating a library. Angular CLI now has set of tools to help you with creating Angular Library.

How does it work?

Let’s create Angular Library which will have service, component and interface. It is simple library which will provide functions to call WordPress REST API on our blog and return list of posts or post by it’s id.

Start by generating new workspace using ng new command.

Console
 ng new virtuooza

When we use the new Angular 6 CLI, the default environment is now a workspace that allows for the development of multiple applications and libraries in a single workspace. When you add new applications and/or libraries, you are creating project items. A project item has a specific type to indicate whether it is an application or a library.

Now we can generate new virtuooza-cli library and add it to our workspace.

Console
cd virtuooza
ng generate library virtuooza-cli

New projects folder is created in our workspace with our virtuooza-cli library inside. If you check virtuooza-cli/src/lib folder you will see that Angular CLI has already generated for us example service, component and module.

Add interfaces

Let’s create a projects/virtuooza-cli/src/lib/virtuooza-cli.models.ts file with all the interfaces. We won’t be fetching all post properties so this will be pretty simple setup.

projects/virtuooza-cli/src/lib/virtuooza-cli.models.ts
export interface Content {
  rendered: string;
}

export interface Post {
  id: number;
  date: Date;
  title: Content;
  content: Content;
  excerpt: Content;
}

Add Service

Angular CLI already added example service when it generated our library. We will just edit already created virtuooza-cli.service, define our API URL and two functions. First one will return single post by its id and second will return list of posts from our blog.

projects/virtuooza-cli/src/lib/virtuooza-cli.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

import { Post } from './virtuooza-cli.models';

@Injectable({
  providedIn: 'root'
})
export class VirtuoozaCliService {

  private _apiUrl = 'https://virtuooza.com/wp-json/wp/v2/posts/';

  constructor(private _http: HttpClient) { }

  /* Return post by id */
  getPost(id): Observable<Post> {
    return this._http.get<Post>(this._apiUrl + id);
  }

  /* Return list of posts */
  getPosts(): Observable<Post[]> {
    return this._http.get<Post[]>(this._apiUrl);
  }
}

If you are confused with providedIn: ‘root’ property in @Injectable you should know that it’s added in Angular 6. It allows your service to be provided to any component without registering it in any angular module. This is useful because it makes it easy for you to remove library from your project if it’s not needed anymore.

When you provide the service at the root level, Angular creates a single, shared instance of HeroService and injects into any class that asks for it.
https://angular.io

Add component

Angular CLI already generated example component for us but I don’t like it’s name so I’ll remove it and add new component. Adding component to your library is really easy with help of Angular CLI:

Console
ng generate component virtuooza-list --project=virtuooza-cli --flat -is -it

We used ng generate component command but we also specified project in which we want to add new component. In this case it is our library virtuooza-cli. This will be simple component which will return list of posts from our blog using service we have already defined.

What about lib prefix? If you don’t specify different prefix when you generate your library using Angular CLI default prefix which will be added to library components and directives is lib. If you want to specify different prefix for your library you can do it when you are generating your library ng generate library virtuooza-cli –prefix=virtu.

You should always specify prefix when you generate your library. But even if you forget to do it Angular CLI will add lib as prefix.

projects/virtuooza-cli/src/lib/virtuooza-list.component.ts
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';

import { Post } from './virtuooza-cli.models';
import { VirtuoozaCliService } from './virtuooza-cli.service';

@Component({
  selector: 'lib-virtuooza-list',
  template: `
    <div *ngIf="posts$">
      <div class="card" *ngFor="let post of posts$ | async">
        <h2>{{ post.title.rendered }}</h2>
        <p>{{ post.date | date }}</p>
        <p [innerHTML]="post.excerpt.rendered"></p>
      </div>
    </div>
  `,
  styles: []
})
export class VirtuoozaListComponent implements OnInit {

  posts$: Observable<Post[]>;

  constructor(private _service: VirtuoozaCliService) { }

  ngOnInit() {
    this.posts$ = this._service.getPosts();
  }
}



Edit module

Since we are using HttpClient in service to fetch posts we have to import HttpClientModule in our library’s module file. We need to import CommonModule also because we are using *ngIf angular directive in lib-virtuooza-list component.

projects/virtuooza-cli/src/lib/virtuooza-cli.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';

import { VirtuoozaListComponent } from './virtuooza-list.component';

@NgModule({
  imports: [
    CommonModule,
    HttpClientModule
  ],
  declarations: [VirtuoozaListComponent],
  exports: [VirtuoozaListComponent]
})
export class VirtuoozaCliModule { }

Export our library resources

To provide access to our interfaces and component outside of our library we need to export them in public_api.ts. Edit projects/virtuooza-cli/src/public_api.ts and add export * from ‘./libs/virtuooza-cli.models’; and export * from ‘./lib/virtuooza-list.component’;. You will need to export all new components, services or interfaces you add to your library in the same way.

projects/virtuooza-cli/src/public_api.ts
/*
 * Public API Surface of virtuooza-cli
 */

export * from './lib/virtuooza-cli.service';
export * from './lib/virtuooza-list.component';
export * from './lib/virtuooza-cli.module';
export * from './lib/virtuooza-cli.models';

Build

Before our Angular Library can be used we need to build it. Angular CLI now supports building individual projects inside workspace. We build our library like this:

Console
ng build virtuooza-cli

Angular CLI created dist directory with our library files inside. Our library isn’t placed with other libraries into node_modules directory but we can import it into our app.module.ts just like it’s there. This is possible thanks to paths entry added into tsconfig.json file in the root of our project by the Angular CLI.

tsconfig.json
 "paths": {
      "virtuooza-cli": [
        "dist/virtuooza-cli"
      ],
      "virtuooza-cli/*": [
        "dist/virtuooza-cli/*"
      ]
    }

When you have your library published in NPM repository and install it from NPM you can just simply remove paths entry and start using newly published version without changing any imports in your application files.

Use it

Time to test our Angular Library in application. Import VirtuoozaCliModule in app.module.ts and add it in imports array. That’s all we need to do to make our library components and services available in application.

src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { VirtuoozaCliModule } from 'virtuooza-cli';

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

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



After we add lib-virtuooza-list component into our app.component.html file you will see list of posts from our blog.

src/app/app.component.html
<lib-virtuooza-list></lib-virtuooza-list>

Our Angular Library is working and it’s ready to be shared with developers around the world. We just need to publish it on NPM.



Share with your friends