Creating Libraries

You can create and publish new libraries to extend Angular functionality. If you find that you need to solve the same problem in more than one app (or want to share your solution with other developers), you have a candidate for a library.

A simple example might be the about section of your application, where you tell the user what you do and who you are. This would probably be the same across all your applications.

Getting started

To get started creating Angular libraries, use the Angular CLI to generate a new library skeleton with the following command:

``ng generate library my-lib``

This command creates the projects/my-lib folder in your workspace, which contains a component and a service inside an NgModule. The workspace configuration file, angular.json, will automatically be updated with a project of type 'library'.

You can build, test, and lint the project with CLI commands:

``` ng build my-lib
ng test my-lib
    ng lint my-lib ```

Notice that the configured builder for the project is different from the default builder for regular angular projects. This builder, among other things, ensures that the library is always built with the AoT compiler, without the need to specify the --prod flag.

Aside building and compiling, to make library code reusable you must define a public API for it. This "user layer" defines what is available to consumers of your library. A user of your library should be able to access public functionality (such as NgModules, service providers and general utility functions) through a single import path.

The public API for your library is maintained in the `public-api.ts` file in your library folder. Anything exported from this file is made public when your library is imported into an application. Use an NgModule to expose services and components.

In addition to the public API, a good documentation is very vital for users who will consume your library. Your library should supply a well detailed documentation (typically a README file) for installation and maintenance.

Refactoring parts of an app into a library

A working application can be converted into a library, or parts of a working application can also be converted to a library. To make your solution reusable, you need to adjust it so that it does not depend on app-specific code. Here are some things to consider in migrating application functionality to a library.

  • Declarations such as components and pipes should be designed as stateless, meaning they don't rely on or alter external variables. If you do rely on state, you need to evaluate every case and decide whether it is application state or state that the library would manage.
  • Any observables that the components subscribe to internally should be cleaned up and disposed of during the lifecycle of those components.
  • Components should expose their interactions through inputs for providing context, and outputs for communicating events to other components.
  • Services should declare their own providers (rather than declaring providers in the NgModule or a component), so that they are tree-shakable. This allows the compiler to leave the service out of the bundle if it never gets injected into the application that imports the library.
  • Multiple registrations of NgModule should be done using forRoot() and forChild() patterns provided by the RouterModule.
  • Check all internal dependencies.
    • For custom classes or interfaces used in components or service, check whether they depend on additional classes or interfaces that also need to be migrated.
    • Similarly, if your library code depends on a service, that service needs to be migrated.
    • If your library code or its templates depend on other libraries (such an Angular Material, for instance), you must configure your library with those dependencies.

Reusable code and schematics

A library typically includes reusable code that defines components, services, and other Angular artifacts (pipes, directives, and so on) that you simply import into a project. A library is packaged into an npm package for publishing and sharing, and this package can also include schematics that provide instructions for generating or transforming code directly in your project, in the same way that the CLI creates a generic skeleton app with ng generate component. A schematic that is combined with a library can, for example, provide the Angular CLI with the information it needs to generate a particular component defined in that library.

What you include in your library is determined by the kind of task you are trying to accomplish. For example, if you want a dropdown with some canned data to show how to add it to your app, your library could define a schematic to create it. For a component like a dropdown that would contain different passed-in values each time, you could provide it as a component in a shared library.

Suppose you want to read a configuration file and then generate a form based on that configuration. If that form will need additional customization by the user, it might work best as a schematic. However, if the forms will always be the same and not need much customization by developers, then you could create a dynamic component that takes the configuration and generates the form. In general, the more complex the customization, the more useful the schematic approach.

Integrating with the CLI

A library can include schematics that allow it to integrate with the Angular CLI.

  • Include an installation schematic so that ng add can add your library to a project.
  • Include generation schematics in your library so that ng generate can scaffold your defined artifacts (components, services, tests, and so on) in a project.
  • Include an updated schematic so that ng update can update your library's dependencies and provide migrations for breaking changes in new releases.

Publishing your library

Use the Angular CLI and the npm package manager to build and publish your library as an npm package. Libraries are built in AoT mode by default, so you do not need to specify the -prod flag when building for publication.

```ng build my-lib
cd dist/my-lib
npm publish```

NB: Publishing a library in NPM entails creating a user account with NPM and following their sample guide

Using your own library in apps

You don't have to publish your library to the npm package manager in order to use it in your own apps, but you do have to build it first.

To use your own library in an app:

Build the library. You cannot use a library before it is built.

```ng build my-lib```

In your apps, import from the library by name:

```import { myExport } from 'my-lib';```

Building and rebuilding your library

The build step is important if you haven't published your library as an npm package and then installed the package back into your app from npm. For instance, if you clone your git repository and run npm install, your editor will show the my-lib imports as missing if you haven't yet built your library.

When you import something from a library in an Angular app, Angular looks for a mapping between the library name and a location on disk. When you install a library package, the mapping is in the node_modules folder. When you build your own library, it has to find the mapping in your tsconfig paths.

Generating a library with the Angular CLI automatically adds its path to the tsconfig file. The Angular CLI uses the tsconfig paths to tell the build system where to find the library.

If you find that changes to your library are not reflected in your app, your app is probably using an old build of the library.

You can rebuild your library whenever you make changes to it, but this extra step takes time. Incremental builds functionality improves the library-development experience. Every time a file is changed a partial build is performed that emits the amended files.

Incremental builds can be run as a background process in your dev environment. To take advantage of this feature add the --watch flag to the build command:

ng build my-lib --watch

Previous: Schematics
Next: Using Published Libraries

Follow us on Facebook and Twitter for latest update.