STORES Product Blog

こだわりを持ったお商売を支える「STORES」のテクノロジー部門のメンバーによるブログです。

Nuxt 3 への移行に向けて頑張ってます

STORES フロントエンドエンジニアの wattanx です。

2022/11/16、ついに Nuxt 3 が正式リリースされましたね。

nuxt.com

私たちのプロダクトである STORES でも Nuxt を利用しており、絶賛 Nuxt 3 への移行中です。

本記事では、私たちのプロダクトにおいてどのようにNuxt 3 に移行しようとしているのか紹介します。

また、これは STORES Advent Calendar 2022 の 11日目の記事です。

移行の基本方針

Nuxt 2 を利用しているプロダクトを Nuxt 3 に移行する場合、以下の2とおりの方法が一般的だと思っています。

  • Nuxt 2 から Nuxt 3 に直接移行する。
  • Nuxt 2 から Nuxt Bridge に移行する。その後 Nuxt Bridge から Nuxt 3 に移行する。

Nuxt Bridge とは、かんたんにいうと Nuxt 3 の機能の一部を Nuxt 2 でも利用できるようにしたライブラリです。

Nuxt Bridge を使用すると、既存の Nuxt 2 のプロジェクトを Nuxt 3 にほぼ対応させることが可能です。

nuxt.com

私たちのプロダクトでは後者の Nuxt 2 から Nuxt Bridge に移行する。その後 Nuxt Bridge から Nuxt 3 に移行する。 方法で移行を進めることにしました。

Nuxt Bridge を経由する理由としては、下記のとおりです。

同じリポジトリ内で移行しやすく、高速化等の恩恵を受けられる

移行は基本的に移行ブランチを作成して移行していく予定で考えています。

移行中も続々と新機能や施策が追加されるため、移行ブランチの存続時間が長くなるとそれらの変更を移行ブランチにマージしていくのは大変だと考えていました。

Nuxt Bridge を経由する場合だと、Nuxt2 から Nuxt Bridge への移行 Nuxt Bridge から Nuxt 3 への移行 と2つの移行作業が発生します。

しかし、それぞれの移行ブランチの存続時間は Nuxt 3 に直接移行するよりも短いだろうと考えています。

Vue 3 に直接移行するのは難易度が高いため

Nuxt 3 へ移行するためには、Vue 3 への移行も必要です。

私たちのプロダクトでは、Nuxt 3 への移行Vue 3 への移行をまとめて対応するのは難しいと判断しました。

Nuxt Bridge を使えば Vue 2.7 が使用でき、Vue 2.7 と Nuxt Bridge から Nuxt 3 と Vue 3 への移行のほうが対応しやすいと考えています。

Nuxt Bridgeで動かない Nuxt Modules は剥がして自分達で作れる

一方で Nuxt Bridge への移行が避けられる理由として、Nuxt 3 に比べて Nuxt Bridge では対応している Nuxt Modules が少ないという問題があります。

ただし、私たちのプロダクトで使っている Nuxt Modules は公式の Nuxt Modules を使わず自分達で実装できると判断しました。

どのように移行していくのか

Nuxt 3 へ移行するにあたって、Vue 2系から Vue 3 に移行する必要があります。

また、Nuxt Bridge に移行するにあたって、Vue 2.7 への対応も必要です。

なので、私たちは下記のようなタスクに分けて進めています。

  • Vue 2.7、Vue 3、Nuxt Bridge にバージョンアップしなくても対応可能なタスク。
  • Vue 2.7 にバージョンアップしないと対応できないタスク。
    • Vue 2.7 にあげることでほぼ Vue 3 に対応できる。
  • Nuxt Bridge にバージョンアップしないと対応できないタスク。
    • Nuxt Bridge にあげることでほぼ Nuxt 3 に対応できる。

どのように進めているのか

Nuxt 3 への移行は進めたいが、プロダクトの機能開発を止めるわけにはいきません。

私たちのプロダクトでは、プロダクト開発を止めずに Nuxt 3 への移行を進められるように Nuxt 3 WG(ワーキンググループ)を立ち上げて、各調査や意思決定を行っています。

(フロントエンドのメンバーは9人でそのうち WG のメンバーは4人)

過去に調査を行なっていたタスク
過去に調査を行なっていたタスク

各種調査の結果、フロントエンドのチームメンバー全員で対応したほうがいい場合は移行手順をまとめて、Nuxt 3 WG 以外も含めてチームメンバー全員で対応しています。

WGが実際に行った作業

WG が実際に行った作業のうち一部を抜粋して紹介します。

bridge: false の状態でNuxt Bridge を導入する

まずは Nuxt Bridge を入れてみて、どのくらい変更が必要なのか検証してみました。

すると、下記のような課題が出てきました。

  • Nuxt Bridge を入れると、Vue 2.7 が入る。
  • Vue 2.7 にバージョンアップしないと、Nuxt Bridge に移行できない。
  • Vue 2.7 への移行もすぐにできない。

そのため、下記の方針でリリースしました。(特に問題は出ていません。)

  • bridge: falseの状態で Nuxt Bridge を導入する。
  • package.jsonresolutionsを使ってVue を2.6系に固定する。

Vitest への移行

私たちのプロダクトでは、テスティングフレームワークに Jest を利用しています。

Vue 2.7 へバージョンアップすると、テストが軒並み通らないということが判明しました。

時間を書けて調査した結果、原因がわからない状態でしたが Vitest に移行すると解決することがわかりました。

これ以上調査にコストをかけるよりも

  • Nuxt Bridge や Nuxt 3 では Vite を利用していきたいと思っていた。
  • 社内の他のプロダクトでも利用しており、移行したいモチベーションがあった。
  • @nuxt/test-utilsは Vitest と Jest の両方をサポートしているため。(バージョン3.0.0以降)

という理由から、この機会に Jest から Vitest へ移行することにしました。

現在、半分以上は Vitest に移行完了しています。

Vue.extend を defineComponent に置き換える

Vueファイルで TypeScript を利用する場合、以前はVue.extendを使った方法が主流でした。

しかし、Vue.extendは Vue 3 ではなくなるので、defineComponentに移行しておく必要があります。

また、defineComponentに置き換えても動作上問題ない(型チェックのみ)であると判断し、一括で置き換えました。(140ファイル程度)

emits option の追加

Vue 3 では.nativeが削除され、emits optionを追加することが実質必須になっています。

v3-migration.vuejs.org

Vue 2系でemits optionを書いても動作上問題がないため、Migration Strategyのとおり emit を使っているコンポーネントに対してemits optionを追加しました。

また、emits optionを追加するにあたって対象のコンポーネントの数が多いので、自動化ツールを作成しました。

github.com

Vueファイルのtemplatescript内で使用されているemitからイベント名のみを抽出し、文字列の配列形式でemits optionに追加します。

(このツールは ts-morph を活用して作成しています。)

このツールのおかげで一括変換しリリースできました。

また、ESLint のルールである vue/require-explicit-emits を適用することで移行漏れを防止しています。

最後に

移行作業は大変ですがさまざまな知見を得られて非常に楽しいです。

(Nitro 等あたらしいライブラリのことを知れたり)

Nuxt 3 への移行に具体的にやったことなどは、また別の機会に共有できればと思っています。

まだまだ課題は山積みなので、一緒に解決してくださる方募集中です。

jobs.st.inc