Next.js+next-on-pages+Tailwind CSS+Cloudflare Pagesの開発体験が良すぎた話(よくない点もある)【ブログ更新しました】

今週はCloudflareのDeveloper Weekでした🎉

ブログのコードを更新しました

今まではNext.js v12でPages Routerを利用していましたが、Next.js v13にしてApp Routerを利用するようになりました!(開発自体は四月初めにすでに終わっていました...) これでブログが一気に完成したのでBuildingを消しました🎉🎉🎉

この記事では更新するのに引っかかった点などを書いていきます。

next-on-pagesの問題とwrangler v2.20.0

Cloudflare PagesでNext.jsのApplicationを動かすためにはNext.jsのEdge Runtimeとnext-on-pagesを利用する必要があります。しかし、next-on-pagesで一個の_worker.jsを生成するとglobalで実行している処理が多すぎてCPU Limitに引っかかりデプロイできないという問題がありました。

ところが、先日_worker.js directory supportが行われたおかげでそれぞれのrouteのファイルが分割されたため1workerごとの処理が軽くなりNext.jsの大きいプロジェクトでもCloudflare Pagesにデプロイできるようになりました🎉 個人的にはv3.0.0の変更でも良かったと思いますが何故かv2.20.0で更新されていました...

Next.js v13.4とnext-on-pages

Next.jsではPagesを利用していなくてもerrorページは生成されるという仕組みですが、next.config.jsonにruntimeを記述する方法がなくなったためerrorがexperimental-edgeであることを明記できなくなってしまいNext.js v13.2を利用しています。 早く全く生成しないかnext-on-pages側が対応して欲しいです(PR立てる機運はあるんですが時間がない...)

App RouterにおけるComponentの記述方法

Atomic Designなどさまざまな書き方があるかと思いますが、私はlayout.tsxのようにそれぞれの階層にcomponentsフォルダがあってもいいのかなと思い、このような構成にしました。

この構成では、全てのファイルで共通して利用するものをsrc/componentssrc/app/index.tsx(layout.tsx)で利用するものをsrc/app/componentsに入れています。 また、src/app/articles/componentsにあるものはそれより下の階層でも利用していいという制約にすることで、ある程度共通利用されるComponentはその単位で再利用できるようにすることで、Atomic Designでいちいちsrc/components/molecule/articles/...を見にいくなどの手間を省くことができるようになりました(ファイル構造だけ見てる時でもシンプル)。 server/client componentはcomponents以下で分類しclient-onlyserver-only packageを利用しています。components内の分類方法はまだ考察していないので今後やっていきたいところです。

Custom DomainとTailwind CSSのDarkMode

このブログはTailwind CSSを用いていて、dark modeをTailwind CSSのclass modeでやっているのですが、ユーザーが自分で変更している場合は変更後の見た目、変更していない場合はprefers-color-scheme: dark queryで取得できるdark mode判定を利用したいのですが、Tailwind CSSの設定をcss内で変更する方法がなくCookie, Local Storageなどの方法を取るように公式が言っていますが、これを使うとFliker(ロード後一瞬だけ画面がチラつく現象)してしまいます。

これに対処するためにscriptタグでmediaを読み取るコードをasync, deferなしでロードするという方法があります。しかし、この方法をCloudflare Pagesで利用すると完全に理解していませんがカスタムドメインからアクセスした際にCacheの影響でHydration Errorが起きてしまうという問題がありました。 うまく実装する方法もよくわからなかったため、せっかくSSRしているので最初の一度のロードの際にcookieにsystem設定を書き込んでおき、その際にはFlikerしますがそれ以降はcookieの値を読んで自動で変更するようにしました。

Cloudflare Image Resizing

Vercel上でホスティングした時に利用できるImage ResizingはCloudflare Pagesでは利用できないので、Cloudflare Image Resizingを利用した新しいImage loaderを作成しました。 ちゃんとcacheされるかわかっていないので少し怖いです...(アラートは、設定した)

終わりに

開発は終わっていたのにCPU Limitのせいで一ヶ月ほど何もできていなくて久しぶりに触ったら割とまだコード読めてすごいな〜と思いました。

今週はCludflareのDeveloper Weekだったんですが、毎日1記事出すとかではなく一日に7記事も出てて意味わからんってなりました(すごい). これからもCloudflare使っていきます!

パフォーマンスも最高レベルなので満足しています。

これでサイトが完成したのでやっと色々記事が書ける... 今後は週一くらいで何か書いていきたいです。