Demonstrates ng-packagr alongside Nx Workspace.
Develop your libraries and applications in a monorepo. Build distribution-ready libraries in Angular Package Format.
This project was generated with Angular CLI version 1.5.0 using Nrwl Nx.
The following transcript documents reproducible steps to set up this project.
First, create an Nx Workspace. This repository was created with the sandbox install script:
$ curl -fsSL https://raw.githubusercontent.com/nrwl/nx/master/packages/install/install-next.sh | bash -s nx-packaged
Alternatively, you could convert an existing Angular CLI project to Nx Workspace. Please see the Nx documentation how to do that.
For show-casing and documenting your library, create an Angular app in the Nx Workspace.
$ ng generate app one-app
$ ng generate lib one-lib
$ ng generate lib two-lib --ngmodule
Let's generate a component in the Angular library:
$ ng generate component myButton --app=two-lib
We also need to export the component through an Angular module in two-lib.module.ts
:
import { MyButtonComponent } from './my-button/my-button.component';
@NgModule({
imports: [CommonModule],
declarations: [MyButtonComponent],
exports: [MyButtonComponent]
})
export class TwoLibModule {}
And let's also implement some very veeee-ry smart business code in one-lib.ts
:
export class OneLib {
public foo(): string {
return "bar";
}
}
Now, import the libraries with @nx-packaged/one-lib
and @nx-packaged/two-lib
in our application.
Add the TwoLibModule
to app.module.ts
:
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { TwoLibModule } from '@nx-packaged/two-lib';
@NgModule({
imports: [ /* ... */ TwoLibModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
Use the OneLib
class in app.component.ts
:
import { Component, OnInit } from '@angular/core';
import { OneLib } from '@nx-packaged/one-lib';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
business: OneLib = new OneLib();
}
Wire up all the parts in app.component.html
:
<h2>Develop Angular libraries with ng-packagr in a monorepo</h2>
<p>Here is a reusable button component, implemented in a library:</p>
<app-my-button></app-my-button>
<p>Here is reusable business code from a library:</p>
<pre><code>{{ business.foo() }}</code></pre>
Run the app with the standard Angular CLI command:
$ ng serve
Open your browser at http://localhost:4200 and you will see "my-button works!" and "bar" printed on the screen.
Add ng-packagr to development dependencies:
$ yarn add --dev ng-packagr
For each library, add a package.json
in the library folders.
Here is the example for the first library:
{
"$schema": "../../node_modules/ng-packagr/package.schema.json",
"name": "@nx-packaged/one-lib",
"version": "1.0.0",
"ngPackage": {
"lib": {
"entryFile": "index.ts"
},
"dest": "@nx-packaged/one-lib"
}
}
Add a build script to the package.json
in the repository root folder:
"scripts": {
"build:libs": "ng-packagr -p libs/one-lib/package.json"
}
Now, build the library with the following command:
$ yarn build:libs
The build artefacts are written to @nx-packaged/one-lib
in the repository root folder!
Add a configuration for Angular CLI to build the app from Angular Package Format bundles in the @nx-packaged
folder.
The Nx Workspace configuration (by default) builds the app from TypeScript sources in libs/*
.
This is a great way to verify that the application works with the distribution-ready artefacts of the libraries:
$ ng build --app one-app-from-packages --prod
However, it also forces you to re-build the library every time you change the sources!
During development you can now use ng serve
for hot-reloading.
On a CI server and in build scripts, you can use the above ng build
command to verify the libraries in Angular Package Format!
Relevant configuration in .angular-cli.json
:
{
"name": "one-app-from-packages",
"root": "apps/one-app/src",
"outDir": "dist/apps/one-app",
"assets": [
"assets",
"favicon.ico"
],
"index": "index.html",
"main": "main.ts",
"polyfills": "polyfills.ts",
"test": "../../../test.js",
"tsconfig": "../../../tsconfig.packages.json",
"testTsconfig": "../../../tsconfig.spec.json",
"prefix": "app",
"styles": [
"styles.css"
],
"scripts": [],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}