The Angular cache can sometimes get in the way when building an application from a library.
While reading a good write-up on the Angular cache (available since version 13), I was reminded of a problem I hit with this feature when working on libraries. Specifically, when a library is added via npm and its source gets updated but the version stays the same, the cache can cause unexpected behavior.
Setting up the workspace
The project we are examining is an Angular workspace that contains both an application and a library. In typical development, when the app and library live in the same workspace, the local tsconfig points Angular to the library's source files, which removes the need for an npm install.
For the sake of this test, we are taking a different route: publishing the library to a registry that is compatible with npm, and then pulling it down through the standard npm install command.
I had a couple of options available:
- A free cloud-hosted Artifactory instance from jfrog.io. This gives you a domain like
https://username.jfrog.iowhere you can publish packages immediately. - A self-hosted Verdaccio server operating alongside the application.
Although the JFrog approach works well for a one-off trial, it is time-limited. Since we only need something straightforward for this demo, Verdaccio fits the bill nicely.
Standing up the local registry
Getting Verdaccio running is a straightforward process:
- Install the package globally:
npm install -g verdaccio
- Launch Verdaccio
verdaccio
Once it is up, you will see the server running:

You can then open your (still empty) registry; make a note of the commands shown here, as they will be needed for the registry later:

The Angular workspace
Start by scaffolding a minimal Angular workspace that contains both a library and an application.
ng new ng-lib --create-application false
ng g application testapp
ng g library @abo/testlib
With both projects in place, strip out the path aliases from the tsconfig file:
As a result, the only way to consume the library will be through an npm install pulled from our Verdaccio registry.
Note: I’m aware that consuming an Angular library this way is not the recommended pattern during
devmode, but that’s beside the point here.
Publish our library with npm
Before we can push anything, the Verdaccio setup requires creating a user to log in with. Once that’s done, log in, compile the library, and publish it:
npm login - registry http://localhost:4873/
Username: admin
Password:
Email: (this IS public) abo@abo.com
Logged in as admin on http://localhost:4873/.*
Run the publish:lib script to build and publish the Angular library:
"scripts": {
"ng": "ng",
"start:app": "ng serve testapp",
"build:app": "ng build testapp",
"build:lib": "ng build @abo/testlib",
"publish:lib": "ng build @abo/testlib && cd dist/abo/testlib && npm publish --registry http://localhost:4873/",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
The output should resemble the screenshot below:

Meanwhile, the Verdaccio console should show the library has been added to the registry:

Add the library to the application
This part is straightforward. Reset the placeholder Angular app code, pull the library from the registry, and place the single exposed component onto the home page.
npm i @abo/testlib --registry http://localhost:4873/
...
+ @abo/testlib@0.0.1
added 1 package, removed 1 package and audited 992 packages in 8.988s

When adding the library, watch out for IDE auto-import features that can be overly eager. You might end up with an import like this, which would unexpectedly recompile the application:
import { TestlibModule } from "../../../abo/testlib/src/lib/testlib.module";
What you actually want is simply this:
import { TestlibModule } from "@abo/testlib";
Now modify the library and release a new version to observe the changes. I won’t bother with automated semantic versioning; just use the npm version command to bump the library and push it out again.
"scripts": {
"upgrade-version:lib": "cd projects/abo/testlib && npm version patch",
"publish:lib": "ng build @abo/testlib && cd dist/abo/testlib && npm publish --registry http://localhost:4873/",
Confirm the new version (0.0.2) appears in Verdaccio, then reinstall it in your Angular workspace.
npm i @abo/testlib@0.0.2 --registry http://localhost:4873/
The application should now render the latest library build:
Publish the same version of Angular library
So why would you ever want to republish the same version? A typical scenario is when you need to keep a release version in lockstep with an external artifact, such as a Maven package. Regardless of the reason, let’s see what occurs.
Make a code change in the library and attempt a plain republish. You’ll be met with an error like this:
Most npm registries refuse to accept the same version twice. Some expose a setting to override this behavior, but I couldn’t locate such an option in Verdaccio — if someone knows of it, please chime in the comments.
For now, the workaround is to unpublish the npm package and then publish again.
"scripts": {
"unpublish:lib": "npm unpublish @abo/testlib --registry http://localhost:4873/ --force",
So the sequence of tasks is:
- Alter the library component
- Unpublish the library on Verdaccio
- Rebuild and republish the library
- Uninstall / reinstall the library in our Angular workspace
- Launch the application and inspect the outcome
Oddly, nothing appears to have changed — the application still runs against an older build of the library. However, examining the package-lock.json reveals that although the version number hasn’t budged, the integrity hash does differ:
Moreover, checking inside node_modules/@abo/testlib shows the expected source code is present:

So what’s going on? As you might have guessed, the Angular cache is the culprit. Let’s look at how to address it.
First, purge the cache and simply restart the application. This forces a fresh build based on the actual library files in node_modules. Note that in the most recent Angular versions there’s a CLI command that didn’t exist back in version 13.
ng cache clean
rimraf .\.angular\
Needless to say, this isn’t an elegant solution, but it does the job. Alternatively, you can disable caching for the application build. Since the library and application share the workspace, disabling the cache means it’s off for everything — no cache will be used at all. Let’s test this with a fourth library version using the configuration below:
ng cache disable
With caching off, rebuilding the application at any point pulls in whichever library version is actually installed. This isn’t a silver bullet — losing the cache means losing build-time speedups — but it’s worth knowing that even with a correct hash and correct local source, you still can’t be certain which version is baked into the cache. Peeking into the cache shows the code has already been precompiled by Angular:
ng-lib\.angular\cache\13.3.11\babel-webpack (for example)
Wrapping Up
Verdaccio, as a self-hosted npm registry, proves to be a handy tool for validating how you publish an Angular library and for experimenting with the various publish-related options. Usually, the exact version number of a dependency doesn't matter much—compatibility is what counts—but there are moments when it becomes crucial.
Project Files
The complete code used in this guide is available at angular ng-lib on GitHub.







