jackmiwamiwa devblog

フロントエンドをメインに行ったことをまとめていくサイトになります。

Nuxt2 から Nuxt3にアップデートを行う

個人で開発しているものをNuxt2からNuxt3にアップデートしたため、その時に対応したこと等を記載していきます。

Nuxt2からNuxt3にアップデートしようと思った理由について

Vue2が2023年末にサポートが切れてしまうためVue3にアップデートさせる必要があった

vue2が2023年12月31日にサポート終了 (EOL) でNuxt2がVue2のみのサポートのため、Vue3サポートがされているNuxt3にアップデートする必要があったため。

Vue2のサポートについて

v2.vuejs.org

Nuxt2, Nuxt Bridge, Nuxt3で対応されているものについて

nuxt.com

Nuxtの3.0がアップデートされた

2022/11/17にNuxt3.0にアップデートされたため、個人開発レベルのものであればNuxt3を使うことができると思ったため。

一部パッケージでVue3にしかサポートされていない

パッケージの最新版を使用する場合、Vue3にしか対応されていない & 新たにインストールするのに古いバージョンを使う理由もなかったため。

一例としては以下パッケージになります。

ja.splidejs.com

github.com

Nuxt3の機能について

nuxt.com

変更前と変更後の各種バージョン

before

{
  "@nuxt/components": "^2.2.1",
  "@nuxtjs/composition-api": "^0.32.0",
  "nuxt": "^2.15.8",
  "vue": "^2.6.14",
}

after

{
  "nuxt": "3.0.0",
}

Nuxt3へのアップグレード手順について

nuxt.com

変更した箇所について

  • npm scriptsの変更
  • configファイルの編集
  • VueファイルをNuxt3にあった書き方に変更
  • process.browserからprocess.clientに変更
  • layoutファイル等の書き方を変更
  • 動的なページのpathの書き方の変更

1. npm scriptsの変更

nuxtjs.org

変更した箇所は大きくNuxt.jsを新規作成する際にnuxt generateした結果を確認するコマンドnuxt previewが追加されました。

nuxt startnuxt previewの違いについて

stackoverflow.com

変更箇所

before

{
  "scripts": {
    "build": "nuxt build",
    "dev": "nuxt",
    "generate": "nuxt generate",
    "start": "nuxt start",
  },
}

after

{
  "scripts": {
    "build": "nuxt build",
    "dev": "nuxt dev",
    "generate": "nuxt generate",
    "start": "nuxt start",
    "preview": "nuxt preview",
  },
}

2. configファイルの編集

nuxtjs.org

nuxt.com

nuxt.com

今回対応した箇所については以下になります。

nuxtjs.org

srcDir: ソースファイルのroot部分の定義。Nuxt3の変更にあたっては変更はなし

nuxtjs.org

css: ページ全体で読み込まれるcssファイルの定義。Nuxt3の変更にあたっては変更はなし

nuxtjs.org

buildModules: 開発時やビルド時にのみ必要となるもののパッケージの一覧。Nuxt3の変更にあたって外部モジュールで使用しているものはなかったため、この項目自体削除。

nuxtjs.org

components: Nuxt.jsでコンポーネントファイルを自動で読み込みを行うかの設定。静的なコンポーネントのみの場合componentsの設定は不要だが、今回は動的に取得したいパターンもあるため、componentsを設定。 今回のコンポーネントの変更で component/Atoms/HogeFugaコンポーネントの場合、以下のように修正は必要。

before: <hoge-fuga />
after: <AtomsHogeFuga />

動的コンポーネントがある場合のcomponentの設定方法参考

zenn.dev

変更箇所

before

import type { NuxtConfig } from '@nuxt/types'

const config: NuxtConfig = {
  srcDir: 'src',
  css: ['~/assets/scss/main.scss'],
  buildModules: [
    // https://go.nuxtjs.dev/typescript
    '@nuxt/typescript-build',
    // https://go.nuxtjs.dev/stylelint
    '@nuxtjs/stylelint-module',
    // https://github.com/nuxt-community/composition-api
    '@nuxtjs/composition-api/module',
    // https://Vueuse.org/guide/index.html
    '@Vueuse/nuxt',
    // https://github.com/nuxt/components
    '@nuxt/components',
  ],
  components: (() => {
    const common = {
      extensions: ['Vue', 'ts'],
      ignore: ['**/_*', '**/constants.ts', '**/hooks.ts'],
    }
    return [
      { path: '~/components/Atoms/', ...common },
      { path: '~/components/Molecules/', ...common },
      { path: '~/components/Organisms/', ...common },
    ]
  })(),
}

