ドラクエウォークの3周年イベントでメタルキングの剣を運良く引くことができて上機嫌なしゃけごんです。

先月の2022年8月に当サイトはNext.jsへ移行しまだまだ習作が続く中で運用しておりますが、大きなバグも減って来たのでこれまでの移行に対しての知見などをまとめられたらと思い書き記しておきます。



↑3月下旬から土日祝を全て注ぎ込んだ図です。がんばった!


当サイトの変遷と技術の移り変わり





当サイト「flap around」は2010年6月からまだ販売開始したばかりのiPhoneを便利に使うブログとして開設しました。

その頃はSeesaaブログか何かで初めてなんとなくHTMLが書けてCSSは書けない程度の知識だったのですが、生きる道すがらWeb制作の勉強をし始めて色々な知識がついて来たので、さくらサーバのレンタルサーバを借りて自分でWordPressサイトに移行したり、その後にWeb制作が仕事となり、様々な知識が増えた中でLinuxも少し扱えるようになったのでConoHaのVPSでNGINXサーバを立ててその上にWordPressを載せて運用したりして来ました。

仕事としてWeb制作業界にいると色々な噂を見聞きします。そんな中でも一際目立って聞こえ始めたのが「Next.jsは超速くてCEOにも良いらしい」という眉唾な噂でした。

私が居る界隈は「HTML+CSS+JavaScript+PHP」という良く言えば枯れた技術、悪く言えば古い技術の世界が主流で、私は普段「HTML+SCSS+JavaScript(&JQuery)+PHPを軽く、程度のスキルでどちらかといえばフロント寄りのお仕事をしています。

私の持っている技術では今よく見かける遷移をせずに見た目をデータに基づいて華麗に変更するにはJavaScriptでAJAX通信をしてDOMをガリガリ変更するようなことが求められます。

それそれで慣れたら結構書けるのですが、状態の管理やイベントの呼び元の管理やDOM生成などはかなりコード量がすごいことになって後で見たくない…みたいなことも起きて来ていました。

そんなレガシーな技術の中で一番気になっていたのはページ遷移とは切っても切れない縁があることでした。ページの切り替わりはシームレスでありたい、そんな個人的な夢をずっと持ち続けてWeb開発に取り組んで来ました。

当ブログではそのページ遷移を少しでも面白くしたい、ということから「Barba.js」を導入し、ページ遷移をpopStateで管理し、遷移先のページをHTMLとして読み込んで本文とmetaタグを書き換えて表示するようなページづくりを行なっていました。

遷移についてはある程度満足していたのですが、問題となって来たのはSEOでした。

元々SEOはそこまで強くないですが、常に読み込みの遅さでGoogle Insightsでは点数が低い状態でした。これはWordPressの使用上、ページがアクセスされてからWordPressの関数が実行されページが作成される・もしくはキャッシュを返すまでに必ず時間がかかるためと考えられました。

SEOの点数を上げるには「いつかWordPressは脱却しなければいけない」と考えていました。

そんな中、JavaScriptは大好きだったので、数年前から個人的にNode.jsやVue.js+Vuexなどを入門してはこれまで培ったWebの技術の考え方の違いに破門にされるということを繰り返していましたが、たまたま見つけたコワーキングスペースのもくもく会に通うようになった時に参加者の方が「Next.js」をやってみると話を聞いて自分もやってみようと手を出したのがきっかけとなってリリースするまでこぎつくことができました。

前書きが長くなりましたが、スキルがWordPressのfunctions.phpが触れてHTMLとSCSSとJavaScriptでなんでもやってやるぞ!と思っている人間がNext.jsに挑戦した際にしんどい思いをしたポイントを思いつく限り書いていこうと思います。ではいってみましょう。

Node.jsがベース





まずいきなりですがNext.jsを開発する環境を構築するには「Node.jsが必要ですよ」という話です。

TypeScriptやVue.jsやReactなんかでもまずはnpmやyarnでinitしてみたいな話で、今JavaScriptで開発していると言えば当たり前の事ですが、WebでもPHPの世界だとそこまで使わないという場合も少なくありません。

私はCSSを生成するSCSSを扱うのにタスクランナーであるGulpが流行った事もあり、その際に学習していたのでいくらか使えたのみたいな事やVue.jsで開発環境を構築するのに使ったりなどもあったので幸い習得していました。

フロントエンドロードマップを見たらわかるように道程は長く果てしないのです…。

WordPressのデータをそのまま使うには



