インフラジスティックス・ジャパン株式会社Blog

インフラジスティックス・ジャパン株式会社のチームメンバーが技術トレンド、製品Tips、サポート情報からライセンス、日々の業務から感じることなど、さまざまなトピックについてお伝えするBlogです。

Angular アプリ開発 - Ignite UI for Angular を使ったコンポーネントを共通ライブラリ化し、複数アプリから使用する開発環境を構築する

Ignite UI for Angular を使ったコンポーネントを、複数の Angular アプリケーションから再利用したい場合はどうしたらよいでしょうか? そのような共通機能のソースコードを各アプリケーションにコピーすることは明らかに間違ったやり方です。そこで今回は、Ignite UI for Angular を共通機能に使用した複数の Angular アプリケーションを効率良く開発できる環境を構築する手順をご紹介いたします。

プロローグ

とあるシステムにて、

  • 一般ユーザーが使用する Angular アプリケーション "A" と、
  • 同じシステムの枠内だがベンダー側が内々に使用する管理業務用 Angular アプリケーション "B"

の、2つの Angular アプリケーションプロジェクトを開発する必要があったとします。また、このシステムでは、システムの稼働履歴を表形式で表示する必要があったため、Ignite UI for Angular のグリッドコンポーネントを使用することになりました。そしてまた、このシステム稼働履歴ページは、アプリケーション "A" と "B" の両方に搭載することとなりました。

このようなシナリオの場合、同じ "システム稼働履歴" 表示機能を、アプリ "A" と "B" のそれぞれのソースコードで別々に・二重に実装するのは効率が悪いことは明白です。"システム稼働履歴" ページに不具合が発見されたときや、開発の進捗が進むにつれて発生した仕様の変更・追加があったときに、アプリ "A" "B" の各々でソースコードを二重に修正する羽目になります。

このような場合は、"システム稼働履歴" のような共通機能を、別途独立した "ライブラリプロジェクト" で実装し、各アプリケーションプロジェクトからはこのライブラリプロジェクトを参照する構造にすることで解決できます。

そのための具体的な技法はいくつか考えられます。しかしとりわけ、アプリケーション "A", "B" のソースコードはもちろん、共通機能側のソースコードにも頻繁に実装・変更作業が発生するような、システム開発の初期~中期で効率良く開発を進めたい場合は、Angular のプロジェクト構成として公式に用意されている、「Angular ワークスペース」および「Angular ライブラリプロジェクト」を活用するのがよいでしょう。

そこで以下では、Angular のワークスペースおよびライブラリプロジェクトを利用して、Ignite UI for Angular を共通機能に使用した複数アプリケーションを効率良く開発できる環境を構築する手順をご紹介いたします。

システム要件

本ブログ投稿では下記バージョンの Angular アプリケーション開発環境に基づいて説明します。

  • Node.js ver.16.x
  • Angular ver.14.x
  • Ignite UI for Angular ver.14.x

事前に Node.js および Angular CLI を開発 PC 環境にインストールしておきます。
また、下記リンク先のドキュメントを参照し、Ignite UI for Angular npm パッケージのプライベート npm フィードを構成済みにしておきます (Ignite UI for Angular トライアル版で評価中の場合は必要ありません)。

jp.infragistics.com

それでは以下に、開発環境構築の手順を示していきます。

Angular ワークスペースとその配下のプロジェクトを作成

Angular ワークスペースの作成

まずは Angular ワークスペースを構築します。 作業用のフォルダをカレントフォルダとしたターミナル (コマンドプロンプト) で、--no-create-application スイッチ付きで、ng new {ワークスペース名} コマンドを実行します。すると、コマンドライン引数に指定したワークスペース名のサブフォルダが作成されて、その中に 📜package.json📜angular.json📜tsconfig.json などの構成ファイルが生成されます (📂node_modules フォルダもワークスペースフォルダ内に作成されます)。

~$ ng new my-workspace --no-create-application
~$
📂my-workspace
  📜angular.json
  📜package.json
  📜tsconfig.json
  ...
  📂node_modules
  ...

