Automate publish of Angular library as npm package with Azure DevOps

Reading time: 10 minutes

Description

In this post I will explain how to set up continuous deployment of Angular library as npm package with Azure DevOps.

This post will also contain instructions of how to configure the build pipeline, how to configure your Angular application as developer and as a consumer of this package.

I will build two Angular applications for this purpose, so it will be clear to distinguish between the library and consumer applications.

What is required

What’s good about it?

If you are using npm packages you need to host them somewhere. There are several options available. Normally if it’s for public use then it’s free if private or corporate then it obviously costs money. That is their business model.

If you already have an Azure subscription then you have an option to store and host them there. This might be more cost effective but it depends on your needs and availability.

For me it was handy to have an Azure DevOps repo that would have continuous integration trigger enabled, so when I commit a change it would build it and publish it for me.

Once I set up the build pipeline it would do the main stuff related to publishing for me. So the only thing that I would have left to do is set the correct version from my local machine.

Let’s start with initiating a repository for an Angular library on Azure DevOps

Prerequisite: you need a project on Azure DevOps. Go to your Azure DevOps main page.

Once the project is created select Repos from the left side menu. Clone this repo to your computer by copying the url link and using it with your choice of Git GUI.

If you haven’t configured your environment with Angular yet then please do so.

Install Visual Studio Code on your machine. Please use the link below.

https://code.visualstudio.com/download

Then you need to install an appropriate Node.js version that is compatible with your version of Angular.

https://nodejs.org/en/download/

Let’s create an Angular library

Open VS code and navigate to the root folder of the destination where you cloned your repo.

In VS code new terminal type ‘cd destination-of-your-repo’ for example ‘cd C:\Users\dmitr\source\frontend\AzureArtifactsNpmPublish’

Then type ‘ng new AzureArtifactsNpmPublish –directory=./ –skip-install –create-application=false
The name of this app should match the folder name. This way it will use the root folder and won’t nest it within an extra folder.

As a result you get minimum files created plus it is created straight away in the repo root folder. Pretty neat.

Open the project code files in new the window by typing ‘code .

Then type ‘ng g library your-library-name’ for example ng g library azure-npm-ng-lib

Once you have done this and you are happy with the output please commit-push to Azure DevOps repo.

Before we head on to create a pipeline we need to create the feed that we will be using to store and manage our packages

Select Artifacts from the left side menu of the project on Azure DevOps. Click on Create feed and type in the name for your feed. For Visibility it should be Members of name-of-your-organisation. Make sure Upstream sources Include packages from common publish sources is ticked. As for the Scope select Organization.

All of these settings are applicable to our current needs. If you want to limit who can use the feed then you need to select the appropriate Visibility and Scope.

We are ready to create a build pipeline

Go to the Pipelines section and click Create Pipeline. Then select Classic Editor.

Since we created our repo with Azure DevOps we need to select Azure Repos Git. As for the template, Empty Job will fit our needs.

Because we will use Angular Cli we need Node.js. So the first task will be Node.js Installer.

We also need angular cli install, npm install, npm build and npm publish tasks.

For angular cli install task we need to set Command as custom, in Command and arguments enter ‘install @angular/cli -g’

For the npm install task we will leave it as it is.

For the npm build task we need to set for ‘Working folder that contains package.json’ the location of the root of the library folder within the angular project e.g. ‘projects/azure-npm-ng-lib’
Also in here for ‘Command and arguments’ we need to type ‘run build your-library-name –prod’ e.g. run build azure-npm-ng-lib –prod

For npm publish task we need set ‘Working folder that contains package.json’ with the destination after the application was built. We know that build files are placed by default into the ‘dist/project-name’ folder (you can change this outputPath in angular.json). Hence the location of this library would be at ‘dist/azure-npm-ng-lib’ and the full path ‘$(System.DefaultWorkingDirectory)/dist/azure-npm-ng-lib’
As for ‘Registry Location’ we want to set ‘Registry’ and for ‘Target registry’ we need to pick a registry that is preferably organization scoped.

Additionally we need to set CI trigger and Agent Specification for this pipeline.

Different agent specifications would have different build processes and different paths. For our purpose we will use ubuntu-18.04 agent specification.

Click on the Pipeline section and set the appropriate agent specification for your needs.

Select dropdown of Save & Queue and select Save.

Before we can run it we need to allow this pipeline to make changes to Artifacts feed-registry that we selected in the npm publish task as Target registry.

Once this is done you need to go back to Pipelines and click Run Pipeline. Check the images for more info.

Click on the dropdown of Save & Queue.

If the build is successfull we can find our package under Artifacts side menu option.

*make sure tsconfig.lib.json library level enableIvy is set to false i.e. “angularCompilerOptions”: { “enableIvy”: false }
*and package.json contains scripts part with ng build i.e. “scripts”: { “ng”: “ng”, “build”: “ng build” }

