You have unlimited access as a PRO member
You are receiving a free preview of 3 lessons
Your free preview as expired - please upgrade to PRO
Contents
Recent Posts
- Object Oriented Programming With TypeScript
- Angular Elements Advanced Techniques
- TypeScript - the Basics
- The Real State of JavaScript 2018
- Cloud Scheduler for Firebase Functions
- Testing Firestore Security Rules With the Emulator
- How to Use Git and Github
- Infinite Virtual Scroll With the Angular CDK
- Build a Group Chat With Firestore
- Async Await Pro Tips
Build an Angular Library With NgPackagr
Episode 103 written by Jeff DelaneyIn this lesson, I will show you how to build an Angular Library from scratch using NgPackagr.
My main motivation for this article is that Google Analytics recently changed their main API to gtag.js, but solid Angular libraries were lacking, so I decided to build one from scratch. NgPackagr made the bundling process very easy.
Angular packages are standardized by the Angular Package Format, but generating this output manually is difficult. NgPackager will do all the stuff you don’t want to deal with, like generating the bundles (FESM2015, FESM5, and UMD), creating your types, and ensuring that the end result is AOT compatible.
Full source code Angular NgPackager Tutorial.
IMPORTANT Update for Angular v6.0
Angular CLI v6.0 introduced a new command that will save much of the manual configuration required in the this lesson.
# Generate a library |
While the code in the following steps is still valid, I highly recommend using the CLI to eliminate the manual creation of files.
Step 1 - Build an Angular CLI Project
Let’s generate an app and give it a module and component. The app itself is not part of the library, but will be used for integration testing.
ng new awesomePackage --routing |
Now lets create a feature module and add some resources to it.
ng g module toast |
I’m not going to cover how to build the actual app, but it’s just simple toast notification system. It includes a service that controls he message content/visibility and component that shows the actual message to the end user.
Step 2 - Setup your Lib
Create a folder in the root of your project named lib (or whatever you want) - this is where the source code for our library will exist.
Inside this the lib folder create the following elements.
- src/ source code
- package.json package definition
- public_api.ts to export your public Angular modules
- README.md so people know how to use your library
Then move the files from your toast feature module to the src folder in lib.
Creating an Angular Module for Root
The library’s module works mostly like it does in Angular, but the main difference is the way services are provided. In many cases, developers may need to pass configuration options to a library. This can be accomplished by defining a forRoot
method, which returns an object typed to ModuleWithProviders interface.
import { NgModule, ModuleWithProviders } from '@angular/core'; |
The end-user of the lib would use this module in their app like so:
ToastModule.forRoot({ apiKey: 'shhhhh' }) |
Injecting Configuration Options
If we need to use the data passed to the module via forRoot
, we can do so by using the @Inject
decorator in the constructor.
@Injectable() |
Step 3 - Configure for NgPackagr
NgPackagr makes a few reasonable requirements of us to perform its magic.
Install
Install NgPackagr.
npm install ng-packagr --save-dev |
Public API
In lib/public_api.ts export the interfaces that the developer should be able to access.
export * from './src/toast-message/toast-message.component'; |
lib/package.json
In the lib/package.json we will define our library’s NPM details. Make sure the name of the package is available on NPM if your project is open source.
The special section is ngPackage
, which is used by NgPackagr to locate the public API file for your project.
Your package should not have any dependendcies, only peerDependencies and devDependencies
{ |
NPM Script
In the package.json (in the root of the project, not lib) add a build script.
"scripts": { |
Now run npm run build:lib
and you should see output like this:
Step 4 - Do some Integration Testing
Now it’s time to do some integration testing. Install the local package and serve the Angular app.
npm i lib/dist |
Then import the library in the app module.
import { ToastModule } from 'super-toasty'; |
Because we provided a service, we can inject it into our components.
import { ToastService } from 'super-toasty'; |
And because we exported a component, we can use it in our templates.
<toast-message></toast-message> |
Step 5 - Publish to NPM
Publishing to NPM is super easy. First, make sure you’re logged into your account, then run the publish command pointing to lib/dist.
npm whoami |
Congrats! The world is free to use for Angular Package by running:
npm install your-awesome-package |
Best Practices when Writing Angular Libraries
On a final note, let’s talk about some best practices when building angular libraries.
Don’t touch the DOM
If your library touches he DOM directly, such as document.getElementById('foo')
, it will break other developer’s apps when they use Angular with server or web worker platforms. If you must do this, wrap your code in a try/catch block.
Strong Type
Your public API should be strong-typed. Developers like Angular because of the awesome tooling provided by TypeScript. Try to make end-users of your package as happy as possible by leveraging types.
Bad
someMethod(options: any) { ... } |
Good
export interface Options { |
Write Documentation
Duh!
Write Unit and Integration Tests
As your library grows in complexity it becomes easy to introduce bugs and regressions. Write some tests an implement use continuous integration to ensure every commit meets your spec. Tests will also make it easier for other developers to contribute to the codebase without breaking everything.