本記事は Angular Advent Calendar 2023 の24日目の記事です❗
23日目は@ic_lifewoodさんで25日目は@lacolacoさんです❗
最新のAngularの機能をふんだんに使って、
Angular Advent Calendarの記事をツリーの飾り(オーナメント)にしたサイトをつくりました❗❗
- https://ver-1000000.github.io/angular-advent-calendar-2023/
- GitHub: https://github.com/ver-1000000/angular-advent-calendar-2023/
あまりおもしろみのあるサイトではないかもしれませんが、
「見た目から要件がすぐにわかる」ことを目指して作成しました。
他の方のAdvent Calendar記事に言及しつつ、実装の詳細を解説していきますので、
実際に触りながら読み進めていただければと思います❗
他の記事で言及されていた実装
Prettier & ESLint
Angularを入れたら最初に設定しておきたい、リンターとフォーマッタの設定です。
次のコマンドで導入したあと、生成された.eslintrc.json
を編集しました。
$ npm i -D prettier eslint-plugin-prettier eslint-config-prettier
$ # commit
$ ng add @angular-eslint/schematics
基本的に、最新のrecommendedな設定を使いたいニンゲンなので、
prettierとの共存のための設定以外ルールの変更などは特に行っていません。
(「アップデートのたびにルールの名前や設定ファイルの構造が変わったことを検知するのが難しくて嫌じゃない?」という気持ちがある)
しかし、有用なオプトインルールはたくさんあるので、導入の際は都度一考することをお勧めします。
-
Angular ESLintの導入と推しルール6選(2023) | @komura-c
- 改めて眺めてみるとどれも本当に有用ですね……。
Angular CDK
普通にWebサイトを作成すると、CDKの使いどころは結構多いのですが、今回はダイアログの作成のみに利用しています。
UI面は非常に薄いですが、反してアクセシビリティなどのサポートなどは手厚く、
実装の際は積極的に利用したいライブラリですね。
(この画面を見ただけでも「モーダルを開いたときに、UI上の最初の要素にフォーカスを当てる」粋なアクセシビリティポイントが嬉しい)
ちなみに、Dialogは内部的に利用しているOverlayなどが、
専用のCSSを読み込まないとなんのスタイルも当てられていない状態になるので、
次の一行をstyles.cssに書いておきましょう。
@import '@angular/cdk/overlay-prebuilt.css';
なぜかDialogのDocumentにはこのことが記載されていません。
CDK Dialogについて、より詳しい説明は次の記事をどうぞ。
NgOptimizedImage
「開発者があまり意識しなくても画像表示を最適化してくれるくん」です。
適当に使ってみると(NgOptimizedImage
をimportしてimgタグのsrcをngSrcにするだけ)、
実行時に警告を出してくれるので、対話的に実装できます。
より詳しい説明は次の記事をどうぞ。
ngSrcを記述する際はルートから始まるパスを書かないように注意!
assetsディレクトリに入れている画像を参照するために
/assets/xxx.png
などと書くと、build時にbase-hrefを設定している場合
パスの解決ができなくなってしまうため、
assets/xxx.png
や./assets/xxx.png
のように書く必要がある。
筆者はデプロイ時に画像が読み込まれない自体に陥って少しだけハマりました😢
SSG(SSR)
v17からはServer Side Generation(Rendering)がヒッッジョ〜に簡単になりました❗
プロジェクト作成時、対話的にssrサポートをONにするか聞かれるので、
ここで有効化したあとはnpm run build
でSSGの生成物が作成されます。
本サイトではSSRオプションをオンにしてGitHub Pagesにデプロイしているので、
すでに一度レンダリングされた結果が返ってくるようになっています。
背景のパーティクルの位置やオーナメントの色がランダムで変わるようになっているので、
JSをオフにした状態でページのリロードを走らせると違いが分かりやすいです。
他にもSSRについて、次の記事でそれぞれ詳しく書かれています。
SSGを利用した外部リソースのキャッシング
今回、オーナメントを表示するために、アプリ内のHttpClientでQiitaのRSSフィードから記事情報を25個取得しています。
ところが、実際にブラウザを更新すると、該当の通信は走りません。
What’s next for Server Side Rendering in Angularの記事によれば、
We’ve also made some updates to HttpClient. It will now cache requests made on the server to avoid re-fetching that same data again on the client.
とのことなので、どうやらSSRモードを有効にするとデフォルトでいい感じにキャッシュしてくれるようです!ス、スゲーー!!!
本サイトではmainブランチへのpush時に、GitHub ActionsのCI上でビルドが走るので、
このタイミングで通信情報が永続化されるわけですね。
Control Flow
ココ最近のアップデートでは大目玉商品ということで話題のControl Flowですが、
Advent Calendarでもやはりみなさん言及されていて、注目度が伺えます。
- 2023 年に入った Angular のさまざまなアップデート | kasaharu
- Angularにおける組み込み制御フローの導入とその背景 | かっこ
- Angular v17 で新しい制御フロー構文がやってきた!マイグレーションコマンドを試してみたよ | @kozy4324
- Control FlowとViewレンダリング | noxi515
- Prettier の Angular サポートの仕組みと built-in control flow 対応 | Sosuke Suzuki
本サイトでも早速使ってみました。
switch文なんかはかなりシンプルで適切な感じの書き方ができている気持ちになっていいですね。
trackByも非常に書きやすいです。
……ただ、ControlFlowの導入によってhtml内に@
記号が使えなくなった点について、
これを解決するための参照文字列を調査するのに少しハマりました。
もともとこの事象自体は知識として知っていたのですが、
「参照文字列」という言葉が頭に出てこなくて
アットマークの参照体(@
)が調べられず……。
アットマークはテンプレートに書くとコンパイルエラーが出るのですが、
ブレースの直前に書いてしまい、構文のパースが影響して
次のようなエラー内容になってしまい、適切な対応方法がしばらくわかりませんでした😢。
|6 col 51 error| ngtsc:Error:-995002:Unrecognized block @.
|14 col 6 error| ngtsc:Error:-995002:Unexpected character "EOF" (Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.)
|14 col 6 error| ngtsc:Error:-995002:Invalid ICU message. Missing '}'.
|6 col 51 error| ngtsc:Error:-995002:Unclosed block ""
比較的何もない箇所に@
を記述した場合は、次のようなエラーが出て対応方法がわかりやすいみたいです。
|1 col 1 error| ngtsc:Error:-995002:Unrecognized block @.
|1 col 1 error| ngtsc:Error:-995002:Incomplete block "". If you meant to write the @ character, you should use the "@" HTML entity instead.
新しい@Input
デコレータのオプション
地味に嬉しいInputのオプション機能、早速使ってみました❗
古いバージョンのAngularを使っていると「新しいInputなら……」と思うことが多々あるんですよね。
単純ですが非常に強力なAPIだと思います。
他の記事であまり言及されていない実装・小技
SVG
今回、イラストみたいなUIを実装するにあたって、SVGを多用することにしました。
こういったサイトの構築だと、
SVGによる実装がDOMのセマンティクスを汚さない気がしててスキなんですよね……。
(「イラストの中のクリスマスツリーの星」を表すタグとかにdivを使いたくない)
ただし、SVGによる実装は基本的に座標の絶対指定になってしまうので、
そこは賢くやらないといけませんね。
現在はコードの中に多くのマジックナンバーがあるので、これを除去していくのは課題です。
Angular Pipeとか使うといいかもしれません
新しいAngularとの相性についてですが、使い心地は昔と変わらずというところでした。
Control Flowなどで問題が起きるかなと不安でしたが、
案外すんなりと進めることができました💮。
GitHub Pagesへのホスティング
筆者は結構GitHub ActionsをつかってGitHub Pagesにホスティングしているのですが、
今回はここで結構詰まってしまいました……。
結論的には、Settings > Actions > General > Workflow permissions
の権限が弱かったことが問題でした。
今までここを触ったことなかったんで、最近デフォルト設定が弱くなったんですかね。
ちなみに、あまり凝っていないのですがGitHub Pagesにデプロイするワークフローの変更はこんな感じです。
ポイント
- actions用のymlを書く
- 今回はpeaceiris/actions-gh-pages@v3を利用
-
publish_dir
にはSSGで生成されるビルド結果の場所を指定する- Angular CLIで普通に作成した場合
.dist/APP_ID/browser
のパスを指定してやるといい
- Angular CLIで普通に作成した場合
-
build
コマンドで--base-href
を設定してやる- ちゃんとやるならenvrionment.tsとかでいい感じにやるのかな?
- ngSrcの絶対パスには気をつける
-
Settings > Pages > Build and deployment
の設定を適切に変更する- Source:
Deployment from a branch
- Branch:
gh-pages
/ (root)
- Source:
Signal API
一部ですが、Signal APIによる実装を頑張ってみました……❗
案外、今回はSignal APIを主軸としたAdvent Calendarの記事はありませんでしたので、
@lacolacoさんの次の記事にあるSimple PDS
パターンを参考にして組んでみてます。
実際に実装してみると、なるほどしっくりくるカモ…… いい感じです🚥。
この辺はコメントも厚めに書いてるので、ぜひコードの方をご覧ください❗
時間がなくて実装が間に合わなかったけど盛り込みたかったやつ
ルーティング(View Transitions API)
当初は記事の詳細表示をダイアログではなく、ルーティングを利用して表示しようとしていました。
この時の遷移にView Transitions APIを利用したかったのですが……。
UI的に遷移を踏まえたアイディアがパパっと出てこず、工数的に見送りました😢。
Deferrable views
クライアントでの動的な取得が行えれば@defer
とかの出番がありそうなので使用するつもりだったのですが、
いざ実装してみると、本アプリでは基本的に通信にリアルタイム性が求められません。
SSGが勝手に通信をキャッシュするため遅延読み込みの必要がありませんでした😽。
テスト/CI周り
npm run test
は通るようにしていますが、カバレッジはほぼ0みたいなもんなので、もう少し何かしら書いてあげたい。
あと、とりあえずテストの自動化とprettier/eslintのチェックをCIで動かしたいですね。
CSP_NONCEによるCSSインジェクション対策
ウオオこれ完全に知りませんでした……。
非常に簡単なので、基本的には意識して有効にするようにしたいですね。
あとがき
Advent Calendarに登録してすぐに「SSGを利用したブツを作って、他の人の記事を全部読んで関連してそうなやつをリファレンスしていく」という指針をたてたのですが、
実装の着手を先送りにしまくった結果、24日当日に泣きながら全部実装することになりました……。
しかしながら……
逆に言えば1日でそれっぽいアプリがほぼフルスクラッチでできたのはなかなかの成果ではないでしょうか❓
しかも工数のうち半分以上はWebデザインとSVGの作成に費やしているわけですから、Angularの生産力は驚かされますね💪
キリの良いところまでは進めましたが、時間がなくて実装が間に合わなかったけど盛り込みたかったやつがたくさんあるように、まだ色々課題を残しています。
Issueなどは整備していませんが、どこかで改修していけたらいいなと思います。(PRも歓迎)
それではみなさま、𝓗𝓪𝓹𝓹𝔂 𝓜𝓮𝓻𝓻𝔂 𝓒𝓱𝓻𝓲𝓼𝓽𝓶𝓪𝓼...💫