Next we need to configure our machine to use artifacts feed-registry for our npm package

Since we will be storing our npm packages in Azure DevOps feed we need to configure our client machine to use this feed.

There is a helpful section of how to do this under Artifacts. Click on Connect feed and then select npm. On the newly opened section click ‘Get the tools’. This should open a slide menu with description of how to do it.

Since we already configured Node.js and npm at the beginning we can skip to Step 2. Copy the command ‘npm install -g vsts-npm-auth –registry https://registry.npmjs.com –always-auth false’

Open a new terminal in VS code and run it. As an extra check if it was installed you can run this command ‘npm list -g –depth 0’ and see if it’s in the list.

There are more details as to how to set up authentication.

Let’s create another Angular app that would consume our npm package

Before that we need to initiate a repository at Azure DevOps. Select Repos in left side menu. Click a dropdown next to the name of your current repository. Select New Repository.

Clone it to your machine and keep in mind the location.

Open VS code and navigate to that location. Run this command ‘ng new AzureArtifactsNpmConsumer –directory=./ –skip-install’
Make sure the name matches the name of the root folder. This way your app won’t be nested within an extra folder.

Next we need to set up our Angular project according to the provided instructions at Azure DevOps Connect to feed section

Add npmrc file to your root project. In my case this would be ‘C:\Users\dmitr\source\frontend\AzureArtifactsNpmConsumer\.npmrc’

Paste in the first command from Connect to feed description into project level npmrc file.

If you open a user level npmrc file which is located at ‘C:\Users\yourName\.npmrc’ and either take a screenshot or copy it somewhere as a backup before it is be modified.

Then run this command in the same project ‘vsts-npm-auth -config .npmrc’.
You will be prompted with a login window. Follow the onscreen instructions to complete the authentication process.

Now if you close and open again the user level npmrc file you would be able to see the difference.

There’s another thing you can do to assist the process of the authentication. Open package.json of the project you are working on and add this bit “refreshVSToken” : “vsts-npm-auth -config .npmrc” into the scripts section. So it would look like so “scripts”: {“refreshVSToken” : “vsts-npm-auth -config .npmrc”}

So in case you are required to refresh the token you can write in terminal ‘npm run refreshVSToken’ and it should reauthenticate you/refresh the token at user level npmrc file.

Basically what is happening behind the scene is every time we run npm install the authentication process kicks in. The token that is in the npmrc file at user lever location is exchanged with registry-feed, so that user machine gets authenticated.

Let’s test if we can install our library package to our Angular consumer app

Please go to the Artifacts at Azure DevOps from there into the package details page and copy the full command to install the package. For example ‘npm install azure-npm-ng-lib@0.0.1’

Use this command in the Angular app where you want to access this npm package.

Next let’s add some code to Angular app and test if we can use npm package code

Open app.component.ts and add this code.

constructor(private _azureNpmNgLibService: AzureNpmNgLibService) {
  }

  ngOnInit(): void {
    this.mainFunc();
  }

  mainFunc(){
    let message = this._azureNpmNgLibService.getMessage();
    console.log(message);
    console.log(123)
  }

So it would look like the image below. Then run ‘ng serve -o’ and open the developer tools. Check if the console/debugger tab contains our ng library npm package message.

Next let’s apply a change and increase the version of lib package

In terminal navigate into folder where library files live and type in ‘npm version 0.0.2’ e.g. C:\Users\dmitr\source\frontend\AzureArtifactsNpmPublish\projects\azure-npm-ng-lib> npm version 0.0.2
This way the package.json version of the library would be updated.

Optionally change the message.

export class AzureNpmNgLibService {

  constructor() { }
  
  getMessage(){
    return "wow what an update! is it the font or a colour :-D"
  }
}

Then commit-push these changes. This should trigger a new build.

This should update our existing package to 0.0.2. You can check this at the Artifacts section.

Next let’s update our Angular consumer app to the latest version of our npm package

In the terminal type in ‘npm outdated’. This would list all the packages that have updated versions.

To update the package to the latest version we need to use ‘npm i azure-npm-ng-lib@latest’ You can also target a particular the version then you need to write what version number like so ‘npm i azure-npm-ng-lib@2.0.0’

Once it is updated to the latest version it is removed from the outdated list. If it’s not the latest it will still be there. For instance if you have 3 versions and your app uses version number two.

Npm follows semantic versioning, more details here.

Conclusion

As you have noticed there are a lot of tips available on Azure DevOps that can guide you through the whole process. As long as you are aware of the process of how npm packages are published to the npm registry all of this should make sense.

If you want an original guide from Microsoft you can find it here.

In my opinion this combination of npm packages and build pipeline with Azure DevOps can be extremely helpful.

It’s one of those things you set up once and you can enjoy the effectiveness of it from then on. In essence you have moved the main heavy lifting(building and publishing) to a cloud based server, so it’s doing it for you.

Moreover you can see the history and related description of changes in a more familiar format.

