I've created 3 angular libraries/packages:
@example/ng-youtube-player
containing a YoutubePlayerComponent
and YoutubeApiService
@example/ng-dailymotion-player
containing a DailymotionPlayerComponent
and DailymotionApiService
@example/ng-vimeo-player
containing a VimeoPlayerComponent
and VimeoApiService
Now I wanted to create a library containing a VideoPlayerComponent
, using only the packages providing the YoutubeApiService
, DailymotionApiService
and VimeoApiService
. In order to not include the other components unnecessarily, I want to split the 3 libraries each, so that I can install only the Service classes.
You could argue that angular uses tree-shaking, so the components will not be bundled with the application anyway, but anyhow I'd rather have those dependencies seperated for brevity.
I've tried setting up a monorepo containing 2 libraries and a test application, but from the moment I reference a service from another library, the build fails. I've created a very basic example workspace to reproduce the issue:
git clone https://github.com/PieterjanDeClippel/angular-monorepo-test
cd angular-monorepo-test
npm install
ng build @mintplayer/ng-youtube-api
ng build @mintplayer/ng-youtube-player
ng build ng-youtube-player-demo
# All projects compile successfully
# Now go to the NgYoutubePlayerComponent and uncomment the injection parameter in the constructor (line 16)
ng build @mintplayer/ng-youtube-player
The build fails with tons of the following errors:
ā Compiling with Angular sources in Ivy partial compilation mode.
projects/mintplayer/ng-youtube-api/src/lib/ng-youtube-api.service.ts:1:1 - error TS6059: File 'C:/Users/user/source/repos/Tmp/mintplayer-ng-youtube-player/projects/mintplayer/ng-youtube-api/src/lib/ng-youtube-api.service.ngtypecheck.ts' is not under 'rootDir' 'C:\Users\user\source\repos\Tmp\mintplayer-ng-youtube-player\projects\mintplayer\ng-youtube-player\src'. 'rootDir' is expected to contain all source files.
1 import { Injectable } from '@angular/core';
projects/mintplayer/ng-youtube-api/src/public-api.ts:1:1 - error TS6059: File 'C:/Users/user/source/repos/Tmp/mintplayer-ng-youtube-player/projects/mintplayer/ng-youtube-api/src/public-api.ngtypecheck.ts' is not under 'rootDir' 'C:\Users\user\source\repos\Tmp\mintplayer-ng-youtube-player\projects\mintplayer\ng-youtube-player\src'. 'rootDir' is expected to contain all source files.
There are 2 main problems here:
I've already read the following similar question, but it didn't help me out:
My test code is hosted here. All instructions to reproduce the issue are noted in the code block above. The main changes I made are in the root tsconfig.json
:
{
...
"compilerOptions": {
...,
"paths": {
"@mintplayer/ng-youtube-api": [
"projects/mintplayer/ng-youtube-api/src/public-api.ts"
],
"@mintplayer/ng-youtube-player": [
"projects/mintplayer/ng-youtube-player/src/public-api.ts"
]
}
}
}
I've already setup a workspace containing a library and application, where the application consumes classes from the library without any problems (see the 3 repositories on top of the question), but from the moment a library consumes classes from another library, the build is broken.
How can I fix this, and have a single workspace with 2 libraries and a test application?
NX it is apparently: https://nx.dev. If you ever need to create an angular library, it's best to generate an NX project rightaway.
npm install -g @angular/cli@latest
npm install -g nx
npx create-nx-workspace
cd mycompany-ng-youtube-player
Generate a library for the youtube player:
nx g @nrwl/angular:lib mycompany-ng-youtube-player --buildable --publishable --import-path @mycompany/ng-youtube-player
Specify your package name and version in the package.json
:
{
"name": "@mycompany/ng-youtube-player",
"version": "1.0.0",
...
}
Generate a library for the IFrame API:
nx g @nrwl/angular:lib mycompany-ng-youtube-api --buildable --publishable --import-path @mycompany/ng-youtube-api
Specify your package name and version in the package.json
:
{
"name": "@mycompany/ng-youtube-api",
"version": "1.0.0",
...
}
Generate a component in the @mycompany/ng-youtube-player
package:
cd .\libs\mycompany-ng-youtube-player\src\lib
nx g component ng-youtube-player --project=mycompany-ng-youtube-player --module=mycompany-ng-youtube-player --export
Generate a service in the @mycompany/ng-youtube-api
package:
cd ..\..\..\mycompany-ng-youtube-api\src\lib
nx g service ng-youtube-api --project=mycompany-ng-youtube-api
Now you can add the package dependency to the package.json
of the player:
{
...,
"peerDependencies": {
"@mycompany/ng-youtube-api": "~3.0.0",
...
}
}
Now it's just a matter of modifying the code.
To build and run the application:
npm run nx run-many -- --target=build --projects=ng-youtube-player-demo --with-deps
npm run nx serve -- --open
If you're considering using NX, then you apparently need to bear the following in mind:
@angular/core@v14
compatible version of your libraryjest-preset-angular
to release a v14 compatible version