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上の速度では「中」という評価
リニューアル後の構成
Wordpressの手前にNext.js on ECS、CloudFront、ElasticCache、Algoliaを置くことにしました。
Next.jsにすると使えなくなるWordpressの機能
- ページキャッシュ
- PVカウンター
- js plugins
特にページキャッシュがまるっとなくなって、WordpressのREST APIは仕組み上激遅くなるためページキャッシュ用にRedis、検索用にAlgoliaを選定しました。
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で収まってしまう・・・すごい。
リニューアル後の改善結果
ε=\__(ΦωΦ)_ ズコー
Next.js 9.2.0 からLightHouseのパフォーマンス劣化が報告されていて、PageSpeedInsightは爆死した。
実際の改善結果
DOMContentLoaded 80 ~ 150msec
First Meaningful Paint 210msec 惜しい!!
Load 400 ~ 450msec
GoogleAnalyticsのスコア改善状況
直帰率 77% => 67%
ページ/セッション 1.67 => 2.72 (なんか変なこと起きてそう確認中)
平均セッション時間 1分25秒 => 1分35秒
PageSpeedInsightはともかく、早くなったことで顧客体験はかなり良くなった。今後も継続的に改善を続けていき、分かりやすく・使いやすいWebメディアを目指していく。
リニューアルにかかったコスト
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大募集!
この記事が気に入ったらサポートをしてみませんか?