export default config

after

import { resolve } from 'path'

// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
  srcDir: 'src/',
  css: ['~/assets/scss/main.scss'],
  alias: {
    '~': resolve(__dirname, './src')
  },
  components: {
    global: true,
    dirs: ['~/components']
  }
})

3. VueファイルをNuxt3にあった書き方に変更

Nuxt3からVue3に対応されたため、composition-apiの書き方をする際に@nuxtjs/composition-apiのパッケージが不要に。 Vue3でsetup関数を使用することができるため、より簡単に記載することができるようになりました。 以下の2点も変更しています。

  • コンポーネントの名前を「ケバブケース(kebab-case)」から「パスカルケース(PascalCase)」に変更。
  • template部分にrootのノードが複数もつことができるようになった。

Vue3でのsetupの書き方について

v3.ja.vuejs.org

Vue3でのマルチルートノードコンポーネントについて

v3.ja.vuejs.org

変更箇所

before

<template>
  <div>
    <component-name1 />
    <component-name2 :array-list="arraySlice" />
  </div>
</template>

<script lang="ts">
import { defineComponent } from '@nuxtjs/composition-api'
import { array } from '~/filePath'

export default defineComponent({
  name: 'Page',
  setup() {
    const arraySlice = array.slice(0, 7)
    return { arraySlice }
  },
})
</script>

after

<template>
  <AtomsComponentName1 />
  <MoleculesComponentName1 :array-list="arraySlice" />
</template>

<script lang="ts" setup>
import { array } from '~/filePath'

const arraySlice = array.slice(0, 7)
</script>

4. process.browserからprocess.clientに変更

www.useful-blog.info

一部hooks部分でprocess.browserを使っていた箇所がNuxt3の変更に伴って動かなくなったため、process.clientに変更。

変更箇所

before

import { reactive, toRefs } from '@nuxtjs/composition-api'
import { useWindowScroll } from '@vueuse/core'
const { x, y } = 
  ? useWindowScroll()
  : { ...toRefs(reactive({ x: 0, y: 0 })) }

after

// Nuxt3のauto importにより、reactive, toRefsのimportは不要。
import { useWindowScroll } from '@vueuse/core'
const { x, y } = process.client
  ? useWindowScroll()
  : { ...toRefs(reactive({ x: 0, y: 0 })) }

5. layoutファイル等の書き方を変更

nuxt.com

Nuxt3でのlayoutファイル群の書き方も異なっていたため、以下のように変更しました。

変更箇所

before

layoutファイル側
<template>
  <nuxt />
</template>
pagesファイル側
<template>
  <component-name />
</template>

<script lang="ts">
import { defineComponent, useRoute, useMeta } from '@nuxtjs/composition-api'

export default defineComponent({
  name: 'PageName',
  layout: 'LayoutName',
  setup() {
    const route = useRoute()
    const paramId = Number(route.value.params.id)
    useMeta({
      title: 'ページタイトル名',
      meta: [{ hid: 'robots', name: 'robots', content: 'noindex' }],
    })
    return { paramId }
  },
  head: {},
})
</script>

after

layoutファイル側
<template>
  <slot />
</template>
pagesファイル側
<template>
  <NuxtLayout name="iframe">
    <ComponentName />
  </NuxtLayout>
</template>

<script lang="ts" setup>
const route = useRoute()
const paramId = Number(route.params.id)

useHead({
  title: 'ページタイトル名',
  meta: [{ hid: 'robots', name: 'robots', content: 'noindex' }]
})

definePageMeta({
  layout: false
})
</script>

6. 動的なページのpathの書き方の変更

nuxtjs.org

masteringnuxt.com

Nuxt3での動的ページの生成の方法も異なっていたため、以下のように変更しました。

変更箇所

before

File: /pages/users/_id.Vue
Url:  /users/123

$route.params = { id: "123" }

after

File: /pages/users/[id].Vue
Url:  /users/123

$route.params = { id: '123' }

今回は対応していないこと

1. storybookの対応

Nuxt3でのstorybookの対応がまだされていないため、今回のアップデートでは対応していません。

github.com

以下の方法で一部コンポーネントの表示は行うことはできましたがNuxtのauto importで読み込みを行っているものがエラーになってしまったため、今回は見送りました。

zenn.dev

<template>
  <div class="hoge" ref="ref">
    コンテンツ
  </div>
</template>

<script lang="ts" setup>
  // ここでrefの読み込みがないとのエラーが出る。
  const ref = ref()
</script>