2018年5月4日にAngular 6がリリースされました。Angular 6は、Angular自体の機能というよりは、Angularをいかに使ってもらえるかというところに重点が置かれたリリース内容でした。その中の1つに、Angular Elementsという、Angularの利用を促進しそうな機能が新たに追加されました。詳細は記事内に書きますが、Angularで構築したコンポーネントを手軽に別のWebサイトで通常のHTMLのように扱えるCustom Elementsに変換する機能です。似たようなことがReactやVueでは既にできていて、Angularはずっと苦手としていた部分です。今回自分の勉強がてら、Angular Elementsの使い方をまとめてみました。参考にしてもらえればと思います。
目次
はじめに – Angular Elements とは
Angular Elementsは、AngularコンポーネントをCustom Elements(Web Componentsの機能の一部)として出力する機能です。このAngular Elementsを使用すると、静的なHTMLのコンテンツ内に、Angularで構築したコンポーネントをCustom Elementsとして手軽に取り込むことができるようになります。取り込んだCustom Elementsは、通常のHTMLの要素と同じように振る舞い、style
要素やscript
要素で操作できるようになります。
詳細は以下をご確認ください。
- Angular Elements Overview – Angular Docs
- Angular Elements概要 – Angular 日本語ドキュメンテーション
- Custom Elements – Web Components | MDN – Mozilla
Angular Elementsのリリースにより、WordPressのような別のサイトで、ReactやVueでは可能であった再利用可能なウィジェット的な使い方がAngularでも手軽にできるようになりました。しかもWeb標準技術のCustom Elementsとしてです。今後Angularの用途はこれまで以上に増えていくことが予想されています。
今回は、このAngular Elementsを使ったCustom Elementsの実装方法について紹介していきます。まずは、以下でAngular Elementsを使って実装したCustom Elementsのサンプルをご確認ください。
Angular Elements サンプル
以下は、Angular Elementsのサンプルです。Angular Elementsとして作ったCustom Elementsをこちらのブログに(jsファイルとして)読み込んで表示させています。
機能的には、テキストフィールドに入力した文字が、ボタン押下時に、Helloの後に反映されるというものです。それからマウスオーバーすると、Custom Elements内の背景色が変わります。こうした機能は、Angularとして実装している部分もありますが、一部はCustom Elementsとして読み込んだ後に、こちらのページ上で、style要素やscript要素を使ってスタイルや処理を書いています。
以下のように表示させたい箇所にCustom Elementsのタグを記述するだけで使えるようになります。
このようにCustom Elementsとしてページに読み込んだ要素は、普通のHTML要素を扱う感覚で扱えるようになるところが、なかなか面白いんじゃないかと思います。そしてAngularで実装したものを、こうしたブログなど静的なページにも簡単に取り込めるようになったことが何より嬉しいですね。
これから、このサンプルを通してAngular Elementsの実装方法について紹介していきます。なお、ソースコードについては、こちらのブログでも説明とともにこの後紹介していきますが、GitHub上にもアップしておきました。こちらも併せてご確認いただければと思います。
Angular Elements の開発環境を構築する
Angular Elementsの機能を利用するには、Angularのバージョンが6以上である必要があります。ほとんどの場合、Angular CLIを使って開発することが多いかと思いますので、Angular CLI前提で話を進めます。
Angular CLIのアップグレード
まずは、Angular CLIのバージョンを確認します。
もし、Angular CLIのバージョンが6以下であれば、以下のコマンドでAngular CLIを最新のバージョンにアップグレードします(インストールされていなかった場合でも、以下のコマンドでインストールされます)。
再度、ng --version
でAngular CLIのバージョンを確認します。
Angule Elements用のプロジェクトを作成
Angular CLIを最新のバージョンにアップグレードしたら、次はAngule Elements用のプロジェクトを作ります。以下のAngular CLIのコマンドでAngularプロジェクトを作成します。プロジェクト名(ディレクトリ名)は任意です。ここでは、「angular-elements-sample」としました。
ちなみに、Node.jsのバージョンによっては怒られてプロジェクトが作られない場合があるので、状況に応じてNode.jsのバージョンアップも行なってください。
プロジェクトを作成したら、プロジェクトディレクトリに移動して、ng add @angular/elements
コマンドを実行します。document-register-element.jsなどAngular Elementsに必要なポリフィルや依存関係がプロジェクトに追加されます。
ちなみに、ng add
もAngular 6(Angular CLI 6)で追加された機能で、Angularプロジェクトに新しい機能を追加します。
ローカルサーバを起動する
実装中は、ローカルサーバを立ち上げて実装内容を確認していくこととなるかと思います。以下のコマンドで、ローカルサーバを起動します。
ブラウザでlocalhost:4200にアクセスします(とりあえず、最初はAngular CLIのデフォルトのアプリが表示されます)。
これでAngular Elementsの開発ができるようになりました。次にコードを書いていきます。
Angular Elements を実装する
Angular Elementsの実装について説明していきます。実装の際のポイントは以下の通りです。
- ブートストラップ処理の変更
- Custom ElementsとしてホストされるAngularコンポーネントの作成
- Custom Elementsの持っている機能にアクセスする
フォルダ構成
今回の実装では、ルートコンポーネントはapp.componentとして、実際の機能は新たにhello.componentを作成して、こちらで実装していくことにします。
app/ ├─ hello/ │ └─ hello.component.ts ├─ app.component.ts ├─ app.module.ts └─ index.html
ブートストラップ処理の変更
Angular Elementsは、自分自身でブートストラップを行います。Custom ElementsとしてDOMに追加されると自動的にブートストラップし、取り除かれると自分自身で破棄します。つまり、ここでは通常のAngularで行うブートストラップの処理は必要ありません。
ここでは、@angular/elements
モジュールのcreateCustomElement
メソッドと、Custom Elementsで用意されているcustomElements.define
メソッドを使って、ブートストラップの処理を書きます。
まず、app.component.ts
を開いて、以下のように修正します。
createCustomElement
メソッドで、HelloComponent
をCustom Elementsに変換して、customElements.define
で、app-hello
要素として扱えるように定義するといった処理の内容となります。この時、Custom Elementsとして定義する要素名とAppComponent
のselector名は同じものとする必要があります。
次にapp.module.ts
を開いて、以下のように変更します。
@NgModule
デコレータのbootstrap
にAppComponent
を指定し、entryComponents
にHelloComponent
を指定します。これは、ブートストラップの対象をAppComponent
とすると同時に、実際にCustom ComponentsとなるHelloComponent
は、Angularアプリとは関係なくなるので、コンパイルの対象から外すということを意味しています。
FormsModule
は、ブートストラップには直接関係ありませんが、HelloComponent
で実装する機能のために読み込んでいます。
ブートストラップに関する実装は以上となります。
Custom ElementsとしてホストされるAngularコンポーネントの作成
ブートストラップ周りの処理を実装したので、次に実際にCustom ElementsとしてホストされるAngularコンポーネントの作成について説明していきます。ここでは、HelloComponent
として新たに実装していきます。
新たに作成したhello.component.ts
を開いて、以下のように記述します(template
とstyles
の部分は別ファイルとしても良いです)。
ここは、普段通りAngularのコンポーネントを実装します。上記のサンプルのコードも特に難しいことはしていません。
なお、サンプルで@Input
と@Output
の2つのデコレータを利用していますが、@Input
はCustom Elementsのプロパティとなり、@Output
はCustom Elementsのイベントとなるという点について覚えておくとよいでしょう。
つまり、以下のように実際にCustom Elementsとしてページに読み込んだ際に、name
属性に指定した値は、HelloComponent
内で@Input
を通して取得できますし、HelloComponent
内で@Output
として定義したイベントは、読み込んだページにてaddEventListener
を通して、イベントをハンドリングすることができます。
Custom Elementsの持っている機能にアクセスする
Angular Elementsは、さらにCustom Elementsの持っているHTML要素としての機能にアクセスする機能も持ち合わせています。@HostBinding
と@HostListener
の2つのデコレータを使います。この2つのデコレータは説明が難しいですが、@Input
と@Output
の逆の役割を持つものだと思ってください。
@HostBinding
は、Custom Elementsの属性に値をバインドするためのデコレータです。@HostListener
は、Custom Elementsのイベントを受け取るためのデコレータです。
実際にサンプルのコードに落とし込んだものが以下となります。
上記のコードでは、@HostBinding
を使って、Custom Elementsのstyle
要素のbackground-colorにアクセスし、背景色をAngular Elements側から指定するようにしています。また@HostListener
を使って、Custom Elementsのmouseover
とmouseout
のイベントの発火を取得するようにしています。
ここまで紹介してきた機能で、ほぼほぼAngular Elementsの実装が行えるようになるかと思います。
プロダクションビルド
続いて、Angular Elementsとして実装したものを、他のサイトで読み込むためのファイルにビルドする方法を紹介します。
通常のビルド
まず通常のビルドを行うには、package.json
に登録されている以下のビルド用のコマンドを実行します。このコマンドの実態は、ng build
コマンドです。
プロダクションビルド
プロダクションビルドを行うには、package.json
のscript
フィールドに以下のコマンドを登録し、ターミナルでnpm run build:prod
コマンドを実行します。UglifyJSによってファイルの圧縮や制限付きのデッドコードなどが削除されます。
dist
ディレクトリが新たに作成されて、その中にビルドされたファイルが出力されます。ただし、現状では生成されるファイルが、runtime.js
、polyfills.js
、scripts.js
、main.js
と4つもあります。この4つのファイルを全て読み込まないと、Custom Elementsが正常に動かないので、これだとせっかく作ったCustom Elementsも配布がしにくいですね。
出力されるファイルを1つにする
おそらく今後のバージョンアップでシングルファイルとして出力されるようになるかと思いますが、現状では自分でシングルファイルを吐き出すようにコマンドを作る必要があります。package.json
のscript
フィールドに以下のコマンドを登録します。
ターミナルで上記で登録したコマンドを実行します。
このコマンドを実行すると、runtime.js
、polyfills.js
、scripts.js
、main.js
の4つのファイルが一つにまとめられて、app-hello.js
というファイル名でdist
ディレクトリ内のangular-elements-sample
ディレクトリに出力されるようになります。
ちなみに、--output-hashing=none
は、ファイル名にハッシュがつかないようにするためのオプションです。--prod
を指定した場合、一緒にこのオプションを指定しなかったら、runtime.a66f828dca56eeb90e02.js
といったファイル名で出力されます。
これでシングルファイルとして出力されるようになりますので、別のページで読み込む場合も、このファイルを読み込むだけで済むようになります。配布する場合もだいぶ楽になりますね。
Custom Elements として別の Web サイトで使用する
最後に出力したCustom Elementsファイルを、別のWebサイトで読み込んで使う方法を紹介します。
使い方は簡単で、上記で出力したファイルをscript
要素で読み込み、Custom Elementsの要素を使用したい場所に設置します。設置したCustom Elementsの要素は、通常のHTMLの要素と同じように、style要素やscript要素を使って操作することが可能です。
実際のサンプルコードは以下のようになっています。
まとめ
以上、Angular Elementsの使い方の紹介となります。おそらく記事を読むだけだと、わかりにくい部分があるかと思いますので、実際に実装されることをお勧めします。特に@Input
や@Output
などのデコレータを使ったデータの入出力の部分など、実際に実装することで、使い方のポイントが見えてくるかと思います。
今回自分でAngular ElementsでCustom Elementsを作ってみて、やはり通常のHTMLと同様に扱えるようになるという点が面白いなと思いました。Custom Elements自体も正直よくわかっていなかった部分があるので、そういう意味でも今回Angular Elementsを通して、Custom Elementsの使い方がわかったのも収穫かなと思います。Angular Elementsが浸透したら、確実に世の中的にAngularの使用頻はこれまで以上に増えていくんじゃないかなと思います。ウィジェットやプラグインのようなものをAngularで作る文化が定着してくれると嬉しいですね。普及のなかなか進まないCustom Elements(Web Components)の普及にも一役買ってくれるとよいですね。
最後にAngularの公式ドキュメント以外に参考にしたサイトを紹介しておきます。
- Getting started with Angular Elements – Winsmarts.com
- Angular Elements — A Practical Introduction To Web Components With Angular 6
- Angular Elements Made Simple with CodeMix – Genuitec
- Building Custom Elements / Web Components with Angular 6
- What Are @HostBinding() and @HostListener() in Angular? – DZone Web Dev
また、今回のサンプルのソースコードについては、GitHub上にもアップしています。ユニットテストなどもちょこっと書いたりしているので、こちらも併せて見てみてください。
コメント