You can find code for ng library package here and consumer app here.

Publish npm package as Node js module

Reading time: 7 minutes

Description

In this post I will demonstrate how to set up everything you need in order to be able to publish the npm package and use it as a js module in another application.

What is required

  • Npm account
  • Visual studio code

First thing first make sure you have a local environment and workspace for Angular app setup. If you got it then skip the next step.

1 step: Setup local environment and workspace for Angular app

Install Visual Studio Code on your machine. Please use the link below.

https://code.visualstudio.com/download

Then you need to install an appropriate Node.js version that is compatible with your version of Angular.

https://nodejs.org/en/download/

2 step: Create npm account if you haven’t got one

Go here https://www.npmjs.com/signup

TO NOTE: Make sure you confirm your account from your email box.
Or you might have errors when trying to login to npm through VS code.

3 step: Login to your npm account through VS code

Assuming you got VS terminal open

  • type in > npm login
  • follow on screen instructions
  • to accept your input press Enter key
  • when you are typing password it wont show it but it’s there….magic

*npm config file for user – .nprmc, can be found at this location C:\Users\YourName
make sure the registry is set to npm like so registry=https://registry.npmjs.org/

4 step: Create npm package

  • navigate into the root folder using > cd folderDestintation e.g. cd C:\Users\dmitr\source\frontend
  • create new directory by typing > mkdir name-of-your-package
  • navigate into newly created directory using > cd name-of-your-package

  • initiate the package with package.json by typing > npm init
  • use this command to go to code > code .

5 step: Create Angular app

It is a straightforward task once your local environment and workspace is set up.

*workspace here I mean the area on your computer rather than angular workspace

  • Open new window in VS code
  • Go to menu option Terminal > New Terminal
  • Optional: Install the latest Angular version globally with this command > npm install -g @angular/cli
  • navigate into the root folder using > cd folderDestintation e.g. cd C:\Users\dmitr\source\frontend
  • type in > ng new your-app-name
  • go to the root folder where app was created by typing > cd your-app-name
  • then by typing > code .
  • new window should open with the app

*ng-new creates a new app that is default project for new ng workspace
*ng serve -o – opens the application in the browser. Prefix -o opens the application in the browser.

Ok we finished setting things up.

Next we need to add some code to our package.

In the package application add new file index.js, it’s going to be our entry point as we previously configured in package.json.

exports.printMsg = function () {
    console.log("This is a message from the demo package");
}

The whole project should look like this.

We are ready to publish.

Since we logged-in in one of the previous steps we will go straight to publishing.

Unless you have a paid account type with npm we can only publish public packages. In other words a package that can be seen and used by everyone.

We will publish an unscoped public package.

Let’s go to npm and check whether our package is there.

Ok let’s get back to the Angular app and let’s use our newly published npm package.

We need to modify the main app component’s ts file. Then we install our npm package using > npm i your-package-name

You can find a complete command on your npm account on your package details page.

In order to consume our package module with Angular we need to use Node.js require function. We also need type definitions for the node. These should be installed once you run the ‘npm install’ command in the terminal. To be sure you can run > npm i @types/node

For these definitions to be found we need to reference them in tsconfig.app.json file. To note it’s tsconfig.app.json and not tsconfig.json.

Check how to do it for your Angular version. Mine is 11. To check angular version either run ‘ng –version’ or ‘npm list -global –depth 0’

Let’s run the Angular app and see if it uses our npm package.

In the terminal run ‘ng serve -o’ command. This should open the app in the browser. Let’s hit F12/open developer tools and check in the console for our package message.

Next thing is let’s update our npm package and re-publish it.

For this we need to change the version by using the ‘npm version 2.0.0’ command. Npm follows semantic versioning, more details here.

Let’s change the console.log message as well.

Then we need to use the command ‘npm publish’ again. You can check on your npm account if the package version was changed.

Next let’s update our package in the Angular app.

We can check if there are any outdated packages by using the ‘npm outdated‘ command in the terminal of our Angular app.

There are multiple but for now we keep the focus on our npm package.

To update we will use ‘npm i your-package-name@latest’ or ‘npm i your-package-name@1.0.0’ with a particular version.

Alternatively if you want to update all the outdated packages then use the ‘npm update’ command. If nothing gets updated then try ‘npm update -dd’ which will give you more details. Possibly you would need to adjust the maximum version in the package.json file.

Let’s run the Angular app again and see if it uses the latest version of our npm package.

Same as previously ‘ng serve -o’, F12/developer tools and check the Console for the message.

Conclusion

As you can see, creating the npm package is straightforward. Npm documentation is clear and concise.

It is very handy to have regularly used pieces of code placed into the package. You can reuse it anywhere you want. You can share it. Plus it is easy to locate it in case you need to modify it. Finally you are avoiding code duplication. Hence less code. It is especially valuable for front end apps.

Source code can be found here for npm package and here for Angular app.