さて開発環境の構築ができた所で、これまで使用していたWordPressのデータをそのまま使ってNext.jsに移行するにはどうしたらいいのかを整理しなければなりません。

私は「WordPressの管理画面はそのまま使う」ことを選択しました。あくまで変更する箇所は見た目だけをNext.jsに任せたいと思ったからです。

記事投稿については管理画面のブログを執筆するための入力補助が使えるプラグインの資産や自作ショートコードやNotionで記事を書いてWordPressの投稿へインポートするPythonista3の自作プログラムなど記事を書くためのツールは充実させていたということも挙げられます。

そうなると、WordPressはWordPressとして置いておいて記事投稿はその管理画面から行い、データだけをNext.jsへ渡す必要がありました。

データを渡すには例として以下の方法があります。


  • WordPress REST APIの利用

  • WordPressにGraphQLでデータが取得できるようになるプラグインの導入



私は、ググった際に記事の多い印象を受けたWordPress REST APIを利用する事にしました。

この考え方は結構色々な記事でも見受けられますので、それなりに情報は揃っていますので作りやすいかと思います。

Reactもあるぞ



Next.jsからWordPressのREST APIを叩けばいいことはわかったのですが、Next.jsでどうやって書くの?となるとそれはReactになります。そうReact。

Reactは宣言的UIを作るためのライブラリで、Viewを生成するにはまずデータが存在しデータが変われば変更の必要なViewを自動的に生成してくれるなんとも凄いライブラリです。

私がJavaScriptを本気で勉強しはじめた2015年あたりに「なんかReactってすごいらしい」という事が囁かれ始めた頃に自分もオライリーの本を買って学習しようと試みましたが、まだクロージャがなんなのかもわからない自分には到底理解できるシロモノでなく、そっと押し入れにしまっちゃうおじさんした思い出が蘇ります。

それから7年、この間にReactも進化しコンポーネント型宣言だったものが関数的な宣言にシフトしており、React Hooksという革命が起きていたようでした。

私はVue.js Ver.2を勉強していたので言語体系が近いものに触れたおかげで幾分か分かりは早いかと思いましたが、このHooksのおかげでまた学習コストは上がった感じはあります。

体感としてはNext.jsでシンプルに表示させるだけならばバケツリレーな作りでそこまで大変な目には遭わなかったかと印象は受けます。

しかしながら通常のHTML+CSS+JavaScriptのような書けばとりあえず動くようなことはないのでなかなかヘビーでした。楽しいですけどね!

Next.jsの基本





やっとこさNext.jsの根幹を攻めることにします。

Next.jsで作成されたサイトはまず1ページの真っ白なHTMLをレンダリングし、その中身をJavaScriptを用いて書き換えていくような動作となります。

これはSPAの仕組みと同じでNext.jsにもSPAで動作するモードがあります。

Next.jsの面白い所はSSGにあり、SSGはビルド時に表示するページを全て一旦JavaScriptの動作に都合のよいデータとHTMLファイルに変換してファイルとしてルーティングしながら格納します。

ページにはSEOに関係するタグのみをHTMLに書き、初期表示でコストのかかるデータを別途遅延読み込みさせることでページ表示の速度が上がりSEO上にも強いサイトとなる、といった具合でしょうか。

サブディレクトリもうまいことルーティングしてくれます。

この仕組みを利用するためにはgetStaticPathsとgetStaticPropsの動きを理解する必要があります。

この動きが頭に入っていないうちはどこでハマっているのかすら理解できなくなることもしばしばあったので、雰囲気以上に掴んでおきたいポイントと思います。

getStaticPaths



getStaticPathsはそれぞれ必要なページのURIを取得してどのページを作るよと宣言する関数です。

/pages/post/[slug].jsのようなpagesフォルダ内のサブディレクトリはビルド時に走査され中の[slug].jsgetStaticPathsでWordPress REST APIに記事のslugを[{params{slug:”iphone14-review”}}]のような形にした配列を渡すことでNext.js上にファイルとして生成されます。

ここで指定された配列だけがファイルとして格納されますので、各々のサブディレクトリでfetchAPIなどを用いてWordPress REST APIを叩いてやる必要があります。

getStaticProps



getStaticPropsはgetStaticPathsで作成したページにアクセスされた時に表示するデータを取得する関数となります。

引数にparamsがあり、getStaticPathsに返した配列のparamの中の値{slug:”iphone-review”}がそのままキーと値として使用できます。

