Angular2のウェブフロントエンド開発に携わっていて難しいと思うことなど振り返り
ウェブフロントエンド開発に携わらせてもらっていて、なかなか大変です。てんやわんやでひたすら頑張るしかないという状況で、ブログを書いている場合ではないと思います。しかしせっかく頭を抱えるような難しさを感じているので、それを新鮮なうちに言葉にしておきたいと思いました。
背景
ウェブフロントエンドと一口に言っても千差万別だと思うので背景を書きます。
10月ごろから既存のウェブサイトを再構築する作業に携わらせてもらっています。仕事内容の詳細は僕から見るとこんな感じです。
- 目的
- 既存サービスのウェブサイトを新しいコンセプトでリニューアルする
- 具体的には、SEOとUXの改善が特に大事
- 技術
- Angular2
- TypeScript
- Rails(slim)
- Bootstrap
- チーム
- ディレクター1名 + エンジニア4人(サーバーサイド x 2 + ウェブフロントエンド x 2) + デザイナー1.5人(デザイナーは社内に1人しかいない -> 途中から1人入社 -> 引き継ぎつつコミットしていただいてる)
- 4人のうち1人はCTOなので全コミットできるわけではない(見るからにいろいろ忙しい)
- 自分
- 趣味でウェブサイトを作ったときにRails, Backbone.js, Reactあたりは一応触ったことある
- 作る流れ
- 企画 -> デザイン -> 開発
- デザインと開発はほぼ並行
- 細かい仕様は開発途中に随時ディレクターやデザイナーに確認
- 企画 -> デザイン -> 開発
以上を踏まえて、今感じている難しいことなどを書き残しておきます。
1. どこでHTML作るの問題
(良い意味でも悪い意味でも)社内で一番盛り上がったテーマのような気がします。もともとSPAとして開発していたウェブサイトでしたが、今回はSEOに気を遣わなければならなくなりました。
JSで動的に作られたHTMLをGoogleがどこまで読んでくれるのかわからないこともあり、SEO対策に万全を期すにはサーバーサイドでHTMLを作らないといけないのでは、という話になり、どこをRails側のslimで書き、どこをAngularのJSに作ってもらうかということに悩みました。
なんやかんや行ったり来たりがあった上で、SEOが本当に大事なページはslimで書くようにして、読み込みで表示が増えるような部分についてはページ遷移で対応したり、コンポーネントが初期化されたときにslimに書いたhtmlを除去するなどしてどうにかすることになりました。ビューをサーバーで生成するということがほぼ無いiOSやAndroidと比較すると、これはWeb特有の悩みなのかなと思います。
個人的には、使っているときに画面がガチャガチャしないように気をつけるのが大事だと思います(ガチャガチャをちゃんと言葉にすると、1ページの表示の間に、その中の要素の幅・高さ・色などがユーザーから見て何度も変わることです)。サーバーサイドで作ったHTMLを返すのに比べて、JSでHTMLを動的に作ると画面の要素はガチャガチャしやすいので、気をつけなければいけません。
2. CSS方針
普通にRailsの /assets/stylesheets
下にscssファイルを書いているんですが、ポリシーみたいなものを考えず手探りで汚いCSSをたくさん書いてしまっています。すみません。本当にすみません。
3. コンテナとコンポーネント
Angularのコンポーネントを、Container Components と Presentational Components に大きく分けています。hoge.container.ts
とhoge.component.ts
のように、ファイル名から明確に区別しています。
Containerは状態や外部とのやりとりを管理します。たとえばサーバーと通信するサービスを利用してデータを読み込んで状態を更新したり、子のコンポーネントから受け取ったイベントに応じたリクエストをサーバーへ投げたりします。
対してComponentは、状態をもらってそれを表示すること、あるいはユーザーからのアクションを受け取って親のContainerに渡すことに専念します。
この考え方の元ネタはというと、Redux作者の @dan_abramov がmediumに投稿した記事です。
見た目のコンポーネントと状態管理のコンポーネントを分けることで、Presentational Components の再利用性を高めることの利点を、以下のように書いています。
You can use the same presentational component with completely different state sources, and turn those into separate container components that can be further reused.
全く違うステートソース(状態の元)に、同じPresentationalコンポーネントを使うことができ、それらをcontainer componentsに分離し、さらに再利用することもできる。とのこと。
しかし自分はどうもこの考え方を実践しきれていません。コンポーネントがユーザーからのアクションを受け取ったときに、もうそこで状態管理までしてしまえばいいじゃないかという気持ちになります。イベントを親に持っていくにはAngularの場合はEventEmitterというクラスを使って子コンポーネントのイベントを親コンポーネントへ転送するのですが、それを手間に感じてしまって、親のContainer Component が管理するべき状態を、子のPresentational Component で持ってしまうのです。
上の記事で言われているようなコンポーネントを切り離すことの利点をよくよく思い返しながら作っていかなければ、と思います。
4. RxJS
難しい。
とりあえず以上です。何か思い出したら書き足します。