Closed12

Migrate to Nuxt3

Masayuki TsujiMasayuki Tsuji

整理

  • Nuxt2 でも Composition API 対応はしていない状況。
  • 単純なポートフォリオサイトなので SSG で出力した静的 HTML を S3 にデプロイして配信している。
Masayuki TsujiMasayuki Tsuji

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 を継承している模様。

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 用に作り直した方がいいかもしれない。
書き方全然変わってるという事実に気がついた。

nuxt.config.ts
export default defineNuxtConfig({})

この状態で再度実行したらうまく動いた!!
あとで全面的にコンフィグファイルを書き直しが必要そう。

npx nuxi prepare
Masayuki TsujiMasayuki Tsuji

@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

Masayuki TsujiMasayuki Tsuji

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 にアップグレードすることにする。

Masayuki TsujiMasayuki Tsuji

次は sass エラーが発生

Preprocessor dependency "sass" not found. Did you install it? 

元々は node-sass を利用していたが、時代的に Dart Sass が推奨されている現状である。
そのため、node-sass をアンインストールして sass を別途インストールしたら解消した。

Masayuki TsujiMasayuki Tsuji

さて、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>
Masayuki TsujiMasayuki Tsuji

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>

めっちゃシンプルでよき!!

Masayuki TsujiMasayuki Tsuji

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>
Masayuki TsujiMasayuki Tsuji

公開ファイル設定

Nuxt2 では static ディレクトリに favicon や 固定の画像ファイルを配置していたが、
Nuxt3 では public ディレクトリに変更された。

これは単純にディレクトリ名だけ変更すれば問題ない。

Masayuki TsujiMasayuki Tsuji

特段高度な設定をしてた訳ではないのでこれでうまく動いた。
あとは細かい対応をするだけで完了しそう。

Nuxt2 では fontawesome 対応のモジュールが存在したが Nuxt3 ではモジュールがなさそう。
そのため、fontawesome ではなく Google Material Symbols を採用。
https://fonts.google.com/icons

設定は簡単で nuxt.config.ts の app.head 情報に追加。

nuxt.config.ts
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",
        },
      ],
    },
  },
});
このスクラップは2023/02/05にクローズされました