Error: Type ****Component is part of the declarations of 2 modulesの解消 -共有モジュールの作成

# この記事の内容
[前回の記事](https://qiita.com/yunity29/items/9627694f23c141b39409)のようにコンポーネントを複数のモジュールの`declarations`に記述する方法でコンポーネントの親子関係を構築すると、記事タイトルのエラーが発生してしまいます。

```エラー内容.
HeaderComponent is part of the declarations of 2 modules: Tab1PageModule and Tab2PageModule! Please consider moving HeaderComponent to a higher module that imports Tab1PageModule and Tab2PageModule. You can also create a new NgModule that exports and includes HeaderComponent then import that NgModule in Tab1PageModule and Tab2PageModule.
```

今回はこのエラーを解消するためにコンポーネントの共通化の方法を書いていきます。
Ionicという部品のライブラリを使用しますが書いている内容はAngularです。


# 参考ページ
- [Angular公式 - Sharing Modules](https://angular.io/guide/sharing-ngmodules)
- [Qiita - AngularのNgModuleを使って、アプリの構成を管理する](https://qiita.com/Yamamoto0525/items/c647f03a5ab56883e09e)

#環境
- Angular8.0
- Ionic4.0
- IonicCLIを導入済み

# 具体的に
モジュールのTSファイルに記述する`declations`はモジュールに属するコンポーネントなどを記述しますが、コンポーネントが所属するモジュールは１つまでのため下のような構成はできません。
![スクリーンショット 2020-01-04 18.15.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537165/7b6e0c9f-595f-fb2b-16e8-e918ab1e8bdd.png)

---

エラーメッセージに記載されているように共有で使用したいコンポーネントを新しい共有用モジュール（SharedModule）に取り込み、使用したいモジュールにインポートすることで解消することができます。
具体的には共有モジュールを作成し、共通で使用したいコンポーネントを共有モジュールの`declations`に記述することで、どのモジュールからもコンポーネントのカスタムタグを使用することができます。

![スクリーンショット 2020-01-04 18.15.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537165/7e444e94-7628-1075-3bba-0aaf8f35c68d.png)




# 共有モジュールの生成

IonicCLIのジェネレート機能を使って共有モジュールを生成します。

```
ionic start myApp tabs

ionic generate
? What would you like to generate? module
? Name/path of module: shared
```

共有用のモジュールが作成できたので、このモジュールにコンポーネントを登録していきます。sharedフォルダに使用するコンポーネントを生成します。

```
ionic generate
? What would you like to generate? component
? Name/path of component: shared/component/sample-shared
```

sharedフォルダ配下に`shared-component`のファイル一式が作成されます。
せっかくなので、Ionicのカスタムタグを使用してみます。

```sample-shared.component.html
<ion-label>
  sample-shared works!
</ion-label>
```

生成した`shared-component`を共有モジュールに追加します。Ionicのカスタムタグをモジュール内で使用しているため、Ionic部品をインポートしておきます。
コンポーネントを外部で利用するためにexportに記述します。

```shared.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonicModule } from '@ionic/angular';
import { SampleSharedComponent } from './component/sample-shared/sample-shared.component';


@NgModule({
  declarations: [SampleSharedComponent], // 共有するコンポーネントを追加
  imports: [
    CommonModule, 
    IonicModule // モジュール内でIonic部品を使用するためにインポート
  ], 
  exports: [
    SampleSharedComponent //共有するコンポーネントを追加
  ]
})
export class SharedModule { }
```

# 共有モジュールの利用

共有モジュールを使用したいモジュールで`SharedModule`を`importants`に加えます。

```tab1.module.ts
@NgModule({
  imports: [
    IonicModule,
    CommonModule,
    FormsModule,
    RouterModule.forChild([{ path: '', component: Tab1Page }]),
    SharedModule
  ],
  declarations: [Tab1Page]
})
```

これで共有するコンポーネントのカスタムタグが利用できるようになります。

```tab1.page.html
<ion-header>
  <ion-toolbar>
    <ion-title>
      Tab One
    </ion-title>
  </ion-toolbar>
</ion-header>
<!-- カスタムタグの利用-->
<app-sample-shared></app-sample-shared>
```

最終的に[Augury](https://augury.rangle.io/)のNgModuleの状態はこんな感じ。
`declations`に`SampleSharedModule`を記述した`SharedModule`を各ページのモジュールにインポートしています。
<img width="936" alt="スクリーンショット 2020-01-04 22.05.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537165/5fb586ac-66f8-67c8-2e18-49451d19e674.png">

#共に働くWebエンジニアを募集しています!
不動産SHOPナカジツでは自社サービスを作っていく仲間を募集しています。
詳しくは[Wantedly](https://www.wantedly.com/projects/134741)からお問い合わせください。