Nuxt2->Nuxt3rc移行の雑なメモ
追記 2023/10/07
rcのときの内容なのでだいぶ情報古いです。
現在は公式のMigration Guideも充実してきたのでこっちを見たほうが良いかと!
下記の個人サイトの移行を雑にメモしていきます
- コード量少なめ
 - Pinia導入済み
 - Composition API導入済み
 
Nuxt3の移行ガイドは2022/9現在未完のようなので Nuxt bridgeの移行ガイドを見ながらやってみる
とりあえずnuxtのバージョン上げてpnpm iしてみる
-   "nuxt": "^2.15.8",
+   "nuxt": "^3.0.0-rc.9",
各コマンドをnuxiに変える
-    "dev": "nuxt",
-    "build": "nuxt build",
-    "start": "nuxt start",
-    "generate": "nuxt generate",
+    "dev": "nuxi dev",
+    "build": "nuxi build",
+    "start": "nuxi start",
+    "generate": "nuxi generate",
@nuxtjs/composition-apiのエラーが出るので下記ガイドを参考に@vue/composition-apiに移行する。
まだエラー出ててビルドできないので合ってるかわからないがとりあえず下記をやった
- 
import { *** } from '@nuxtjs/composition-api';を消す (auto importされるため) - useContext(); -> useNuxtApp(); に変更
 - useFetch -> useLazyFetch
 
