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 and if you want to sign up for Beta please use this link
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.
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.
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.
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).
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
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.
//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
"name": "ComponentsLib",
to
"name": "@owner/ComponentsLib",
(@owner is the same as in step 5 but it has to be all lowercase here!)
and add the following lines
"repository": {
"type": "git",
"url": "git://github.com/OWNER/REPOSITORY.git"
}
When you're finished your package.json
should look something like this
{
"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:
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
ng build
cd ..\..\dist\ComponentsLib\
npm pack
This should result in a tarball being created in your dist folder
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.
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
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:
registry=https://npm.pkg.github.com/owner
Finally, you can bring in the library
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.
npm version [patch | minor | major | ...]
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
Configuring NPM for use with GitHub Package Registry by GitHub
Creating a personal access token for the command line
Configuring your registry settings as an npm Enterprise user
HTH
Story photo by jesse ramirez on Unsplash
Top comments (2)
I follow all the steps and I complete my job! thank you!
Hi Marko!
I followed this tutorial. In the end, after npm publish I get an error:
24 error Only absolute URLs are supported
Any idea why this might happen?