DEV Community

Alain Boudard for This is Angular

Posted on • Edited on

Using Angular cache with library

Angular cache and library

How the angular cache can interfere with the build of an application.

I was reading this nice article about Angular cache (starting with version 13), and it reminded me that I stumbled upon an issue with this feature regarding the development of libraries. Basically, if you install a library with npm, if the source code of the library changes but not the version number, what happens.

The project

The Angular project we will be using consists of a workspace in which there will be a library and an application. Normally, when we develop an Angular library in the same workspace than the application, the local tsconfig file takes care of telling Angular where the source code is so that we don’t need to install the library.

For this project, we won’t be using the library directly, but we will publish it to any kind of registry compatible with npm and install it with npm install command.

I had 2 tools available :

  • A free demo account with jfrog.io that allows you to host your Artifactory registry in the cloud. You get a domain name like https://username.jfrog.io and can publish right away.
  • A local install of Verdaccio running next to our app.

The first option is really nice to test, but it’s limited in time, and our actual needs for this demo are very simple and Verdaccio is more than enough.

The local npm registry

Using verdaccio is very simple :

  • Install the package globally :
npm install -g verdaccio
Enter fullscreen mode Exit fullscreen mode
  • Run verdaccio
verdaccio
Enter fullscreen mode Exit fullscreen mode

You should see the server running :
Local verdaccio registry running
And access your empty registry (note these commands for using this registry for later) :
verdaccio panel

The Angular workspace

Let’s create a very simple angular workspace and add a library and an application.

ng new ng-lib --create-application false
ng g application testapp
ng g library @abo/testlib
Enter fullscreen mode Exit fullscreen mode

This way we have both projects in the workspace. Let’s remove the path configuration from the tsconfig file :
Angular library path in tsconfig

This way, we will only use the library through the npm install, using our Verdaccio registry.

Note : I’m aware that using an Angular library this way is not the proper way when you’re in dev mode but this is not the point here.

Publish our library with npm

We must have followed the Verdaccio instructions to create the user we will login with. Then we can actually login, build 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/.*
Enter fullscreen mode Exit fullscreen mode

Building and publishing the angular library with the publish:lib script :

"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"
  },
Enter fullscreen mode Exit fullscreen mode

The result must look like that :
Angular build of a local library and publish to registry
And in our Verdaccio console, we should see the library added to the registry :
Verdaccio angular published library

Add the library to the application

This is pretty easy, let’s clean up the code of the placeholder Angular application, install our library via the registry and add the single component exposed to our 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
Enter fullscreen mode Exit fullscreen mode

The app.component with the library component
Be careful when adding your library because some IDEs have an auto-import feature that is a little bit too fast to find the proper import. You could have something like that (and this would trigger application recompile when unwanted) :

import { TestlibModule } from "../../../abo/testlib/src/lib/testlib.module";
Enter fullscreen mode Exit fullscreen mode

When you would only want this :

import { TestlibModule } from "@abo/testlib";
Enter fullscreen mode Exit fullscreen mode

Let’s alter the library and publish a new version to see the changes. I don’t use any automatic semantic versioning system, let’s use simply the npm version command to upgrade the library and then re publish.

"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/",
Enter fullscreen mode Exit fullscreen mode

Check that your library is up to date in Verdaccio and re install in your Angular workspace (the new 0.0.2 version).

npm i @abo/testlib@0.0.2 --registry http://localhost:4873/
Enter fullscreen mode Exit fullscreen mode

The application should show the new library version :

New angular library version

Publish the same version of Angular library

Now, why would we want to publish the same version ? This could be a typical use case when you want to strictly control a release version, maybe aligned with a Maven package or something else. Anyway, let’s see what happens.

If you alter your code in the library and simply try to re publish it, you will get an error like this :

npm publish package same version error

Most of the npm registries prevent from publishing the same version, some allow you to set options to override, but I didn’t find the option in verdaccio — if anyone knows about it, feel free to say it in the comments.

Anyway, we will simply unpublish the npm package and re publish it.

"scripts": {
    "unpublish:lib": "npm unpublish @abo/testlib --registry http://localhost:4873/ --force",
Enter fullscreen mode Exit fullscreen mode

So the tasks here are :

  • Alter the library component
  • Unpublish the library on Verdaccio
  • Re build et re publish the library
  • Uninstall / re install the library in our Angular workspace
  • Run the application and see the result

Still the same angular library version

Well, there is no difference, the application was built with a previous verison of the library. Yet, when we take a look at the package-lock.json we see that even if the version number is the same, the integrity property hash is different :

Same npm version but different archive

And actually, if we take a look in the node_modules/@abo/testlib we see that the source code is the one we should expect :

This is the proper updated source code of our Angular library
So, what happend ? Well as you guessed, the angular cache is responsible for this, let’s see how we can act on this.

Remove the cache and then simply re start the application, which will force the build based on the actual node_modules version of the library. In the latest versions, there is a CLI command that doesn’t exist in version 13.

ng cache clean

rimraf .\.angular\
Enter fullscreen mode Exit fullscreen mode

Updated version of the Angular library

Of course this solution is far from excellent, but at least it works. The alternative would be to deactivate the cache on the build of the application (we don’t care about the build of the library, but since we are in a single workspace, no cache will be used at all). We will try with a fourth version of the library and the following configuration :

ng cache disable
Enter fullscreen mode Exit fullscreen mode

Angular cache disabled

Then we can rebuild the application anytime we want and whatever the version of the library, we will have the proper version. Of course it’s not a perfect solution because caching would improve our build time, but it’s good to know that even if the hash of the library is ok, even if the local source code is ok, well you really can’t know what version is actually stored in the cache, because if we look into the cache, we can see that the code is already precompiled by Angular :

ng-lib\.angular\cache\13.3.11\babel-webpack (for example)
Enter fullscreen mode Exit fullscreen mode

Angular precompiled cache

Conclusion

This local npm registry Verdaccio is really nice to test your Angular library publish skills and parameters. In many cases we don’t really care about the actual version of our libraries other than compatibility, but sometimes, well things happen.

Source code

Source code for this article can be found here angular ng-lib

Top comments (0)