/SyedSaadQamar96
/in/syed-saad-qamar
/saadqamar01
/saadqamar96
Syed Saad Qamar
Software Engineer
Angular 6 was released. Many of the improvements were to the Angular CLI. The one I have really been looking forward to is the integration of the Angular CLI with ng-packagr to generate and build Angular libraries. ng-packagr is a fantastic tool created by David Herges that transpiles your library to the Angular Package Format.
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.
The Angular Ahead-of-Time (AOT) compiler converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase before the browser downloads and runs that code. Compiling your application during the build process provides a faster rendering in the browser
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
cd awesomePackage
|
Now lets create a feature module and add some resources to it.
ng g module toast ng g service toast/toast -m toast ng g component toast/toast-message --export
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.
Then move the files from your toast feature module to the src folder in lib.
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';
import { CommonModule } from '@angular/common';
import { ToastService } from './toast.service';
import { ToastMessageComponent } from './toast-message/toast-message.component';
@NgModule({
imports: [ CommonModule ],
declarations: [ToastMessageComponent],
exports: [ToastMessageComponent]
})
export class ToastModule {
public static forRoot(config): ModuleWithProviders {
return {
ngModule: ToastModule,
providers: [
ToastService,
{ provide: 'config', useValue: config }
]
};
}
}
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()
export class ToastService {
constructor( @Inject('config') private config ) { }
}
NgPackagr makes a few reasonable requirements of us to perform its magic.
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';
export * from './src/toast.module';
export * from './src/toast.service';
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.
{
"name": "super-toasty",
"version": "0.0.1",
"author": "Syed Saad Qamar <Saadqamar01@gmail.com>",
"license": "MIT",
"peerDependencies": {
"@angular/core": ">=5.0.0",
"@angular/common": ">=5.0.0"
},
"ngPackage": {
"$schema": "./node_modules/ng-packagr/ng-package.schema.json",
"lib": {
"entryFile": "public_api.ts"
},
"dest": "dist"
}
}
NPM Script:
In the package.json (in the root of the project, not lib) add a build script.
"scripts": {
// ...
"build:lib": "ng-packagr -p lib/package.json"
}
Now run npm run build:lib and you should see output like this:
Now it’s time to do some integration testing. Install the local package and serve the Angular app.
npm i lib/dist ng serve
Then import the library in the app module.
import { ToastModule } from 'super-toasty';
@NgModule({
imports: [
ToastModule.forRoot({ brand: 'IOmechs' })
]
})
Because we provided a service, we can inject it into our components.
import { ToastService } from 'super-toasty';
@Component({...})
export class AppComponent {
constructor(toast: ToastService) {
toast.show()
}
}
And because we exported a component, we can use it in our templates.
<toast-message></toast-message>
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 npm publish lib/dist
Congrats! The world is free to use for Angular Package by running:
npm install your-awesome-package