Angular Library を使って共通コンポーネントを作る


# :one: Angular Library とは
- Angular CLI v6 から提供された機能で通常の application 作成と異なり library を作ることができる
    - ref. [Library support in Angular CLI 6](https://github.com/angular/angular-cli/wiki/stories-create-library)

# :two: 利点
- Angular は Angular CLI の [Multiple Projects](https://github.com/angular/angular-cli/wiki/stories-multiple-projects) を利用するとひとつの repository 内で複数の application を管理できるが library を作ることによりこれらの複数 application で共通に使えるコンポーネント群を作ることができる
- また library をパッケージングすることで npm として公開しなくても別の Angular repository で同じように共通コンポーネントととしても使用可能

# :three: 作ってみる
## application を作成
- sample-project という名前で Angular repository を作成する(これは library とは別)

```shell
$ ng new sample-project
$ cd sample-project
# 起動まで確認する
$ yarn start --open
```

## library を作成
- my-lib という名前で library project を作成する
```shell
$ yarn ng generate library my-lib
```
- sample-project の中に projects/my-lib/ というディレクトリが作られたのが確認できる

## library をビルド
- library をビルドする
    - `--watch`オプションを付けると変更を監視するようになる(Angular CLI v6.2 以上)
    - 1 回だけビルドしたい場合は不要

```shell
$ yarn ng build my-lib --watch
```

## library project でコンポーネントを作成
- ButtonComponent を作成する
    - repository 内に project が複数あるので `--project` で対象を指定する必要がある

```shell
$ yarn ng g c components/button --project my-lib
```

- ButtonComponent の公開
    - 下記のように export する

```diff
diff --git a/projects/my-lib/src/lib/my-lib.module.ts b/projects/my-lib/src/lib/my-lib.module.ts
index 1737e01..384bef0 100644
--- a/projects/my-lib/src/lib/my-lib.module.ts
+++ b/projects/my-lib/src/lib/my-lib.module.ts
@@ -6,6 +6,6 @@ import { ButtonComponent } from './components/button/button.component';
   declarations: [MyLibComponent, ButtonComponent],
   imports: [
   ],
-  exports: [MyLibComponent]
+  exports: [MyLibComponent, ButtonComponent]
 })
 export class MyLibModule { }
```

# :four: 使ってみる
## library を同一 repository の application で使う
- my-lib で作った ButtonComponent を sample-project で使う
    - 同じ repository 内にある application では library のビルドだけですぐに使うことができる

```diff
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 2c3ba29..f95347c 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,6 +1,8 @@
 import { BrowserModule } from '@angular/platform-browser';
 import { NgModule } from '@angular/core';

+import { MyLibModule } from 'my-lib';
+
 import { AppRoutingModule } from './app-routing.module';
 import { AppComponent } from './app.component';

@@ -10,7 +12,8 @@ import { AppComponent } from './app.component';
   ],
   imports: [
     BrowserModule,
     AppRoutingModule,
+    MyLibModule,
   ],
   providers: [],
   bootstrap: [AppComponent]
```

- コンポーネントを表示する
    - あとはいつもどおりタグを記述するだけでコンポーネントの表示ができる

```diff
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 0f3d9d8..0e56a2e 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -17,5 +17,6 @@
     <h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
   </li>
 </ul>
+<lib-button></lib-button>

 <router-outlet></router-outlet>
```

## 別の repository で使う
- library のパッケージングが必要なので my-lib のビルド成果物があるディレクトリで下記コマンドを実行

```shell
$ cd dist/my-lib
$ yarn pack
# my-lib-v0.0.1.tgz ができる
```
- my-lib-v0.0.1.tgz ができる
- もし名前を変えたければ `$ yarn pack --filename my-lib.tgz` のようにする
- パッケージングした library を任意の application でインストールする

```shell
$ yarn add ../angular-sample/sample-project/dist/my-lib/my-lib.tgz
```
- 使い方は同一 repository 内のときと同様

# :five: まとめ
最新のAngular CLI を使うと library の作成が簡単にできることがわかった。今回はコンポーネントしか試していないが service や pipe などを共通 library として用意してもよさそう。

# 参考
- [Library support in Angular CLI 6](https://github.com/angular/angular-cli/wiki/stories-create-library)
- [The Angular Library Series - Building and Packaging](https://blog.angularindepth.com/creating-a-library-in-angular-6-part-2-6e2bc1e14121)