Create a library with Angular and publish it to GitHub Package Registry
Tags: angular, typescript, github, package
Published: 2019-11-08 16:15:28

## How to set up Angular library project, pack it up into an installable package, publish it to GitHub Package Registry and use it in another project

## Intro

*This post will only feature crucial steps that took me some time to get right. I will try to be as concise as possible but still provide enough details to make things easier for you.*

In case you didn't know some time ago GitHub announced their own Package Registry which at the time of writing this article is in beta. There are a couple of reasons why I think GitHub Package Registry (GPR) is great news for developers:

- when you publish to GPR you publish to a known/selected GitHub repository; that way your packages reside next to where their code/implementation is;
- you can publish different packages to the same repository, meaning it doesn't have to be one repo = one package (you just have to set it up correctly and I will show you how to do it later on);
- you can reuse your existing team/organization structure that you have on GitHub not having to replicate everything on NPM (or any another registry, for that matter);
- personally I never liked the NPM experience be it either their search or the administration side of it and would much rather have everything on GitHub,
- using GitHub to host both code and packages just means one (or more) less service you have to configure and learn to use,
- the familiar GitHub experience,
- the GPR is currently in Beta and you can use it free of charge even for private packages; at the moment of writing I don't know of any other online package registry where one can host private packages free of charge,
- you can also use GitHub's registry for other types of packages for instance Gem (Ruby), NuGet (.NET), Maven (Java) and others.

