noxi雑記

.NET、Angularまわりの小ネタブログ

Angularライブラリーに別のEntryPointを追加する

Angular CLI で作成したライブラリープロジェクトに別の EntryPoint を追加する方法です。
前回は Component Harness を使用したテストを書いてみましたが、 Component Harness はライブラリーとして配布することでより効果を得ることができます。しかし同じ EntryPoint からテスト用のクラスをインポート出来てしまうのは違和感があるため、 @hoge/lib に対して @hoge/lib/testing を追加してみます。



環境

Angular CLI: 9.0.2
Node: 12.16.0
OS: win32 x64

Angular: 9.0.1
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.900.2
@angular-devkit/build-angular      0.900.2
@angular-devkit/build-ng-packagr   0.900.2
@angular-devkit/build-optimizer    0.900.2
@angular-devkit/build-webpack      0.900.2
@angular-devkit/core               9.0.2
@angular-devkit/schematics         9.0.2
@angular/cdk                       9.0.0
@angular/cli                       9.0.2
@angular/material                  9.0.0
@ngtools/webpack                   9.0.2
@schematics/angular                9.0.2
@schematics/update                 0.900.2
ng-packagr                         9.0.0
rxjs                               6.5.4
typescript                         3.7.5
webpack                            4.41.2

ライブラリープロジェクトに別のEntryPointを追加する

Angular CLI で作成したライブラリーに別の EntryPoint を追加する方法は ng-packagr が正式にサポートしています。

github.com

新しい EntryPoint となるディレクトリーを作成し、その中に package.json または ng-package.json と export する機能を含めた public_api.ts を追加します。

my_package
├── src
|   ├── public_api.ts
|   └── *.ts
├── ng-package.json
├── package.json
└── testing
    ├── src
    |   ├── public_api.ts
    |   └── *.ts
    └── package.json

my_package/testing/package.json の中身は空の ngPackage を含めるだけで良いようです。筆者は ng-package.json を配置しています。こちらはライブラリープロジェクトのルートディレクトリーにも存在する設定ファイルと同じです。

{
  "ngPackage": {}
}

ただしこの方法で新しい EntryPoint を追加し、 my_package/src の下にあるファイルを public_api.ts に追加すると '...' is not under 'rootDir' と怒られてビルドに失敗します。

違うディレクトリーに含まれるクラスを新しいEntryPointに含める

ソースコードを眺めてみたところ、どうやら rootDir は entryFile (public_api.ts) のディレクトリーを指している様です。

// https://github.com/ng-packagr/ng-packagr/blob/v9.0.0/src/lib/ts/tsconfig.ts#L80
const basePath = path.dirname(entryPoint.entryFilePath);

...

const overrideOptions: ng.CompilerOptions = {
  flatModuleId: entryPoint.moduleId,
  flatModuleOutFile: `${entryPoint.flatModuleFile}.js`,
  basePath,
  rootDir: basePath,
  lib: entryPoint.languageLevel ? entryPoint.languageLevel.map(lib => `lib.${lib}.d.ts`) : tsConfig.options.lib,
  declarationDir: basePath,
  sourceRoot: `ng://${entryPoint.moduleId}`,
  jsx,
};

ならばいたしかたがないと、全て my_package/src/* にファイルを含めてしまえば解決します。いたしかたがない。
my_package/src/testing_api.ts を作成し、ここに @mypackage/testing からエクスポートされるものを追加します。

my_package
├── src
|   ├── public_api.ts
|   ├── testing_api.ts
|   └── *.ts
├── ng-package.json
├── package.json
└── testing
    └── ng-package.json

my_package/testing/ng-package.jsonmy_package/src/testing_api.ts を EntryFile に指定するだけで OK です。

{
  "lib": {
    "entryFile": "../src/testing_api.ts"
  }
}