{ "id": "guide/creating-libraries", "title": "Creating libraries", "contents": "\n\n\n
\n mode_edit\n
\n\n\n
\n

Creating librarieslink

\n

This page provides a conceptual overview of how you can create and publish new libraries to extend Angular functionality.

\n

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.\nA simple example might be a button that sends users to your company website, that would be included in all apps that your company builds.

\n

Getting startedlink

\n

Use the Angular CLI to generate a new library skeleton in a new workspace with the following commands.

\n\n ng new my-workspace --create-application=false\n cd my-workspace\n ng generate library my-lib\n\n

The ng generate command creates the projects/my-lib folder in your workspace, which contains a component and a service inside an NgModule.

\n
\n

For more details on how a library project is structured, refer to the Library project files section of the Project File Structure guide.

\n

You can use the monorepo model to use the same workspace for multiple projects.\nSee Setting up for a multi-project workspace.

\n
\n

When you generate a new library, the workspace configuration file, angular.json, is updated with a project of type library.

\n\n\"projects\": {\n ...\n \"my-lib\": {\n \"root\": \"projects/my-lib\",\n \"sourceRoot\": \"projects/my-lib/src\",\n \"projectType\": \"library\",\n \"prefix\": \"lib\",\n \"architect\": {\n \"build\": {\n \"builder\": \"@angular-devkit/build-angular:ng-packagr\",\n ...\n\n

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

\n\n ng build my-lib --configuration development\n ng test my-lib\n ng lint my-lib\n\n

Notice that the configured builder for the project is different from the default builder for app projects.\nThis builder, among other things, ensures that the library is always built with the AOT compiler.

\n

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.

\n

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

\n

Your library should supply documentation (typically a README file) for installation and maintenance.

\n

Refactoring parts of an app into a librarylink

\n

To make your solution reusable, you need to adjust it so that it does not depend on app-specific code.\nHere are some things to consider in migrating application functionality to a library.

\n\n\n

Integrating with the CLI using code-generation schematicslink

\n

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.\nA library is packaged into an npm package for publishing and sharing.\nThis 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 new component with ng generate component.\nA schematic that is packaged with a library can, for example, provide the Angular CLI with the information it needs to generate a component that configures and uses a particular feature, or set of features, defined in that library.\nOne example of this is Angular Material's navigation schematic which configures the CDK's BreakpointObserver and uses it with Material's MatSideNav and MatToolbar components.

\n

You can create and include the following kinds of schematics.

\n\n

What you include in your library depends on your task.\nFor example, you could define a schematic to create a dropdown that is pre-populated with canned data to show how to add it to an app.\nIf you want a dropdown that would contain different passed-in values each time, your library could define a schematic to create it with a given configuration. Developers could then use ng generate to configure an instance for their own app.

\n

Suppose you want to read a configuration file and then generate a form based on that configuration.\nIf that form will need additional customization by the developer who is using your library, it might work best as a schematic.\nHowever, if the form 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.\nIn general, the more complex the customization, the more useful the schematic approach.

\n

To learn more, see Schematics Overview and Schematics for Libraries.

\n

Publishing your librarylink

\n

Use the Angular CLI and the npm package manager to build and publish your library as an npm package.

\n

Before publishing a library to NPM, build it using the production configuration which uses the older compiler and runtime known as View Engine instead of Ivy.

\n\nng build my-lib\ncd dist/my-lib\nnpm publish\n\n

If you've never published a package in npm before, you must create a user account. Read more in Publishing npm Packages.

\n
\n

For now, it is not recommended to publish Ivy libraries to NPM because Ivy generated code is not backward compatible with View Engine, so apps using View Engine will not be able to consume them. Furthermore, the internal Ivy instructions are not yet stable, which can potentially break consumers using a different Angular version from the one used to build the library.

\n

When a published library is used in an Ivy app, the Angular CLI will automatically convert it to Ivy using a tool known as the Angular compatibility compiler (ngcc). Thus, publishing your libraries using the View Engine compiler ensures that they can be transparently consumed by both View Engine and Ivy apps.

\n
\n\n

Managing assets in a librarylink

\n

Starting with version 9.x of the ng-packagr tool, you can configure the tool to automatically copy assets into your library package as part of the build process.\nYou can use this feature when your library needs to publish optional theming files, Sass mixins, or documentation (like a changelog).

\n\n

Linked librarieslink

\n

While working on a published library, you can use npm link to avoid reinstalling the library on every build.

\n

The library must be rebuilt on every change.\nWhen linking a library, make sure that the build step runs in watch mode, and that the library's package.json configuration points at the correct entry points.\nFor example, main should point at a JavaScript file, not a TypeScript file.

\n

Use TypeScript path mapping for peer dependencieslink

\n

Angular libraries should list all @angular/* dependencies as peer dependencies.\nThis ensures that when modules ask for Angular, they all get the exact same module.\nIf a library lists @angular/core in dependencies instead of peerDependencies, it might get a different Angular module instead, which would cause your application to break.

\n

While developing a library, you must install all peer dependencies through devDependencies to ensure that the library compiles properly.\nA linked library will then have its own set of Angular libraries that it uses for building, located in its node_modules folder.\nHowever, this can cause problems while building or running your application.

\n

To get around this problem you can use TypeScript path mapping to tell TypeScript that it should load some modules from a specific location.\nList all the peer dependencies that your library uses in the workspace TypeScript configuration file ./tsconfig.json, and point them at the local copy in the app's node_modules folder.

\n\n{\n \"compilerOptions\": {\n // ...\n // paths are relative to `baseUrl` path.\n \"paths\": {\n \"@angular/*\": [\n \"./node_modules/@angular/*\"\n ]\n }\n }\n}\n\n

This mapping ensures that your library always loads the local copies of the modules it needs.

\n

Using your own library in appslink

\n

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.

\n

To use your own library in an app:

\n\n

Building and rebuilding your librarylink

\n

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.\nFor 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.

\n
\n

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.\nWhen 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.

\n

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

\n
\n

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.

\n

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

\n

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:

\n\nng build my-lib --watch\n\n
\n

The CLI build command uses a different builder and invokes a different build tool for libraries than it does for applications.

\n\n

The two build systems support different things, and even where they support the same things, they do those things differently.\nThis means that the TypeScript source can result in different JavaScript code in a built library than it would in a built application.

\n

For this reason, an app that depends on a library should only use TypeScript path mappings that point to the built library.\nTypeScript path mappings should not point to the library source .ts files.

\n
\n\n \n
\n\n\n" }