angulartypescriptwebpackangular-libraryng-packagr

Entry point @example/ng-bootstrap/core which is required by @example/ng-bootstrap/src/lib/badge doesn't exists. - NX


I've built an angular component library in an NX workspace. For several weeks I've been struggling to get my angular library to work properly. The library contains some 50 components with their respective module. I've asked a similar question some time ago, but still wasn't able to solve the problem. However I do have more intel.

For a starter

All pages in my application are lazy-loaded. Each page demonstrates a component from the library. But just because I'm using the BsNavbarModule in my AppComponent and load the BsNavbarModule in the AppModule, javascript chunks from all other components inside the library are ending up in my main bundle.

angular main bundle

All chunks in red should not be in the main bundle and are only used on lazy-loaded pages. The total size of the main bundle is 850 kB.

Troubleshooting

SCSS

In my previous question someone suggested that this is because I'm using SCSS in my components like this:

badge.component.scss

:host ::ng-deep {
    // Configuration
    @import "~bootstrap/scss/functions";
    @import "~bootstrap/scss/variables";
    @import "~bootstrap/scss/mixins";

    // Layout & components
    @import "~bootstrap/scss/badge";
}

However commenting out :host ::ng-deep everywhere does not get me rid of the javascript chunks in the main bundle, so that's not the solution I'm looking for.

Adding components

The total size of my main bundle used to be 650 kB. But adding components to the library increased the main bundle with a staggering 200 kB up to 860 kB.

One application, no library

Moving all components to the application and removing the library, gives me something totally different. Doing so reduces the main bundle down to 400 kB.

Use angular workspace instead

It seems that angular workspaces now allow you to reference a library from another library, so I tested that as well. The results are the same, javascript chunks from all over end up in the main bundle just because I use one component from the library in the AppComponent.

Just remove all component SCSS

I've commented out all SCSS in the library components. This does not affect the result in any way. The main bundle is still larger than 800 kB.

The real solution

Up to this point it's become obvious that this has nothing to do with the SCSS, but rather with the fact that the components are inside a library. Using one component from the library bundles the entire library in the main bundle. The same phenomenon is explained, demonstrated and potentially solved here.

So I've added a ng-package.json to the folder of each component:

src/lib/badge/ng-package.json

{
    "$schema": "../../../../../node_modules/ng-packagr/ng-package.schema.json",
    "dest": "../../../../../dist/libs/example-ng-bootstrap",
    "lib": {
      "entryFile": "index.ts"
    }
}

src/lib/badge/index.ts

export * from './badge.component';
export * from './badge.module';

and refactored the code to use this entrypoint instead of ../../..

import { BsBadgeModule } from '@example/ng-bootstrap/badge';

However, the workspace won't compile now. I've reduced the code to the bare minimum (seperate branch) with the information gathered from the previous link, and still the project won't build, but gives this error instead:

npm run build -- --skip-nx-cache --configuration production --source-map

> mintplayer-ng-bootstrap@0.0.0 build
> nx build "--skip-nx-cache" "--configuration" "production" "--source-map"


   ×    1/4 dependent project tasks failed (see below)
   √    3/4 dependent project tasks succeeded [0 read from cache]

 —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————


> nx run mintplayer-ng-bootstrap:build:production

Building Angular Package

 >  NX   Entry point @mintplayer/ng-bootstrap/core which is required by @mintplayer/ng-bootstrap/src/lib/badge doesn't exists.

   Pass --verbose to see the stacktrace.


 ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— 

 >  NX   Ran target build for project ng-bootstrap-demo and 4 task(s) it depends on (7s)

         With additional flags:
           --source-map=true

    ×    1/4 failed

 >  NX   Entry point @mintplayer/ng-bootstrap/core which is required by @mintplayer/ng-bootstrap/src/lib/badge doesn't exists.

   Pass --verbose to see the stacktrace.


 ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— 

 >  NX   Ran target build for project ng-bootstrap-demo and 4 task(s) it depends on (6s)

         With additional flags:
           --source-map=true

    ×    1/4 failed
    √    3/4 succeeded [0 read from cache]

   View structured, searchable error logs at https://nx.app/runs/IAaoSSkobF

What am I still doing wrong? Is ng-packagr not able to determine the build order of the entrypoints?


Solution

  • Problem solved

    Documentation

    The folder for sub-entrypoints MUST be next to the src folder.