angulartypescriptangular-libraryng-packagr

Angular library secondary entry points that reference each other , use via npm link


All the examples I find for developing libraries in Angular always have the library in the same workspace as the app, but I can't do so.

I have three different Angular 18 workspaces, one for libraryA, one for libraryB that uses libraryA and the other one for an app that uses the two libraries via npm link.

This is the general structure:

ws2
└── src/
    └── app/
        └── component.ts

ws2
└── projects/
    └── libraryA/
        └── featureA1/
            ├── ...
            ├── index.ts
            ├── ng-package.json
            └── public-api.ts
        └── featureA2/
            ├── ...
            ├── index.ts
            ├── ng-package.json
            └── public-api.ts

ws3
└── projects/
    └── libraryB/
        └── featureB1/
            ├── ...
            ├── index.ts
            ├── ng-package.json
            └── public-api.ts

I have been following "Building an Angular Library with multiple entry points".

The libraries only have secondary entry points. Some entry points import others.

So, for a featureA1 in libraryA to use featureA2 in libraryA the imports are like so:

import { ... } from 'libraryA/featureA2'; And in libraryA's paths in tsconfig.json I have included

"paths": {
   "libraryA": ["./projects/libraryA"],
   "libraryA/*": ["./projects/libraryA/*"],
}

libraryB uses libraryA via npm link and the imports in components in libraryB are like so:

import { ... } from 'libraryA/featureA1';

When building libraryB the compiler rises the error:

error TS2307: Cannot find module 'libraryA/featureA1' or its corresponding type declarations.

pointing to the file in dist folder of libraryA ("../libraryA/dist/libraryA/featureA1/...") that contains import { ... } from 'libraryA/featureA1';

I have tried including another path mapping in libraryB's tsconfig.json to give the compiler the hint on where to find "libraryA"

"paths": {
      "libraryB": ["./projects/libraryB"],
      "libraryB/*": ["./projects/libraryB/*"],
      "libraryA": ["./node_modules/libraryA"],
      "libraryA/*": ["./node_modules/libraryA/*"],
}

And then libraryB builds just fine but then it becomes mandatory to include the type mappings for libraryA and libraryB (pointing to node_modules) in the app's tsconfig.json. The app then builds but Angular throws error NG0203 on ng serve.

How can I reference a secondary entry point in another secondary entry point in same library and then use the library in a project in another workspace via npm link?


Solution

  • Make sure you have "preserveSymlinks": true set in angular.json, for all the projects that use linking.

      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            ...
            "preserveSymlinks": true,
    

    This tutorial is good for working with linked packages.

    How to Develop Angular Libraries Locally?

    I think pointing to the dist folder is causing the NG0203 which basically means, the service you have, is not considered as an angular service but a javascript class.