Migrate to Nuxt3
自身のポートフォリオサイトを Nuxt2 から Nuxt3 へ移行する。
Nuxt3 への移行は公式で公開されているので、参考にしながら移行できるかどうか検証してみよう。
整理
- Nuxt2 でも Composition API 対応はしていない状況。
- 単純なポートフォリオサイトなので SSG で出力した静的 HTML を S3 にデプロイして配信している。
Nuxt3 のインストール
まずは Nuxt2 をアンインストールして Nuxt3 をインストールする
現時点では nuxt@3.1.1 が最新バージョンの模様。
npm remove nuxt && npm i nuxt@3
Config ファイルの更新
最初のステップとして Configuration の nuxt.config ファイルの変更が一番上に書かれているが TypeScript ベースに変更されているため、 tsconfig.json ファイルの修正を優先して着手する。
https://nuxt.com/docs/migration/configuration#migration-2
Nuxt3 で用意されている tsconfig.json を継承している模様。
{
"extends": "./.nuxt/tsconfig.json"
}
ただし、./.nuxt ファイルが Nuxt2 になっているので生成してあげる必要がありそう。
npx nuxi prepare
エラー調査1
上記コマンドで生成してくれるみたいだけどエラーが発生した。
$ npx nuxi prepare
Nuxi 3.1.1 21:59:24
ERROR Cannot read property 'options' of undefined 21:59:25
at axiosModule (node_modules/@nuxtjs/axios/lib/module.js:12:13)
at installModule (node_modules/@nuxt/kit/dist/index.mjs:435:9)
at async initNuxt (node_modules/nuxt/dist/index.mjs:2044:7)
at async loadNuxt (node_modules/nuxt/dist/index.mjs:2077:5)
at async loadNuxt (node_modules/@nuxt/kit/dist/index.mjs:519:19)
at async Object.invoke (node_modules/nuxi/dist/chunks/prepare.mjs:30:18)
at async _main (node_modules/nuxi/dist/cli.mjs:51:20)
@nuxtjs/axios モジュール関係でエラーになっていると予想。
Nuxt3 に対応しているモジュール一覧が公開されているので確認してみると axios は対応していないとみた。
https://nuxt.com/modules?q=axios&version=3.x
一旦 @nuxtjs/axios をアンインストールして、通常の axios を利用することにする。
nuxt.config.js からもモジュールを削除することを忘れないように!
npm remove @nuxtjs/axios
エラー調査2
次は @nuxtjs/pwa のモジュールでエラーが発生している模様。
このモジュールも Nuxt3 では対応していないためアンインストールして PWA はどうするかは別途検討することにする。
$ npx nuxi prepare
Nuxi 3.1.1 22:05:51
ERROR Cannot destructure property 'nuxt' of 'this' as it is undefined. 22:05:52
at pwa (node_modules/@nuxtjs/pwa/dist/pwa.js:733:10)
at installModule (node_modules/@nuxt/kit/dist/index.mjs:435:9)
at async initNuxt (node_modules/nuxt/dist/index.mjs:2044:7)
at async loadNuxt (node_modules/nuxt/dist/index.mjs:2077:5)
at async loadNuxt (node_modules/@nuxt/kit/dist/index.mjs:519:19)
at async Object.invoke (node_modules/nuxi/dist/chunks/prepare.mjs:30:18)
at async _main (node_modules/nuxi/dist/cli.mjs:51:20)
同じようにアンインストールしてコンフィグファイルから削除
npm remove @nuxtjs/pwa
もしかして
コンフィグファイルを一旦退避して Nuxt3 用に作り直した方がいいかもしれない。
書き方全然変わってるという事実に気がついた。
export default defineNuxtConfig({})
この状態で再度実行したらうまく動いた!!
あとで全面的にコンフィグファイルを書き直しが必要そう。
npx nuxi prepare
@nuxtjs/dotenv
元々 @nuxtjs/dotenv を導入していたが Nuxt3 ではデフォルトでサポートしているため、モジュールをアンインストールする
https://nuxt.com/docs/migration/configuration#dotenv
npm remove @nuxtjs/dotenv
もうこのような書き方をしなくてもよいのは素晴らしい
require('dotenv').config()
nuxt.config.ts
defineNuxtConfig が ESLint エラー発生している
'defineNuxtConfig' is not defined.
ESLint 系は一旦全てアンインストールして後から導入し直す
公式にも手順書いてあるから参考にする予定
https://nuxt.com/docs/community/contribution#use-eslint
package.json を更新
before
"scripts": {
"dev": "nuxt-ts",
"build": "nuxt-ts build",
"start": "nuxt-ts start",
"generate": "nuxt-ts generate"
}
after
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare",
}
npm run dev でエラー発生
別案件で nuxt@3.1.0 を利用しているがこんなエラー発生しているのをみたことがない。
$ npm run dev
Nuxi 3.1.1 22:56:16
Nuxt 3.1.1 with Nitro 2.1.1 22:56:16
22:56:19
> Local: http://localhost:3000/
(省略)
ERROR Cannot start nuxt: Cannot find module '@nuxt/vite-builder' 22:56:19
Require stack:
- /workspace/me/portfolio/index.js
Require stack:
- index.js
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:995:15) 22:56:16
at Function.resolve (node:internal/modules/cjs/helpers:109:19)
at Function._resolve [as resolve] (node_modules/jiti/dist/jiti.js:1:244249)
at resolveModule (node_modules/@nuxt/kit/dist/index.mjs:260:29)
at importModule (node_modules/@nuxt/kit/dist/index.mjs:290:24)
at bundle (node_modules/nuxt/dist/index.mjs:2490:82)
at build (node_modules/nuxt/dist/index.mjs:2466:11)
at async Promise.all (index 1)
at async load (node_modules/nuxi/dist/chunks/dev.mjs:6804:9)
at async Object.invoke (node_modules/nuxi/dist/chunks/dev.mjs:6858:5)
at async _main (node_modules/nuxi/dist/cli.mjs:51:20)
解決!
nuxt@3.1.1 から nuxt@3.1.0 にダウングレードしたら解消した。
となると、パッチ修正で何かしら更新があったに違いないと思って調べてみた。
https://github.com/nuxt/nuxt/releases/tag/v3.1.1
!?!?
パッチリリースなのに Update notes が書かれてる...もうこの時点でパッチじゃないでしょ。。と思ったのは自分だけではないはず。
今回は移行がメインのため、そのまま nuxt@3.1.0 を利用して必要に応じて nuxt@3.1.1 にアップグレードすることにする。
次は sass エラーが発生
Preprocessor dependency "sass" not found. Did you install it?
元々は node-sass を利用していたが、時代的に Dart Sass が推奨されている現状である。
そのため、node-sass をアンインストールして sass を別途インストールしたら解消した。
さて、npm run dev
で起動時エラーが発生しなくなったので、移行ガイドに戻って対応を進めることにする。
layouts/default.vue の書き換え
とは言いつつ .vue ファイルの書き換えを進めていこうかな。
https://nuxt.com/docs/migration/pages-and-layouts#migration-1
1つめ
<Nuxt />
から <slot />
に変更する
before
<template>
<div id="app">
<Nuxt />
</div>
</template>
after
<template>
<div id="app">
<slot />
</div>
</template>
2つめ
特に script で設定をしていないため、削除するだけで終わり。
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({})
</script>
Props の置き換え
元々は props の key で設定していたが defineProps
に置き換える必要がある。
before
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
props: {
src: {
type: String,
required: true,
},
},
})
</script>
after1
<script setup>
defineProps({ src: String })
</script>
after2
もし TypeScript の型定義を使いたい場合は以下のように定義する。
<script setup lang="ts">
interface Props {
src: string
}
defineProps<Props>()
// デフォルト値ありの場合は
// withDefaults(defineProps<Props>(), {
// src: ""
// })
</script>
めっちゃシンプルでよき!!
components の置き換え
Auto-Imports 機能により import DefaultButton from '~/components/atoms/DefaultButton.vue
などのインポート構文を書かなくても自動でインポートされる。自動でインポートされても TypeScript による型補完も効くみたいでとても開発体験が良くなってる。
$ tree -l components
components
├── Logo.vue
├── README.md
├── atoms
│ ├── RootIcon.vue
│ ├── SnsIcon.vue
│ └── UserIcon.vue
├── molecules
│ ├── HeaderMenuItem.vue
│ └── WorkItem.vue
├── organisms
│ ├── HeaderMenu.vue
│ ├── HeaderPc.vue
│ ├── HeaderSp.vue
│ └── SnsMenu.vue
└── templates
└── Portfolio.vue
コンポーネントは上記のようなファイル構成となっている。
自動インポートする際にはフォルダ名を含めたコンポーネント名が適用される。
例えば、UserIcon
のコンポーネントを呼び出す場合は AtomsUserIcon
の呼び出すルールとなっている。
サンプル
<template>
<AtomsUserIcon class="image" src="/images/profile_main.jpg" />
</template>
メタ情報の置き換え
useHead で置き換えが可能らしい。
https://nuxt.com/docs/getting-started/seo-meta#composable-usehead
before
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
head() {
return {
title: 'About',
}
},
})
</script>
after
<script setup lang="ts">
useHead({ title: "About" })
</script>
こちらもめっちゃシンプルに書けるようになって幸せ!!
公開ファイル設定
Nuxt2 では static ディレクトリに favicon や 固定の画像ファイルを配置していたが、
Nuxt3 では public ディレクトリに変更された。
これは単純にディレクトリ名だけ変更すれば問題ない。
特段高度な設定をしてた訳ではないのでこれでうまく動いた。
あとは細かい対応をするだけで完了しそう。
Nuxt2 では fontawesome 対応のモジュールが存在したが Nuxt3 ではモジュールがなさそう。
そのため、fontawesome ではなく Google Material Symbols を採用。
https://fonts.google.com/icons
設定は簡単で nuxt.config.ts の app.head 情報に追加。
export default defineNuxtConfig({
app: {
head: {
link: [
{
rel: "stylesheet",
href: "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200",
},
],
},
},
});