Qwikに移行してPageSpeed Insightsスコアが74点から100点に向上した

本記事は https://blog.physalis.net/2024/qwik-migration-pagespeed-100 からの転載です。

# Qwikに移行してPageSpeed Insightsスコアが74点から100点に向上した

先日さけのわのWebサイトをNext.js(App Router)からQwikに移行してPageSpeed Insightsのスコアが74点から100点に向上しました。この記事ではその過程と結果について説明します。

## さけのわについて

さけのわは、飲んだ日本酒を投稿するSNSで、100万件以上の投稿がある業界最大のサービスです。iOS版とAndroid版のアプリがあり、Webサイトは [https://sakenowa.com](https://sakenowa.com) でアクセスできます。

## 移行前の状況と課題

移行前も体感的なパフォーマンスは十分に速かったのですが、PageSpeed Insightsのパフォーマンススコアは74点でした。

![pagespeed-nextjs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2859/5cecc317-546b-d400-143b-ca235666b15a.png)


74点は一般的に良好なスコアです。SEO的には十分と言えるかもしれません。ただSEOに関してできることはどんどんやっていこうと考えていたので、最適化に注力しましたが、これ以上の改善策が思いつかない状態でした。

## Qwikへの移行を決断

そこでパフォーマンスが良いと評判のQwikへの移行を検討しました。JSXが使えるため移行が比較的容易そうだと考えました。最初は興味本位だったのですが、少し試したところすぐに移行できそうな感触があったため移行を進めることにしました。

期待していた効果は主に以下の2点です。

1. PageSpeed Insightsのスコア向上
2. それに伴うSEO効果（特にGoogleのクロールリソース削減によるインデックスページ数の増加）

## 移行プロセス

### アプリケーションの規模

さけのわのWebサイトは14ページで構成されています。参照がほとんどで、検索機能のために入力欄がひとつあります。

### コード変更

コードの移行自体は約1週間で完了しました。多くの場合は機械的な変換で対応できました。例えばコンポーネントは次のように変換できます。

```typescript
// React
export const HelloWorld = () => {
  return <div>Hello world</div>;
}

// Qwik
export const HelloWorld = component$(() => {
  return <div>Hello world</div>;
});
```

主な作業は、コンポーネントの変換と`useState`から`useSignal`などフックの変換です。

Reactの経験がある方ならチュートリアルと[React Vs Qwik](https://qwik.dev/docs/guides/react-cheat-sheet/)を読めば比較的簡単に開発を進められると思います。

ただいくつか難しい面もありました。

- エラーメッセージが一般的だったりエラー発生箇所としてレポートされるコードが根本原因と離れていて、原因の特定が難しい場合があります
  - 少しずつ変更しながら進めて、原因がわからない問題が発生したらいったん戻って原因箇所を特定するようにして進めました
- ソースコードに問題がるとdevサーバーが終了してしまうことがよくあります

それでもこの過程で大きな困難はなかったです。

### デプロイ

一方で、デプロイは当初1, 2日でできるかなと考えていたのですが、実際には1週間と予想以上に時間がかかりました。ローカル環境では問題なく動作していましたが、ステージング環境にデプロイすると様々な問題が発生したのです。

1. CloudFrontの設定：オリジンに転送するヘッダ、クエリーパラメータの正しい設定が必要でした。

   - `x-qrl`ヘッダ
   - `qfunc`クエリーパラメータ

   実際に送信されるリクエストを見ればわかるものですが、`x-qrl`ヘッダを見逃してしまって長い時間ハマってしまいました。

2. SPAナビゲーションの問題：環境変数`ORIGIN`をホスト名と同じに設定する必要がありました。

   ステージング環境だとページ遷移がすべて`location.href`での遷移になってしまう問題がありました。さっぱりわからなくてソースコードを読むと環境変数`ORIGIN`の設定が必要だとわかりました。（今回利用したAWS AdapterではなくNode Adapterのドキュメントには書いてありました）

#### Tips:  キャッシュが必要ならserver$ではなく`onGet`エンドポイントを使う

`server$`はサーバーの処理を型安全な関数として呼び出す機能です。当初はAPI呼び出しを`server$`を使って実現していたのですが、`server$`はPOSTリクエストを使用するため、キャッシュできません。キャッシュが必要なfetch処理には`onGet`エンドポイントを使用するのが良いでしょう。

## 結果

移行の結果、PageSpeed Insightsのスコアは74点から100点に劇的に改善しました🎉

![pagespeed-qwik.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2859/4655cbfa-3ef1-070c-2ca3-cb3fa3f19b66.png)

さらに、インデックス済みのページ数が約3倍に増加しました。ここまでは期待以上の成果です。サーチコンソールのスクリーンショットです。

![release-ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2859/9fa27307-c5d6-6805-4e90-4aeb8b9a609f.png)

## まとめ

さけのわのWebサイトをNext.jsからQwikに移行した結果、PageSpeed Insightsのスコアが劇的に向上しました。SEO効果が期待できる兆候が現れています。

今回の移行を通して感じたQwikの利点です。

- Qwikは比較的容易にPageSpeed Insightsのスコアを満点近くまで上げられる
- Next.jsでの最適化に比べて、より簡単にパフォーマンスを向上できる

課題もあります。

- ドキュメントや情報が比較的少ない
- Reactほどライブラリが豊富ではなく、選択肢が限られる

さけのわでは`qwik-speak`(i18n)と`@radix-ui/colors`（色定義）だけで十分だったので特に問題にはなりませんでした。

総じて開発体験はReact/Next.jsとあまり変わりませんでした。QwikはSEOを重視するプロジェクトにとっては良い選択肢だと思います。