【ITニュース解説】🌍Step-by-Step Guide to Setting Up an Angular Application with CMS-Driven Architecture(Optimizely)
2025年09月23日に「Dev.to」が公開したITニュース「🌍Step-by-Step Guide to Setting Up an Angular Application with CMS-Driven Architecture(Optimizely)」について初心者にもわかりやすく解説しています。
ITニュース概要
Optimizely CMSとAngularを連携させ、コンテンツを動的に表示する方法を解説。専用ライブラリとコンポーネントのレジストリ活用で、CMSデータ(ページやブロック)に応じてAngularコンポーネントを自動で動的レンダリングする仕組みを学ぶ。これにより、開発者はUI設計に集中し、CMS駆動サイトを効率的に構築できる。
ITニュース解説
システムエンジニアを目指す初心者にとって、ウェブサイトがどのように作られ、動いているのかを理解することはとても重要だ。この記事では、人気のあるウェブフレームワーク「Angular」を使って、ウェブサイトのコンテンツ管理システム(CMS)である「Optimizely」と連携する動的なアプリケーションを構築する手順について詳しく解説する。
まず、ウェブサイトにおけるCMSの役割から説明しよう。通常、ウェブサイトの見た目や動きを制御する部分は「フロントエンド」、データの保存や処理を行う部分は「バックエンド」と呼ばれる。そして、ウェブサイトに表示されるテキストや画像といったコンテンツを、プログラミングの知識がない人でも簡単に管理・更新できるようにするのがCMSだ。OptimizelyもそのようなCMSの一つで、これとAngularアプリケーションを組み合わせることで、コンテンツの変更がウェブサイトに即座に反映される、非常に柔軟なシステムが実現できる。この仕組みでは、ウェブページのレイアウトや表示される部品(コンポーネント)が、CMS側で設定された内容に基づいて動的に生成される点が大きな特徴だ。
この動的な連携を実現するために、特別な「カスタムライブラリ」が使われる。このライブラリが、Optimizely CMSから送られてくるコンテンツデータと、Angularアプリケーションがそのデータをどのように画面に表示するかという部分との橋渡し役を担うのだ。これにより、フロントエンドの開発者は、CMSのコンテンツ変更に逐一コードを修正することなく、コンテンツの表示ロジックに集中できるようになる。
アプリケーションのコードは、いくつかの役割ごとにフォルダに整理されている。
一つ目は「DropComponents」フォルダだ。ここには、CMSの管理画面からウェブページ上に「ドラッグ&ドロップ」するように配置される、小さな部品(コンポーネント)たちが格納されている。例えば、ウェブページの特定のセクションに表示される「ヒーローブロック」や「Eサービスブロック」といった要素がこれにあたる。これらのコンポーネントは、ウェブサイトにアクセスしたときに、CMSからの指示に基づいて動的に読み込まれて表示される。
二つ目は「GlobalComponents」フォルダで、ウェブサイト全体で共通して使われるUI部品が置かれている。例えば、どのページを見ても上部に表示される「ヘッダー」や、存在しないURLにアクセスしたときに表示される「404 Not Found」ページなどがここに含まれる。これらはサイトの基本的な骨格を構成する重要な要素だ。
三つ目は「Pages」フォルダだ。ここには、ウェブサイトの個々のページに対応するコンポーネントが格納されている。例えば、共通のページレイアウトを提供する「PageLayoutComponent」や、ニュース記事の詳細を表示する「NewsDetailsComponent」といったものがこれにあたる。これらのコンポーネントが、特定のURL(ルート)に対応して画面全体を構築する役割を果たす。
これらのフォルダ構造は、アプリケーションを整然と保ち、開発者がコードを見つけやすく、管理しやすくするために非常に重要だ。
次に、Angularアプリケーションの具体的なセットアップ手順を見てみよう。まず、基本的なAngularアプリケーションを新規作成する。次に、先ほど説明した「DropComponents」「GlobalComponents」「Pages」という三つのフォルダをアプリケーション内に作成する。その後、「GlobalComponents」内に「LayoutComponent」を、「Pages」内に「PageLayoutComponent」をそれぞれ生成する。
このアーキテクチャの肝となるのが「ルーティング」の設定だ。Angularアプリケーションでは、URLと表示するコンポーネントのマッピングを「ルーティング」と呼ぶ。ここで重要なのは、ウェブサイトのどのURLにアクセスしても、最終的には「PageLayoutComponent」という共通の入り口を通るように設定することだ。これは「ネストされたキャッチオールルート」と「グローバルなキャッチオールルート」という二つの設定によって実現される。これにより、CMSで新しくページが作成されたり、URLが変更されたりしても、Angularアプリケーション側でルーティングのコードを頻繁に修正する必要がなくなり、CMSの柔軟性が最大限に活かされるのだ。
ウェブページに表示されるコンテンツは、バックエンドのCMSから提供されるデータによって決まる。このデータには大きく分けて二つのパターンがある。
一つ目は、「pageComponents」という配列を含むデータだ。これは、CMSの管理画面で、複数の小さな部品(ブロック)を組み合わせて作られたページの場合に送られてくる。例えば、ヘッダーの下にヒーローセクションがあり、その下にサービス紹介セクションがあるようなページだ。このデータが届くと、アプリケーションはライブラリが提供する「libDynamicComponent」という特別なディレクティブを使って、これらの部品を一つずつ動的にレンダリングしていく。
二つ目は、「pageComponents」配列を含まないデータだ。これは、CMS上で特定のコンテンツブロックを持たず、ページそのもののプロパティ(タイトル、サブタイトル、画像URLなど)だけで構成されるシンプルなページの場合に送られてくる。例えば、会社概要のような詳細ページがこれにあたる。このタイプのページは、「ViewContainerRef」というAngularの機能を使って、ページ全体のコンポーネントを動的に表示する。
これらのデータ形式に対応するため、カスタムライブラリをAngularアプリケーションにインストールする。このライブラリは、ビルドされたファイルをプロジェクトのルートディレクトリにコピーし、その後「npm install」コマンドでインストールすることで利用可能になる。
次に、各コンポーネントのコードと役割について詳しく見ていこう。
「LayoutComponent」は、ウェブサイトの共通レイアウトを提供する。これは、常に表示されるヘッダー部品(app-header)と、URLに応じて変化するコンテンツを表示するための「router-outlet」を配置する。これにより、どのページに移動してもヘッダーが変わらない一貫したユーザー体験が提供される。
「DropComponents」フォルダ内のコンポーネント、例えば「HeroComponent」や「EServicesComponent」は、CMSから送られてくるデータを「@Input() data: any;」という形で受け取る。このdata変数には、CMS側で設定されたそれぞれのブロックのタイトル、説明、画像URLなどの情報が全て含まれている。フロントエンドの開発者は、このdata変数を使って、HTMLテンプレート内でデザインを組み立て、コンテンツを表示する。
「Pages」フォルダ内のコンポーネント、例えば「LeadershipDetailsComponent」も同様に、「@Input() data: any;」を通じて、そのページ固有のプロパティデータを受け取る。これも、受け取ったデータに基づいてページ全体をデザインする。
このシステムの中心的な役割を果たすのが「PageLayoutComponent」だ。まず、このコンポーネントでは、「COMP_REGISTRY」と「PAGE_REGISTRY」という二つの「レジストリ」を定義する。これらのレジストリは、CMSから送られてくるデータの「Type」(ページのタイプ名やブロックのタイプ名)と、対応するAngularのコンポーネントを紐付ける「マップ」のようなものだ。例えば、「HeroBlock」というタイプ名が来たら「HeroComponent」を表示する、といったマッピングがここで行われる。これらのレジストリは、ライブラリのsetPageRegistry()とsetComponentRegistry()という関数を使ってライブラリに登録される。
そして、「PageLayoutComponent」の内部では、OptimizelyCmsIntegrationServiceというライブラリのサービスが使われる。このサービスには、ウェブサイトのURLに基づいてバックエンドのCMSからコンテンツデータを取得するgetPageContent()というメソッドがある。データが取得されると、そのデータの内容に応じて、renderPages()関数とrenderComponents()関数が呼び出される。
renderPages()は、取得したデータがページプロパティのみで構成される場合、PAGE_REGISTRYを参照して適切なページコンポーネント(例: LeadershipDetailsComponent)を動的に生成し、#dynamicContainerという専用の表示領域に表示する。一方、renderComponents()は、データにpageComponents配列が含まれる場合、COMP_REGISTRYを参照して、CMSで配置された各ブロック(例: HeroComponent, EServicesComponent)を動的に生成し、libDynamicComponentというライブラリのディレクティブが指定された領域に表示する。これにより、CMSでブロックの順序が変更されても、フロントエンドのコードを修正することなく、その変更がウェブサイトに反映される。
要するに、ウェブサイトにアクセスすると、まずルーティングによってPageLayoutComponentに到達する。PageLayoutComponentはCMSにコンテンツデータを要求し、そのデータを受け取ると、あらかじめ登録しておいたレジストリ情報に基づいて、必要なページや部品のコンポーネントを動的に判断し、適切な場所に生成して表示する。これにより、CMS側でコンテンツやレイアウトを自由に組み立て、変更しても、Angularアプリケーションはそれを自動的に解釈して表示してくれるというわけだ。
このアーキテクチャの大きな利点は、CMSのコンテンツ管理ロジックと、フロントエンドの表示ロジックを完全に分離できる点だ。CMSから送られてくる「Type」というキーワードと、Angularコンポーネントがレジストリによって紐付けられているため、フロントエンド開発者は新しいページタイプやコンポーネントが必要になった場合、対応するコンポーネントを作成し、レジストリにマッピングするだけで済む。コンテンツのレンダリングはライブラリが自動的に処理してくれるため、非常に効率的で柔軟なウェブサイト開発が可能になる。これにより、非技術者であるCMSの編集者でも、ウェブサイトの構成を自由に組み立て、コンテンツを更新できる「CMS著者主導型」のウェブサイト体験が実現できるのだ。