またこのgetStaticProps内でfetch API等でWordPress Rest APIに記事情報を取得する事となります。

Next.jsでハマったメモ



さて、ここから開発時にハマった、意味を取り違えていた等のメモを書いていきます。

取得したデータが雑すぎて大変





getStaticPropsでWordPress REST APIから記事データを取得してきますが、取得した記事データはWordPressによってレンダリングされた後のHTMLファイルとなります。

はじめはその方が楽でいいじゃんとも思っていたのですが、いざ表示させてみるとかなり厳しくなったのでかなり記事取得後に正規表現などを使って整形しまくったので予め綺麗にしておくことも視野に入れた方がいいと思います。

例えば、ショートコードを拡張するようなプラグインを利用していた場合、PHPで書き出すだけで済んでいるプラグインならば問題ないですが、JavaScriptも絡んでいて別途プラグイン内のJavaScriptを読み込んで処理させているようなものであれば動作しない可能性も高いので、プラグインを活かすとなるとそのプラグインがどのように作用しているかも見る必要があります。

他に、画像データなどはURLがレンダリング時のAPIのドメイン名である場合もあるため、別ドメインに指定する場合は正規表現で変換する必要もあります。

styleタグが悪さをする



はじめは、受けとったデータをそのままdangerouslySetInnerHTMLで表示させる方法をとっていましたが、useRefで画像の拡大処理を書きたいなと思った際にただHTMLとして書き出したデータのイベントをとって良いかわからなかったため、react-html-parserでJSXに書き戻すように仕様を変更しました。

その時、styleタグが原因でページが表示できない旨のエラーが表示されるようになりました。

過去にWordPressの記事側でちょっとデザイン的に良くない時にstyleタグでちょっと修正していたものがJSXではstyle={{””}}のような書き方をしないとエラーが吐かれるため起きていたこととなりました。

これもまた、正規表現でstyleタグのstyle=””を消す処理を入れる事で対応しました。あとはCSSに任せよう。

WordPressの記事は自由度が高いため、それをきちんと表示させるために後処理がグッと増えてしまったので結構辛い思いをしました。

取得した値のURLエンコードが不揃い



getStaticPathsで取得した値が日本語だったら勝手にエンコードされていている事があってページが表示できたりできなかったりと悩まされたこともありました。

getStaticPathsで取得した際に、decodeURIComponentでデコードできるまでデコードしてからparamsに渡すことで取り扱いが楽になりました。

URLがデコード/エンコードされているかどうかを知る方法は?

SSGなのでAWSのS3で展開したい





さて、Next.jsでだいぶ動くようになってきたので、そろそろどこに置いて運用するかを考える時期がきました(初めからしておけよ)

Next.jsの開発元のVercelにデプロイする方法も考えたのですが、アフィリエイトをするには無料プランでは認められておらず、有料プランで$20/月かかるとの事で一旦見合わせました。

SSGは予めレンダリングしておくのであとはWebサーバであればどこにおいても動く事が特徴的なのでAWSのS3に置く事にしようと思いました。

WordPressは管理画面付きでWordPress REST APIも必要なのでどこかのサーバに置こうとしてはじめはlightsailに置いたのですが、安いプランだとAPIを叩いた時のデータ取得が非常に遅くてローカル環境の10倍くらいの速度がかかるのに辟易してしまったので、とりあえずWordPress環境はローカルに置いておくという選択にしました。

どこか良い所があれば、サーバに置いてREST APIの呼び先を指定してやれば問題なく動くので勘案中のままとなっています。

S3はAWSのサービスですが、これもそこまで深く知らなかったので利用できるまでにかなりの時間を要したこととなりました。

特にWordPressのURLが/2022/09/iphone14-reviewという設定にしていて、Next.js on S3では/post/iphone14-review.htmlというURLにアクセスされなければならない場合などにCloudFront@edgeでrewrite処理を挟まないといけないなど、知らないことだらけで連休が一気に消化されていったのは良き思い出です。。

結果S3+CloudFront+Route53の環境で動いています。

しかし、Next.jsの肝の一つ画像の自動リサイズを担うNext/Imageなどのサーバサイド処理は機能しなくなりますので要注意です。

一旦動いてしまえばあとは思いつくままに



とまぁ、ここに辿り着くまでに幾多の困難を乗り越えてきました。

一旦動き始めましたらもうあとは思いつくままにアレンジしてやろうと思っています。

そんなflap aroundをどうかよろしくお願いいたします。

この記事が誰かのつらさの何かに役立てばと思います