VSCodeの拡張機能の設定
ワークスペース内のみでveturを無効にしてvolarを有効にするようにした。
あとTake Overモードを有効にする
参考: https://zenn.dev/ymgn____/articles/e7709e88948446#take-over-modeを有効化
nuxt.config.jsをdefineNuxtConfig使う形に変更
拡張子を nuxt.config.js から nuxt.config.ts に変える
+   import { defineNuxtConfig } from 'nuxt';
+   export default defineNuxtConfig({
-    export default () => ({
オプションも変更あるかもしれないけどとりあえずtype error出てなさそうなのでそのままにしとく
tsconfig.jsonに1行追加する
{
+ "extends": "./.nuxt/tsconfig.json",
  "compilerOptions": {
    ...
  }
}
nuxt3で不要になッタモジュールを削除
Remove Incompatible and Obsolete Modules
Remove @nuxt/content (1.x). A rewrite for Nuxt 3 is planned (2.x)
Remove nuxt-vite: Bridge enables same functionality
Remove @nuxt/typescript-build: Bridge enables same functionality
Remove @nuxt/typescript-runtime and nuxt-ts: Nuxt 2 has built-in runtime support
Remove @nuxt/nitro: Bridge injects same functionality
Remove @vue/composition-api from your dependencies (migration guide ).
Remove @nuxtjs/composition-api from your dependencies (and from your modules in nuxt.config) (migration guide ).
.outputディレクトリをGit管理外にする
+ .output
CI/CDのデプロイディレクトリも合わせて ./.output/public  に変更。
ビルドするとpostcssのモジュール @nuxt/postcss8 でエラーが出る。nuxt3には対応していない(というかいらなくなった)ようなので直す
参考: https://stackoverflow.com/questions/70302520/nuxtjs-v3-and-tailwindcss-v3-postcss8-not-compatible
再度ビルドし直すもエラー
Cannot start nuxt:  resolver.resolveModule is not a function
@nuxtjs/style-resources がnuxt3に対応していないようなのでこれも直す。
参考: https://stackoverflow.com/questions/69953025/nuxt-3-resolver-resolvemodule-is-not-a-function
ついでにwebpackからviteに移行する。(webpackでやろうとすると自分でmoudule作ったりしないと無理そうでかなりめんどくさそう)
ちょっと気持ち悪い書き方だけどこうしないとsass:mathとかのメソッド周りででエラーが出てしまった。
  vite: {
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: `
@use "sass:math";
@use "sass:color";
@use "~/assets/scss/mixins.scss" as *;
          `,
        },
      },
    },
  },
~~~
  bridge: {
    vite: true,
再度ビルド
@nuxtjs/markdownitでエラー
 ERROR  Error compiling template:  {                                                                          18:41:53
  src: '/home/attt/Projects/attt-nuxt/node_modules/.pnpm/@nuxtjs+markdownit@2.0.0_webpack@4.46.0/node_modules/@nuxtjs/markdownit/dist/runtime/plugin.js',
  fileName: 'markdownit.js',
  options: {
    linkify: true,
    breaks: true,
    injected: true
  },
  filename: 'markdownit.js',
  dst: '/home/attt/Projects/attt-nuxt/.nuxt/markdownit.js'
}
現状Nuxt3対応していないので、
Issuesで上がっている内容を参考に、moduleを介さず直接markdown-itを使うように変更
1- install package npm install markdown-it
2- within your Vue Single File component ref your markdown
a- add to the script import md from "markdown-it";
b- in the script, create a renderer const renderer = md();
3- in the component template, use it in a dev like
nuxt-webfontloaderでエラー
 ERROR  Error compiling template:  {                                                                          18:45:55
  src: '/home/attt/Projects/attt-nuxt/node_modules/.pnpm/nuxt-webfontloader@1.1.0/node_modules/nuxt-webfontloader/lib/plugin.template.js',
  ssr: false,
  fileName: 'webfontloader.js',
  options: {
    google: {
      families: [Array]
    }
  },
  filename: 'webfontloader.js',
  dst: '/home/attt/Projects/attt-nuxt/.nuxt/webfontloader.js'
}
@nuxtjs/google-fontsがNuxt3対応しているようなのでそっちに乗り換えた。
axiosは使わずfetchを使うように書かれているので該当の記述を移行する
ここで今更ながら・・・dependenciesのvueのバージョンが古かったので上げる。
-    "vue": "2.6.14",
+    "vue": "^3.2.39",
piniaを最新版にする。
// Nuxt 2
export default {
  buildModules: [['@pinia/nuxt', { disableVuex: true }]],
}
// Nuxt 3
export default defineNuxtConfig({
    modules: ['@pinia/nuxt'],
})
<Nuxt /> を <slot /> に変える。
環境変数のオプションがprivateRuntimeConfigからruntimeConfigに変わったようなので移行
middlewareの仕様が色々変わってるので移行する。
- 
defineNuxtRouteMiddlewareを使って定義する - ファイル名を 
middleware/hoge.global.tsにすると勝手に全ページで実行してくれるようになるので便利(nuxtServerInitの処理をこれに移行できる) 
↓で変えた環境変数周り、Pinia内で環境変数を使用しているのでPinia内にも反映する
こうやって定義しておいて
  runtimeConfig: {
    MICROCMS_API_KEY: process.env.MICROCMS_API_KEY,
  },
使うときはnuxtのメソッドの useRuntimeConfig で呼び出すのだが、Piniaファイル内でuseRuntimeConfigするとエラーが出てビルドできず・・・。
危険な香りがするが、いったんmiddlewareから引数でPiniaに渡してあげるようにしておいた
(一応外から見えないようにはなっているので大丈夫そうではある)
  const runtimeConfig = useRuntimeConfig();
  if (process.server) {
    const postsStore = usePostsStore($pinia);
    await postsStore.getPosts(runtimeConfig.MICROCMS_API_KEY);
  }
issuesが上がってるのでバグ?なのかやり方が悪いのかどうなんだろう。。
.nuxt 以下のファイルがないためにCIがコケるので nuxi prepare を追加する
  "scripts": {
    "dev": "nuxi dev",
    "build": "nuxi build",
    "start": "nuxi start",
+  "generate": "nuxi generate",
    steps:
      ~~~
      - name: Install dependencies
        run: pnpm install
+    - name: Prepare Nuxt
+      run: pnpm prepare
Dynamic Routesで仕様変わってるので直す。
ファイル名を pages/_slug.vue のようにしていたのを pages/[slug].vue のように変える
@nuxtjs/google-gtagが3に対応していないので、vue-gtag-nextを使用するように変更する
static フォルダを pubic に名前変更する
v-deepを使ってると怒られる場合があるので直す。
参考にした記事: https://zenn.dev/mihorin1729/articles/21f0b44f9cbfc4#::v-deep、やめて?代わりに、:deep(<inner-selector>)にして?
(Nuxt3というよりはViteにした影響っぽいがで一応メモ)
ZennのRSSを取得してJSONに変換する処理を行うために使ってる rss-parser 周りでコンソールエラーが出てしまう
Cannot read properties of undefined (reading 'prototype') 
調べてみるとviteとxml2js(rss-parserの依存ライブラリ)の相性が云々っぽかったが、viteの知識不足でよくわからなかった。。
generate時のみ発生する。devのときは平気なようなのでnode.js周りの何かなんだとは思う
動作には影響無いもののエラーが出てるのは嫌なので・・・rss-parserを諦めて力技でxml->jsonに変換するコードを書くことにした。悲しみ。
ここで問題が発生。
pnpm generate後のページで、dynamic routingしているページにnuxt-linkで遷移するとuseFetchが走ってしまう。(runtimeConfigで設定した環境変数が取得できていないので401エラーになってる)
entry.d0610673.js:1 TypeError: Cannot destructure property 'publishedAt' of 'w.data.value' as it is null.
    at setup (_slug_.fea35164.js:1:4247)
たぶんuseFetch周りがSSGに最適化できていないんだろうなと思い、調べてみたところNuxt2のときのuseAsyncDataのような完全staticにできる機能はまだないということが発覚・・・・。まじか。。
下記ページで話されているserver配下にAPI定義するようなやり方等も試してみたものの結局だめだった。。。
追記 2023/10/7
めちゃくちゃ時間空いてしまいましたが、、最新バージョン(3.7)ではuseFetchが走らないようになっており、完全static可能になってました。(どのバージョンから変わったかは調べてませんが)
最後めちゃくちゃ時間空いた上に急に雑になってしまいましたが、時間が解決してくれたのでデプロイも成功し移行完了!