Angular CLIビルド時にできる利用OSSリスト(3rdpartylicenses.txt)をWebアプリ上に表示する

# はじめに
近年、OSSを利用せずにWebアプリ(SPA)を開発することはないですよね？
ライセンス条項にもよりますが、OSSを利用するとき、ライセンス条項に従うために利用OSSリストとライセンスを表示する必要があります。
Webアプリの場合はライセンス表示用ページを用意しますが、新しくOSS追加・削除したり、利用OSSのバージョン変更の度に、ライセンス表示用ページをメンテナンスするのが煩わしかったり、忘れてしまいませんか？

# 目的
@angular/cliでのSPA開発において、ライセンス一覧ページをメンテナンスフリーとすることを目的としています。
実現することで開発者は、開発時の負担を軽減し、本当に開発するべき内容に集中できるようになります。

# 前提
以下を前提とします。

- @angular/cliによる開発
- `ng build` 実行時に`dist/project`ディレクトリに`3rdpartylicenses.txt`ファイルが生成されている(`--prod`オプションを付与すると生成されます)

# 内容
@angular/cliで作成したプロジェクトをビルドすると、`package.json`ファイルのdependenciesに記載されている依存OSSの名称、バージョン、ライセンスを纏めたファイル`3rdpartylicenses.txt`が`dist/project`ディレクトリに生成されます。
このファイルを読み込んで表示するComponentを作成します。
表示のスタイルは各自でアレンジしてみてください。

# 基本手順
基本的な手順は以下となります。必要に応じて省略してください。

## @angular/cli インストール
適当な作業ディレクトリを作成し、作業ディレクトリ上で以下を実行してください。
1. `npm install -g @angular/cli@latest`

## プロジェクト作成
新しいプロジェクトを作成します。
1. `ng new license-list-sample`

## Component作成
以下を実行すると、`app/license/license.component.*`ファイルが生成されます。クラスはLicenseComponentとなります。

```text:commandline
cd license-list-sample
ng g component license
```

## ソース修正
各ソースを修正してください。

```ts:app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http'; // 追加

import { AppComponent } from './app.component';
import { LicenseComponent } from './license/license.component';

@NgModule({
  declarations: [
    AppComponent,
    LicenseComponent // 追加
  ],
  imports: [
    BrowserModule,
    HttpClientModule // 追加
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
```

```html:app/app.component.html
<h2>Open Source Licenses</h2>
<div>
  <!-- LicenseComponentを挿入 -->
  <app-license></app-license>
</div>
```

```ts:app/license/license.component.ts
import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { HttpClient } from '@angular/common/http';

import { Observable } from 'rxjs';
import { share } from 'rxjs/operators';

/**
 * 3rdpartylicenses.txtライセンスを
 * 読み込んで表示するコンポーネント
 */
@Component({
  selector: 'app-license',
  templateUrl: './license.component.html',
  styleUrls: ['./license.component.css']
})
export class LicenseComponent implements OnInit {

  /**
   * ライセンスを読み込むストリーム
   */
  public license$: Observable<string>;

  /**
   * コンストラクタ
   * @param http HttpClient
   */
  constructor(
    private http: HttpClient,
    private location: Location) {
  }

  /**
   * 初期化イベントハンドラ
   */
  ngOnInit() {
    // 3rdpartylicenses.txtを読み込むストリームを生成
    // --baseHref を設定していても対応できるようにしてみた。
    const path = this.location.prepareExternalUrl('3rdpartylicenses.txt');
    const url = `${window.location.protocol}//${window.location.host}${path}`;
    this.license$ = this.http.get(url, { responseType: 'text' }
    ).pipe(share());
  }
}
```

```html:app/license/license.component.html
<pre [innerText]="(license$ | async)"></pre>
```

## ビルド&実行
`ng serve --prod`実行後、ブラウザで`http://localhost:4200`を開いてください。
こんなふうに出力されれば、成功です。各自CSS/htmlを修正して、デザインを整えてください。

![angular-license-list.png](https://qiita-image-store.s3.amazonaws.com/0/179413/fd08fd3d-a227-2427-e412-bb998171184a.png)

※補足
`ng build --extractLicenses=true`とするとprodでなくともライセンス一覧を出力してくれます。
angular.json内にて、"extractLicenses": true を指定するのも同様です。

# 動機
@angular/cliでビルドしたときに`3rdpartylicenses.txt`が生成されているのに気付いて、活用できないかと考えてました。
そんな中、英語サイトで紹介されていたので、日本語で紹介しておこうということで執筆しました。
少しでも貢献できたら嬉しいです。

# 追記

テキストではなく、JSONで扱いたいと思っていたので、取り組みを[「依存OSSのライセンス一覧(JSON)生成ツールを作ってみた」](https://qiita.com/kyosho/items/4a83b4da1c457536548e)にまとめてみました。
良かったら見てやってください。

# 参考

* [StackOverflow - Angular 4 - How to display 3rdpartylicenses in HTML](https://stackoverflow.com/questions/47058802/angular-4-how-to-display-3rdpartylicenses-in-html "Angular 4 - How to display 3rdpartylicenses in HTML")
* [Github - @angular/cli](https://github.com/angular/angular-cli)
* [AngularでHttpClientのgetのためにbase-hrefを取得する](https://kamino.hatenablog.com/entry/angular-httpclient-base-href)

# 更新履歴

* 2019-06-03: Angular CLI 8.xとrxjs6向けに修正
* 2019-08-25: --baseHrefに対応
* 2019-10-07: --extractLicensesオプションの補足追加
* 2019-10-07: angular.json内のextractLicensesについて補足追加