Slide 1

Slide 1 text

Amebaチョイス 立ち上げの裏側 ~依存システムとの闘い~

Slide 2

Slide 2 text

自己紹介 2 AmebaLIFE事業本部 五十嵐 大地(Daichi Igarashi) X: @mr_ynu_2014_no4 / GitHub: Dai7Igarashi ● 20新卒 フロントエンジニア@Ameba ● Ameba Pick → ブログ → Amebaチョイス 立ち上げ → Owl出向中 ● SEO関連の開発を多数経験 ● 目標はフルスタック

Slide 3

Slide 3 text

アジェンダ 3 ● Amebaチョイスを取り巻く技術 ● しんどかったこと・乗り越えた方法 ● 成果と振り返り ● 締め

Slide 4

Slide 4 text

Amebaチョイスを取り巻く技術 4

Slide 5

Slide 5 text

サービス紹介 5 2024年5月15日リリースした、商品比較メディア。 「Amebaチョイス」を検索してみてね!

Slide 6

Slide 6 text

開発経緯 6 去年 Ameba x CyberOwl によるライフスタイル管轄が誕生。 CyberOwlのノウハウ・システムを利用し、Ameba発のSEOメディア立ち上げへ。

Slide 7

Slide 7 text

記事配信の大まかな流れ 7 商品モジュール (SSR)

Slide 8

Slide 8 text

記事配信の大まかな流れ 8 記事本文エリア (SSR)

Slide 9

Slide 9 text

記事配信の大まかな流れ 9 ページ全体 (SSR)

Slide 10

Slide 10 text

記事配信の大まかな流れ 10 なんか複雑すぎん🤔?

Slide 11

Slide 11 text

microCMSでやる場合の比較 11 vs

Slide 12

Slide 12 text

microCMSでやる場合の比較 12 vs OwlのCMSについては 詳しく触れません(ご容赦🙏)

Slide 13

Slide 13 text

しんどかったこと・乗り越えた方法 13

Slide 14

Slide 14 text

制約と願望 14 ● DB参照モジュールは ○ SSRしてCMSに返す ○ 個々でhydration用scriptを実行 ● CMSはSSR結果を記事配信サーバに返す ● Amebaで標準化されつつある構成が良い†1 ● DB更新系&SEO対策のためSSR必須 ● App Router使いたい(使ってみたい) ● ウィジェットサーバは分離したい <直感 †1. Muddy Web #4 「Amebaブログの会員画面システム刷新の道程」を真似たい

Slide 15

Slide 15 text

しんどかったこと1. 記事用CMSのレスポンスがHTMLのため、UI作りが難しい 15 記事本文はHTML(文字列)で返されるので、Reactコンポーネント作りが無理。 CMS側でclassを自由につけられるので、それでひたすら頑張る... これについては工夫の余地がなかったので諦め😇

Slide 16

Slide 16 text

しんどかったこと1. 記事用CMSのレスポンスがHTMLのため、UI作りが難しい 16 CMSが返すDOM構造で対応不可なUIは、createPortalでDOMに差し込む(荒技)

Slide 17

Slide 17 text

しんどかったこと2. ウィジェットhydration用scriptがNative ESM + libモードでビルド必須 17 これだけならViteが良さそうだが、Viteでのサーバビルドは不都合が多い。 ● express動かすのにvite-plugin-nodeなどが必要。 ○ CJSでのサーバ実行自体に必要そうだが、ロックインがヤダ(制御が難しい)。 ● importするライブラリによってはESM→CJSがうまくいかずエラーになる。 ○ vite-plugin-esmoduleとか色々試したが、やはり制御が難しいのでヤダ。

Slide 18

Slide 18 text

しんどかったこと2. ウィジェットhydration用scriptがNative ESM + libモードでビルド必須 18 そこで、クライアントはvite・サーバはtsup(esbuild)でビルドを分けた。

Slide 19

Slide 19 text

しんどかったこと3. viteとtsupに分けたらcss modulesの同期取れない懸念出てきた 19 CSS Modulesは、仕様は決まっているが実装は各々。 ビルドツールが異なると、SSR↔hydration間のclass名が不一致の懸念あり†1。 そこで、viteビルドのhash値をtsup側でSSR結果に埋め込むようにした。 †1. hydration後の結果を強制的に正にする方法は、出来ない場合があるのでやらない vite tsup

Slide 20

Slide 20 text

しんどかったこと4. デプロイ方法を良く考えないと修正リリース時に障害が起きる 20 ウィジェットのhydrationエントリファイルは choice-widget.js のみ。 これは事前にCMSに登録するもので、バージョニングするには工夫が必要。 バージョニングしない状態で、Amebaプラットフォームに沿って ● クライアント用assetを先にS3に保存 ● ローリングアップデートによるサーバデプロイ を行うと、修正リリース時のみhydrationエラーの可能性が出てくる。

Slide 21

Slide 21 text

しんどかったこと4. デプロイ方法を良く考えないと修正リリース時に障害が起きる 21 この問題に対しては ● デプロイ戦略の変更は変更コスト・金銭コストを鑑みて一旦やらない ● バージョニングはメンテナンス性を鑑みて一旦やらない ことにし、代わりに ● 後方互換性を持たせた段階リリース ● リリースに関するドキュメントの整備 で暫定対応。

Slide 22

Slide 22 text

しんどかったこと5. App RouterではCache-Controlを使ったCDN制御が難しい 22 キャッシュの責務はCDNに一任し、アプリケーションのキャッシュは切りたい。 force-dynamic等を指定すると、 ● アプリケーションのキャッシュはOFFになる ● が、Cache-ControlがApp Router側で制御される(private等が付与される) www.ameba.jpのFastlyはAmebaチョイス以外も管理しており、 Cache-Controlを見てキャッシュ判定をしているので、そこは汚したくない。 ※ Cache-Control的にはキャッシュしないのにCDN側でキャッシュさせるのはそもそも不自然

Slide 23

Slide 23 text

しんどかったこと5. App RouterではCache-Controlを使ったCDN制御が難しい 23 そこでApp Router用にカスタムCache-Controlヘッダを作成。 Fastly側でCache-Controlを上書き。 Fastly(vcl)

Slide 24

Slide 24 text

成果と振り返り 24

Slide 25

Slide 25 text

成果 25 ● Owlのシステムを使った(Owl以外での)開発実績を作った ● Amebaのプラットフォーム上で開発出来た ● Amebaで標準化されている構成のため、新規参入コストを低く出来た ● ロックインを極力避け、制御や移管が容易な状態に出来た

Slide 26

Slide 26 text

振り返り 26 ● ビルドが複雑化したので、ウィジェットサーバを分離しておいて助かった ● ビルド・hydration・キャッシュの深い部分を学べた💪 ● App Router導入のメリットを検証出来ていないのが心残り😢 ● リリース障害等、テストで未然に障害を防げる仕組みがあると良い

Slide 27

Slide 27 text

締め 27

Slide 28

Slide 28 text

28 とても勉強になる開発でした。 本日はご清聴ありがとうございました!