ワークスペース内に Angular プロジェクトを追加

ターミナル (コマンドプロンプト) 内で、Angular ワークスペースを作成したフォルダにカレントフォルダを移動しておき、ng generate コマンドを使用して、ワークスペース内に Angular プロジェクトを作成します。

  • ng generate application {プロジェクト名} で Angular アプリケーションプロジェクト、
  • ng generate library {プロジェクト名} で Angular ライブラリプロジェクト、

が、ワークスペース内に作成されます。

例えば、 Angular アプリケーション app-a と app-b、および、Angular ライブラリ lib-x の、合計 3 つのプロジェクトを作成する例は下記のとおりです。
(途中、Angular ルーティング機能の利用有無や、CSS スタイルシートの記述言語をコンソール上で訊かれますので、適宜、作成したいプロジェクトに合せて応答します。Ignite UI for Angular を利用することを想定した場合、CSS スタイルシートの記述言語は SCSS が推奨されます。)

~$ cd ./my-workspace
~/my-workspace$ ng generate application app-a
(結果省略)
~/my-workspace$ ng generate application app-b
(結果省略)
~/my-workspace$ ng generate library lib-x
(結果省略)

作成された各プロジェクトは、ワークスペースフォルダ内の 📂projects サブフォルダ以下に、各々のプロジェクト名のサブフォルダが作成されて、そこに生成されます。

📂my-workspace
  ...
  📂projects
    📂app-a
    📂app-b
    📂lib-x

ライブラリのビルド

さて、この状態から開発継続するにあたっては、Angular ライブラリプロジェクトは事前にビルドしておく必要があります。具体的には、カレントフォルダをワークスペースフォルダとしているターミナル (コマンドプロンプト) にて、ng build {プロジェクト名} を実行します (下記実行例)。

~/my-workspace$ ng build lib-x
(結果省略)

なお、開発の真っ最中で、このワークスペース内のアプリケーションプロジェクトもライブラリプロジェクトも、プログラムコードの編集・変更が頻繁に行なわれる場合は、--watch オプション付きで ng build を実行し、ライブラリ側のコード変更があったら自動で再ビルドされるように起動・監視しておくのがよいでしょう (下記実行例)。

~/my-workspace$ ng build lib-x --watch

アプリケーション側からライブラリを参照・使用する

以上の構成で、ワークスペース配下の Angular アプリケーションプロジェクトからは、同じワークスペース配下の Angular ライブラリプロジェクト内のモジュールを、普通に import で参照・使用することができるようになります。下記実装例のように、ワークスペース配下にあるライブラリに対しては相対パスは解決済みで import できます。さらには Visual Studio Code で開発している場合は、ちゃんとコード補完も効きます。

