見出し画像

Next.jsでWordpressのデザインリニューアルした話

ウェディングニュースをNext.jsにリニューアルしました

リニューアルの目的
1.SEOトラフィックの獲得
2.ユーザー体験の向上
3.採用

引き金となったのは2019年11月にSearchConsoleに速度レポートが出たことで、SEOとして投資すべきは「速度」と判断しました。

あわせて、チームとしてUX No1を目指しているので、速度はとても重要なKPIです。

すべてのページを200msecで返すことが今回のゴール。

元の構成

Wordpress on EC2(t3.xlarge)
- nginx
- php-fpm

 使用しているプラグイン
- w3total cacheでpage cache
- Fast Velocity Minify
- defer.js
- ShortPixel
- 他、Wordpress Popular Postなど約30プラグイン利用

t3.xlargeのスペック
- vCPU 4(ベースラインパフォーマンス/vCPU 40%)
- Memory 16GiB
- $120/m

80万MAU、200万PVくらいをこの1台でさばいていました。

W3 Total Cacheのページキャッシュがあると普通に1秒くらいで表示できている状況でしたが、SearchConsole上の速度では「中」という評価

スクリーンショット 2020-03-25 15.07.35

リニューアル後の構成

Wordpressの手前にNext.js on ECS、CloudFront、ElasticCache、Algoliaを置くことにしました。

Next.jsにすると使えなくなるWordpressの機能
- ページキャッシュ
- PVカウンター
- js plugins

特にページキャッシュがまるっとなくなって、WordpressのREST APIは仕組み上激遅くなるためページキャッシュ用にRedis、検索用にAlgoliaを選定しました。

Next.js構成図

Algoliaを使ってみた感想

Algoliaを使ってみて、とにかく早く動き、早く実装できるので、Wordpressを入稿ツールにしてフロントエンドを構築する場合にはおすすめです。

・WP Search with Algoliaというプラグインでデータ連携が画面ぽちぽち
・レスポンス 30msec 未満で返ってくる
・実装が楽(下記)
// example
import algoliasearch, { Index } from 'algoliasearch';

export const searchClient = algoliasearch(
 'applicationId',
 'apiKey',
);
export const WpUser: Index = searchClient.initIndex('wp_users');

export const wpPostAuthorCache = async (id: string): Promise<Author[]> => {
 const key = `cache:api:author:${id}`;
 const cache = await redis.connection.get(key);
 if (cache) {
   return JSON.parse(cache);
 }

 const res = await WpUser.getObjects([`${id}`]);
 if (res.results.length) {
   const authors = res.results.map((result: any) =>
     normalizeAlgoliaUser(result),
   );
   await redis.connection.set(
     key,
     JSON.stringify(authors),
     'ex',
     60 * 60 * 24,
   );
   return authors;
 }
 return [];
};

キャッシュとセットでAlgoliaを利用すれば、スターターの$29のプランでまかなえます。データ量が多い場合は課金がまた高くなるのですが、Wordpressのリニューアルで5万記事以上保有していることは稀だと思うので$29で収まってしまう・・・すごい。

リニューアル後の改善結果

スクリーンショット 2020-03-25 16.03.04

ε=\__(ΦωΦ)_ ズコー

Next.js 9.2.0 からLightHouseのパフォーマンス劣化が報告されていて、PageSpeedInsightは爆死した。

実際の改善結果
DOMContentLoaded
80 ~ 150msec
First Meaningful Paint 210msec 惜しい!!
Load 400 ~ 450msec

スクリーンショット 2020-03-24 21.34.33

スクリーンショット 2020-03-24 21.34.00

GoogleAnalyticsのスコア改善状況

直帰率 77% => 67%
ページ/セッション 1.67 => 2.72 (なんか変なこと起きてそう確認中)
平均セッション時間 1分25秒 => 1分35秒

PageSpeedInsightはともかく、早くなったことで顧客体験はかなり良くなった。今後も継続的に改善を続けていき、分かりやすく・使いやすいWebメディアを目指していく。

リニューアルにかかったコスト

スクリーンショット 2020-03-26 21.59.54

clocだと2万行ほど書いていたらしい。当初見積もってたよりも1ヶ月伸びたのは単純に、あれもこれもと機能追加してしまったことが原因で、そのせいでリリースタイミングもコストも膨れ上がってしまってCTO失格だなと少しだけ反省している。

Next.js+Wordpressで困ったこと

Wordpress REST APIが劇的に遅い
Wordpressはリクエスト毎にスクリプトをロードして、実行する設計なのでプラグインを入れれば塵積で遅くなり、必要ない処理が大量に実行されてしまっている。

これを解決するために、shortinitという機能があるが十分ではない。shortinitを使ってもウェディングニュースの場合は 900msec が 500msecに改善しただけで、結局遅い。

必要な loader を時前で全部書いてみたが、結局Algoliaを使って解決した。

900msec => under 30msec となり劇的に改善
Wordpressのプラグインで解決したい時がある
Sitemap.xmlの出力なんかはWordpressのAll in One SEOから出力したほうが楽だし、プレビューの機能や外部公開確認のプラグインもそのまま使いたかった。

そんなときは変にNext.jsに処理させずに、ALBで特定のURL・パラメータのときはWordpressを直接参照するようにして、なるべく工数がかからないようにリニューアルできた。
Wordpressのビジュアルエディターにcssを適用する
スタイルがNext.js側に来たので、Wordpressのテーマと同期を取る必要があった。

今回はカジュアルに、GitHub Actionsのビルドプロセスの中で、Wordpress用のスタイルを作成して、Wordpress側は@import url;をすることで解決した。
画像のLazyLoadingをどう実現するか?
普通にWordpressから返す post.content はこうなっている。

<img src="xxx.jpg" alt="hoge" />

pictureに変えたかったり、何やのかんやのしたい場合はfunctions.phpで書いてしまうか、受け取ったテキストを置換してしまう。

例えばこんなふうに

const replaceImgSrc = (html: string): string => {
 const regex = /img[^>]+\bsrc=["']([^"']+)["']/g;
 return html.replace(regex, `img src="${PLACEHOLDER}" data-src="$1"`);
};

useEffect(() => mountLazyLoadImages(), []);

We are Hiring!!

ウェディングニュースを運営しているオリジナルライフでは、顧客志向なプロダクト開発ができるチームを目指しています。もちろんオンラインだけでなくオフラインとの統合もテクノロジーで解決するので社会全体をエンジニアリングするメンバーを募集しています。

世間的には新型コロナで採用が止まる中ですが、引き続きWebデザイナー・Swiftエンジニア・Webエンジニア・CMO大募集!


この記事が気に入ったらサポートをしてみませんか?