angularangular-ivynpm-link

Angular 9 application build fails when working with linked libraries


I am developing an application and a bunch of libraries to be used in the application. All are recently upgraded to Angular 9. The libraries are configured to build without ivy and the application is configured to build with ivy, which is as per the upgrade guidelines. The local development process I used to follow is as below -

  1. Build the library and application with --watch.
  2. Make changes in the library. After library build succeeds, copy dist/my-lib and paste it in the application's node_modules folder(this triggers the application build).

This worked till Angular 8 and below but with Angular 9 the application build errors out saying: ERROR in Tried to overwrite path/node_modules/my-lib/lib/services/payment.service.d.ts.__ivy_ngcc_bak with an ngcc back up file, which is disallowed.

So, now I have to additionally do the following -

  1. Stop the application build.
  2. Delete the lib from application's node_modules and then copy paste the new one.
  3. Start the application again.

The angular docs says to use npm link https://angular.io/guide/creating-libraries#linked-libraries. But I am not able to get the meaning of :

the library's package.json configuration points at the correct entry points. For example, main should point at a JavaScript file, not a TypeScript file.

I tried npm link but that doesn't trigger the application build and my changes are not reflected. I would like to know how to resolve the npm link issue or if there is a better way to work with libs and apps together.

My lib's package.json looks like this (Since I am working on a client application, I am only posting the package.json structure):

{
  "name": "my-lib",
  "version": "1.2.0",
  "description": "description",
  "repository": {
    "url": "http://private-nexus-url"
  },
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "build-ci": "npm run test-headless && npm run sonar && npm run publish",
    "test-headless": "ng test --watch=false --browsers=ChromeHeadlessNoSandbox --code-coverage",
    "sonar": "sonar-scanner",
    "test": "ng test --code-coverage",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "build-lib": "ng build --prod my-lib",
    "publish": "npm run build-lib && cd dist/my-lib && npm publish",
    "postinstall": "ngcc"
  },
  "dependencies": {
    "@angular/animations": "^9.1.6",
    "@angular/common": "^9.1.6",
    "@angular/compiler": "^9.1.6",
    "@angular/core": "^9.1.6",
    "@angular/forms": "^9.1.6",
    "@angular/platform-browser": "^9.1.6",
    "@angular/platform-browser-dynamic": "^9.1.6",
    "@angular/router": "^9.1.6",
    ...
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^0.901.5",
    "@angular-devkit/build-ng-packagr": "~0.901.5",
    "@angular/cli": "~9.1.5",
    "@angular/compiler-cli": "~9.1.6",
    "@angular/language-service": "~9.1.6",
    ...
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.ts": [
      "prettier --write",
      "git add"
    ]
  }
}

Solution

  • I had absolutely the same problem. Turns out, the postinstall: ngcc entry you have there is only needed with Angular version 9.0.0

    I'm running 9.1.10, and removing the postinstall: ngcc entry fixed the issue for me.

    Also, I opted for a library re-design, as we're integrating another build system. I really don't like linking libraries. Yes, you evade any checksum problems you might have when developing the library in parallel with your main application (if you include the library as a dependency in your package.json that is). My favorable long-term solution is to have a separated library which deliverable / artifact gets consumed by the application, has a package.json and a corresponding package-lock.json entry.