// app-a の app.module.ts
...
import { LibXModule } from 'lib-x'; // 👈 追加
...
@NgModule({
  ...,
  imports: [
    ...,
    LibXModule // 👈 追加
  ],
  ...

開発環境でのアプリケーションの実行

なお、同じワークスペース配下に複数の Angular アプリケーションプロジェクトが作成されている場合、ng serve でそれらアプリケーションを開発用に実行する際に、どのアプリケーションを実行するのか指定する必要が発生します。もし単純に、ワークスペースフォルダ内で ng serve とだけ実行すると、「どのアプリケーションを実行すればよいか曖昧でわからない」というエラーになってしまいます (下記実行例)。

~/my-workspace$ ng serve
Error: Cannot determine project for command.
This is a multi-project workspace and more than one project supports this command. Run "ng serve [project]" to execute the command for a specific project or change the current working directory to a project directory.

Available projects are:
- app-a
- app-b

この場合、上記実行例のエラーメッセージにて示されているとおり、コマンドライン引数にプロジェクト名を指定した ng server {プロジェクト名} の構文でコマンド実行することで、指定したプロジェクトの Angular アプリケーションが実行されます (下記実行例)。

~/my-workspace$ ng serve app-a
(結果省略)

app-aapp-b の両方の Angular アプリケーションを同時に実行したい場合は、ターミナル (コマンドプロンプト) を2つ開いて、各々のターミナル (コマンドプロンプト) で ng server {プロジェクト名} コマンドを実行すればよいでしょう。

以上のとおり、

  • ng build {プロジェクト名} --watch でライブラリプロジェクトを watch モードで自動再ビルドするようビルドプロセスを監視モードで常駐させつつ、
  • ng server {プロジェクト名} でアプリケーションプロジェクトを開発サーバー実行

しておくと、ライブラリとアプリケーションの、いずれの側のソースコードを編集して保存しても、随時、ブラウザ上でアプリケーションは再ロードされるようになり、開発作業が捗ります

アプリケーションを配置用にビルドする

ワークスペースフォルダ内の各 Angular アプリケーションプロジェクトは、普通に ng build コマンドを実行すれば配置用にビルドできます。ただし、プロジェクト名をコマンドライン引数に加えるのを忘れないようにしてください。それと、依存関係にあるプロジェクトを自動で再ビルドされることはありませんので、ライブラリプロジェクトを先に確実にビルドするようにしましょう (下記実行例)。

~/my-workspace$ ng build lib-x
(結果省略)
~/my-workspace$ ng build app-a
(結果省略)
~/my-workspace$ ng build app-b
(結果省略)

ビルドすると、ワークスペースフォルダ内の 📂dist フォルダ以下に、プロジェクト名のサブフォルダが作成されて、その中に Angular アプリケーションコンテンツが生成されます。

📂my-workspace
  ...
  📂dist
    📂app-a
    📂app-b
    📂lib-x

Ignite UI for Angular を組み込む

ng add igniteui-angular を実行

それではこの Anuglar ワークスペース内のプロジェクトに対し、Ignite UI for Angular を組み込んでいきましょう。

ワークスペースフォルダをカレントフォルダとしたターミナル (コマンドプロンプト) 内にて、ng add igniteui-angular コマンドを実行することで、

  • Ignite UI for Angular の npm パッケージ参照をワークスペースに追加、
  • ワークスペース内の各プロジェクトに対して CSS 参照の追加、
  • および 📜app.module.ts 内にモジュール読み込みのコードを追加、

といった処置を実施します (下記実行例)。

~/my-workspace$ ng add igniteui-angular
ℹ Using package manager: npm
✔ Found compatible package version: igniteui-angular@14.1.1.
✔ Package information loaded.

The package igniteui-angular@14.1.1 will be installed and executed.
Would you like to proceed? Yes # 👈 "Y" で応答
✔ Packages successfully installed.
? Add CSS library to reset HTML element styles across browsers? Yes # 👈 この例では "Y" で応答
(以下省略)

ng g @igniteui/angular-schematics:upgrade-packages を実行

続けてそのターミナル (コマンドプロンプト) 内で ng g @igniteui/angular-schematics:upgrade-packages コマンドを実行し、参照先パッケージを更新します。

~/my-workspace$ ng g @igniteui/angular-schematics:upgrade-packages
(結果省略)

(※ Ignite UI for Angular トライアル版で評価中の場合は、この ng g @igniteui/angular-schematics:upgrade-packages コマンドの実行は不要です。)

ng add igniteui-angular コマンド実行結果の調整

Angular ワークスペース構築の順序にも依るのですが、ひとつ注意点として、ng add igniteui-angular コマンドの実行によるワークスペース配下のファイルの変更に対し、二点ほど修正が必要な場合があります。

まず一つ目は、📜angular.json の修正です。
ng add igniteui-angular コマンドの実行による 📜angular.json の変更結果に対し、📜angular.json に含まれている Angular ライブラリプロジェクトのノード以下、projects > (library name) > architect > build > options 内に、styles のノードが追加されることがあります。もしそのような styles ノードがライブラリプロジェクトのノード内に追加されていた場合は、これを削除してください。

// 📜angular.json
{
  ...
  "projects": {
    ...
    // 👇 "ライブラリ" プロジェクトのノード内の...
    "lib-x": {
      "projectType": "library",
      ...
      "architect": {
        "build": {
          ...
          "options": {
            ...
            // 👇 この "styles" ノードが追加されていたら、これを削除 
            // (⚠️注: アプリケーションプロジェクトについては削除しない!)
            "styles": [
              "node_modules/igniteui-angular/..."
            ]

二つ目は各アプリケーションプロジェクトの 📄index.html です。
通常は ng add igniteui-angular コマンドの実行によって、📄index.html ファイル内の <body> 要素に対し、igx-typography および igx-scrollbar の 2 つの CSS クラス名が付与されます。しかし状況によってはこれら CSS クラス名が <body> 要素に付与されない場合があります。その場合はテキストエディタで 📄index.html を編集し、これら 2 つの CSS クラス名を <body> 要素に設定してください。

<!-- 各アプリケーションプロジェクトの index.html -->
<html>
...
<!--        👇igx-typography および igx-scrollbar の2つの CSS クラス名を付与 -->
<body class="igx-typography igx-scrollbar">
...

以上を済ませますと、アプリケーションプロジェクト、ライブラリプロジェクトのそれぞれで、**.module.ts 内で必要な Igunite UI コンポーネントのモジュールを import し、コンポーネント内で利用できるようになります。

補足 - Ignite UI for Angular 組み込み後のビルド

ところで、Ignite UI for Angular をワークスペースおよびその配下のプロジェクトに組み込み後、アプリケーションのビルド時に下記実行例のようなエラーが出る場合があります。

> ng build app-a
✔ Browser application bundle generation complete.
(途中省略)
Error: bundle initial exceeded maximum budget. Budget 1.00 MB was not met by 1.19 MB with a total of 2.19 MB.

上記実行例のエラー、"bundle initial exceeded maximum budget" は、ビルドした結果の Angular アプリケーションコンテンツのサイズが、"所定の上限" を超えてしまったことで発生したエラーです。

ビルド後のサイズ (上記実行例では 2.19 MB となっています) が許容できる場合は、ワークスペースフォルダ内にある 📜angular.json 内の上限指定を変更・緩和することで、このエラーを回避できます (下記編集例)。

// 📜angular.json
{
  ...
  "projects": {
    ...
    // 👇 ビルド対象アプリケーションのノード内の...
    "app-a": {
      "projectType": "application",
      ...
      "architect": {
        "build": {
          ...
          "configurations": {
            "production": {
              "budgets": [
                {
                  "type": "initial",
                  // 👇 "budgets" ノード内の指定にて、上限を緩和
                  // (下記では 3MB まで許容)
                  "maximumError": "3mb"
                },
                ...

Ignite UI for Angular ad 202211

まとめ

以上の構成にて、Ignite UI for Angular を使用している "共通コンポーネント" を Angular ワークスペース配下のライブラリプロジェクトとして構築し、同じワークスペース配下の複数アプリケーションプロジェクトから参照して使うことができるようになりました。

このように Angular ワークスペースを活用することで、同じ機能・コンポーネントを二重に実装・保守することなく、その共通機能を使った複数アプリケーション開発を進めることができるようになります。また、ライブラリ側、アプリケーション側、いずれのソースコードを編集しても再ロードされる、効率の良い開発体験も得られます。

また、本記事では紹介しませんでしたが、このようにして作成した Ignite UI for Angular を使用した Angular ライブラリプロジェクトは、npm パッケージとして配付することもできます。組織内でアプリケーションに依らず再利用したい共通機能がある場合は、Angular ワークスペースを用いずとも、npm パッケージとして配付・再利用する方法もあります。

本記事に沿って実装したサンプルコードを、下記 GitHub リポジトリで公開しています。本記事で説明した手順が、下記 GitHub リポジトリ内のコミット履歴として確認いただけます。

https://github.com/igjp-sample/use-Igx-on-shared-angular-libgithub.com

以上、是非本記事を、Ignite UI for Angular を活用した共通機能の再利用化にお役立てください。