> Learn more about [GitHub Package Registry](https://help.github.com/en/github/managing-packages-with-github-package-registry/about-github-package-registry) and if you want to sign up for  Beta please [use this link](https://github.com/features/package-registry)

## *Lets start*

## 1. Create an empty Angular workspace

We will be using Angular CLI for this. There's been changes in the latest versions of Angular which make this very easy.

Create an empty Angular workspace that can host multiple projects. This will set everything up with correct configuration in `package.json` and `angular.json.`

```cmd
ng new LibraryWorkspace --createApplication=false
```

## 2. Create a new Angular library project within the workspace

This will create `/projects` folder under the workspace root with a library subfolder inside. It will also create a new library module and a service and component to start with.

```cmd
ng g library ComponentsLib --prefix cmpts
```

## 3. (optional) Build (and pack your library)

**Step 3 is only required here as a precaution. Building the library at this point makes sure our Angular workspace and library project were set up correctly by the CLI. You will be rebuilding the library again after you've completed the steps 4-7.**

Now, the previous CLI command will also create files required for the project to become a package at some point:

- `package.json,`
- `ng-package.json,`
- and an important file `src/public-api.ts`

At this point we have everything we need to run a build for this project.

The CLI is smart enough to build the default library first if you also happen to have other projects within the workspace. It will also build for production by default so you don't have to use the `--prod` switch.

```cmd
ng build
```

To pack the library you will switch to the `dist` folder and use `npm pack`. You can do that now OR **do it later after you've set up the GitHub Package Registry settings (steps 4-7).**

```cmd
cd ..\..\dist\ComponentsLib\
npm pack
```

*You could of course make these lines part of a custom script in package.json but I won't go into details on that.*

## 4. Register with GitHub Package Registry

This is very straightforward, just sign up for the beta at
<https://github.com/features/package-registry> and you should be fine.

## 5. Authenticate to GitHub using personal token and store it in your personal .npmrc file

*When I did this for the first time I had issues both with `.npmrc` file not containing what I wanted and with logging into GitHub from cmdline in the first place. Please, take your time and give it a couple of retries if it doesn't work the first time.*

First, you need a token from GitHub and you can get it by following the steps outlined here <https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line>

When you have the token bring up your cmdline/powershell/whatever and do this

```cmd
npm login --scope=@OWNER --registry=https://npm.pkg.github.com
```

> The `@OWNER` is the package scope and you should use either your GitHub account name or your GitHub organization name here (prefixed by the @ sign).

Follow the steps presented at cmdline and login to GitHub with your token.

Succesful login will create .npmrc file in your machine-wide personal folder (on Windows, this will be C:\Users\accountname\\.npmrc).

If you open this file you should find the following lines in it. If the two lines are not present just add them yourself.

```json
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN_HERE
@OWNER:registry=<https://npm.pkg.github.com/>
```

> Again, @OWNER will be replaced with your GitHub username or organization name (prefixed by the @ sign).

## 6. Modify your library files

Certain files in your library code have to be modified with GitHub specific NPM settings/configuration.

Modify your `./projects/ComponentsLib/package.json` like this 
> (that is the `package.json` within the library folder in your Angular workspace NOT the one at the root of your workspace)

change

```json
	"name": "ComponentsLib",
```

to

```json
	"name": "@owner/ComponentsLib",
```

**(@owner is the same as in step 5 but it has to be all lowercase here!)**

and add the following lines

```json
	"repository": {
		"type": "git",
		"url": "git://github.com/OWNER/REPOSITORY.git"
	}
```

When you're finished your `package.json` should look something like this

```json
{
	"name": "@owner/ComponentsLib",
	"version": "0.0.1",
	"peerDependencies": {
		"@angular/common": "^8.2.13",
		"@angular/core": "^8.2.13"
	},
	"repository": {
		"type": "git",
		"url": "git://github.com/OWNER/REPOSITORY.git"
	}
}
```

## 7. Create `.npmrc` file in your library folder

This file is needed by the `npm` to discover your GitHub registry and for `npm` to know where to publish your package when you run `npm publish` later on. You would also check this file into source control.

Create a new `.npmrc` file alongside `package.json` and add this line to it:

```json
registry=https://npm.pkg.github.com/owner
```

> If you plan to have packages that belong to multiple developers or different organizations within the same Angular project you can support multiple scopes by adding the registries in the following format in `.npmrc`:
> ```
> @owner:registry=https://npm.pkg.github.com
> ```

## 8. Build and pack you library

With all those files changed you can now build the library and produce a package for it

```cmd
ng build
cd ..\..\dist\ComponentsLib\
npm pack
```

This should result in a tarball being created in your dist folder

```cmd
owner-componentslib-0.0.1.tgz
```

## 9. Publish the library package to GitHub

You should now be able to publish the package to GitHub repository configured in `package.json` and `.npmrc`.

*`npm` requires you are still logged in with GitHub for this to work.*

```cmd
npm publish
```

## 10. Use the published package in another app

Go to your GitHub repository and click on the packages link (should be next to commits and branches tabs) and it will take you to a list of published packages within that repo.

It will also be accessible by URL

```cmd
https://github.com/owner/repository/packages
```

Clicking on a package will give you the instructions for installing it, either via `npm i` or adding it to `package.json`.

Now, to make the installation work the destination app will also need a `.npmrc` file so it can find your GitHub registry (unless you have registered it in your personal `.npmrc` file).

At the root of your app (the app where you want to install your library package) create `.npmrc` file with the following contents:

```json
registry=https://npm.pkg.github.com/owner
```

Finally, you can bring in the library

```cmd
npm install @owner/componentslib
```

You would then import the `ComponentsLibModule` to one of your Angular modules in your destination app (be it the root `app.module` or any other module).

## 11. Publishing new versions of the library

When you modify your library and want to update the package with a newer version you will have to update the version (semver) number for it.

You can simply use `npm version` command for that and it will automatically advance your version number.

```cmd
npm version [patch | minor | major | ...]
```

> [The npm version command docs](https://docs.npmjs.com/cli/version)

You will then want to rerun the build, pack & publish step.

## Finish

Hopefully this post will help others to set up GitHub as their package registry and contribute to module/component reuse either within private or public teams.

Should you have any questions or comments feel free to post them below.

Also, here is a list of links that helped me while I struggled with setting this up for the first time:

[The excellent Creating a Library series by Todd Palmer](https://blog.angularindepth.com/creating-a-library-in-angular-6-87799552e7e5)

[About GitHub Package Registry](https://help.github.com/en/github/managing-packages-with-github-package-registry/about-github-package-registry)

[Configuring NPM for use with GitHub Package Registry by GitHub](https://help.github.com/en/github/managing-packages-with-github-package-registry/configuring-npm-for-use-with-github-package-registry)

[Creating a personal access token for the command line](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line)

[Configuring your registry settings as an npm Enterprise user](https://docs.npmjs.com/configuring-your-registry-settings-as-an-npm-enterprise-user)

HTH

*Story photo by jesse ramirez on Unsplash*