VuetifyもVue3に対応(一部除く)したようなので、Nuxt BridgeからNuxt3へのアップグレードしてみました。
変更が多くかなり大変なので、何回かに分けてナレッジをメモしていきます。
対象は、Nuxt.jsベースアプリケーション で公開しているdevelopとdevelop_spaceブランチです。
使っているパッケージや実装により、別途対応が必要になりますが、参考になれば幸いです。
- アップグレード方針
- アップグレード可能か確認
- Node.jsアップデート
- まっさらなNuxt3を作る(参考用)
- 差分を確認して、追加・変更(Nuxt3化)
- plugin.apply is not a function
- Cannot read properties of undefined (reading ‘onRequest’)
- Failed to resolve import “@inotom/vue-go-top”
- Cannot read properties of undefined (reading ‘breakpoint’)
- Cannot read properties of undefined (reading ‘loggedIn’)
- _ctx.$t is not a function(i18nを導入)
- $configがundefinedになる(runtimeConfig設定)
- Vuetifyを導入
- Vuetify: $vuetify.breakpoint.width -> $vuetify.display.width
- pagesが表示されない
- 【次回】vee-validateを導入
- 今回のコミット内容
アップグレード方針
過去のcommitを残したいので、現在のリポジトリを使う。
まっさらなNuxt3アプリを作って、参考に動かしながら、変更や不要なファイルを削除して行く。
package.jsonやnuxt.config.ts(.js)は、最低限でスタートして、追加して行く。
先ずは、ページが表示されるようにして、課題を解消して行く。
やる事が多いと破綻するので、今回やらない事を決めます。
Options APIはVue3でも動くので、Composition APIへの書き換えはスコープから外す。
同様にJavaScriptからTypeScriptへの書き換えも、設定等以外はスコープ外。
Mixinも止めたいけど、動くのでスコープ外。
JestからVitestへの変更は後ほど検討。→ 対応できました。
→ Nuxt BridgeをNuxt3に移行。VitestとVue Test Utilsを導入
アップグレード可能か確認
Vuetifyは、現段階では下記には対応していない。
v-calendar v-date-picker v-data-table v-skeleton-loader v-stepper v-time-picker v-treeview
使用している場合は代替え可能か、リリースを待つかを決める。
Nuxt.jsベースアプリケーションのmaster/developは未使用なので続行します。
space_master/space_developは、v-data-tableを使っているので、Vuetify Labs. のを試す?
→ Vuetify Labsとv3-infinite-loadingでv-data-tableを暫定対応する
忘れん坊 はv-calendar(Vuetify Labs.も未対応)とv-stepperを使っているので暫く待ってみて、場合によっては代替え探す事にします。
Node.jsアップデート
$ nvm ls-remote | grep 'Latest LTS' v16.20.2 (Latest LTS: Gallium) v18.18.2 (Latest LTS: Hydrogen) v20.9.0 (Latest LTS: Iron) % nvm install v20.9.0 % nvm alias default v20.9.0 % nvm ls -> v20.9.0 system default -> v20.9.0
まっさらなNuxt3を作る(参考用)
% npx nuxi init nuxt-app Ok to proceed? (y) ● yarn ● Yes % cd nuxt-app % yarn install % yarn dev -o
差分を確認して、追加・変更(Nuxt3化)
ディレクトリ構成の説明が解りやすかったので参考にさせて頂きました。
【Nuxt 3】Nuxt 2と比較しながらはじめるNuxt 3
staticディレクトリをpublicに変更
リネーム: static -> public
server/tsconfig.jsonをコピペ
{
"extends": "../.nuxt/tsconfig.server.json"
}
.gitignoreを変更
coverageとrobots.txtだけ元のを残しました。
# Nuxt dev/build outputs
.output
.data
.nuxt
.nitro
.cache
dist
# Node dependencies
node_modules
# Logs
logs
*.log
# Misc
.DS_Store
.fleet
.idea
# Local env files
.env
.env.*
!.env.example
# Coverage directory used by tools like istanbul
coverage*
/public/robots.txt
app.vueをコピペして、変更
before
<template>
<div>
<NuxtWelcome />
</div>
</template>
after
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
nuxt.config.tsをコピペして、変更
nuxt.config.jsは削除
CSRを使っているので、「ssr: false」を追加しています。
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true },
ssr: false
})
package.jsonを変更
ポートを5000番にしたいので、「–port 5000」を追加しています。
{
"name": "nuxt-app",
"private": true,
"type": "module",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev --port 5000",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"devDependencies": {
"@nuxt/devtools": "latest",
"nuxt": "^3.8.2",
"vue": "^3.3.8",
"vue-router": "^4.2.5"
}
}
tsconfig.jsonを変更
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
}
動かしてみる
予定通り?エラーになりました。
% rm -f yarn.lock % yarn install % yarn dev -o WARN [warn] [nuxt] Plugin /Users/xxxx/workspace/nuxt-app-origin/plugins/application.js is not wrapped in defineNuxtPlugin. It is advised to wrap your plugins as in the future this may enable enhancements. WARN [warn] [nuxt] Plugin /Users/xxxx/workspace/nuxt-app-origin/plugins/axios.js is not wrapped in defineNuxtPlugin. It is advised to wrap your plugins as in the future this may enable enhancements. WARN [warn] [nuxt] Plugin /Users/xxxx/workspace/nuxt-app-origin/plugins/utils.js is in legacy Nuxt 2 format (context, inject) which is likely to be broken and will be ignored. ERROR Failed to resolve import "vee-validate" from "components/users/update/Image.vue". Does the file exist? ERROR Failed to resolve import "vee-validate" from "components/users/update/Data.vue". Does the file exist?
ERROR [worker reload] Cannot read properties of null (reading 'address')
This issue will be resolved in the next patch version of nitro. In the meantime, you can safely ignore it. この問題は、nitro の次のパッチ バージョンで解決される予定です。それまでは、無視しても問題ありません。
plugin.apply is not a function
Mixinをpluginsディレクトリに置いていましたが、
自動インポートしようとしてエラーになるので、別のディレクトリに移動します。
TODO: mixinを止めた方が良いけど、先ずは移行が目的なので、後で対応。
ファイルを移動して、パスを変更
- import Application from '~/plugins/application.js' + import Application from '~/utils/application.js'
Cannot read properties of undefined (reading ‘onRequest’)
plugins/axios.jsで認証ヘッダを追加・保存していました。axiosは無くなったので、削除して、
TODO: 後で、Fetch APIに書き換えます。
→ Nuxt BridgeをNuxt3に移行。$axiosをFetch APIに書き換える。nuxt-lodashを導入
Failed to resolve import “@inotom/vue-go-top”
現段階でVue3に対応していないので削除して、
TODO: 後で対応検討します。
→ Nuxt BridgeをNuxt3に移行。上に戻るボタンに対応
[plugin:vite:import-analysis] Failed to resolve import “@inotom/vue-go-top” from “layouts/default.vue”. Does the file exist?
試したメモ(却下)
% yarn add -D @inotom/vue-go-top
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘_c’)
% yarn remove @inotom/vue-go-top
コードから削除
layouts/default.vue
- <go-top :max-width="48" :size="48" :right="24" :bottom="24" bg-color="#1867c0" />
- import GoTop from '@inotom/vue-go-top'
components: {
- GoTop,
Cannot read properties of undefined (reading ‘breakpoint’)
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘breakpoint’)
暫定対応(置換)
「$vuetify.breakpoint.width」->「$vuetify?.breakpoint?.width || 1300」
TODO: 後で、Vuetifyを入れる時に対応してから書き換えます。
→ Vuetify: $vuetify.breakpoint.width -> $vuetify.display.width
Cannot read properties of undefined (reading ‘loggedIn’)
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘loggedIn’)
暫定対応(置換)
「$auth.loggedIn」->「$auth?.loggedIn」
TODO: 後で、authを入れる時に対応してから書き換えます。
→ Nuxt BridgeをNuxt3に移行。nuxt-authを導入
_ctx.$t is not a function(i18nを導入)
Uncaught (in promise) TypeError: _ctx.$t is not a function
@nuxtjs/i18n(現段階では7.3.1)だとエラーになるので、
ERROR [worker reload] [worker init] Named export 'stringify' not found. The requested module 'file:///Users/xxxx/workspace/nuxt-app-origin/node_modules/devalue/dist/devalue.umd.js' is a CommonJS module, which may not support all module.exports as named exports.
@nuxtjs/i18n@next(8.0.0-rc.5)を導入します。
Setup · @nuxtjs/i18n
% yarn add -D @nuxtjs/i18n@next
before(nuxt2): nuxt.config.js
modules: [
'@nuxtjs/i18n',
],
i18n: {
locales: [
{ code: 'ja', iso: 'ja', file: 'ja.js' }
],
defaultLocale: 'ja',
lazy: true,
langDir: 'locales/'
},
after(nuxt3): nuxt.config.tsを変更
export default defineNuxtConfig({
devtools: { enabled: true },
ssr: false
+ ssr: false,
+ modules: [
+ '@nuxtjs/i18n'
+ ],
+ i18n: {
+ vueI18n: './i18n.config.ts'
+ }
})
i18n.config.tsを追加
import { ja } from '~/locales/ja'
export default defineI18nConfig(() => ({
legacy: false,
locale: 'ja',
messages: {
ja
}
}))
locales/ja.js -> .tsに変更
折角なので、tsに変更します。(jsonでも良いけど、自由度が高いので)
- module.exports = {
+ export const ja = {
app_name: 'NuxtAppOrigin',
<省略>
}
$configがundefinedになる(runtimeConfig設定)
before(nuxt2): nuxt.config.js
const environment = process.env.NODE_ENV || 'development'
const envConfig = require(`./config/${environment}.js`)
// eslint-disable-next-line nuxt/no-cjs-in-config
const commonConfig = require('./config/common.js')
export default defineNuxtConfig({
publicRuntimeConfig: Object.assign(envConfig, commonConfig),
publicRuntimeConfigは、runtimeConfig.publicに変更されています。
after(nuxt3): nuxt.config.tsを変更
+ import { commonConfig } from './config/common'
+
+ const environment = process.env.NODE_ENV || 'development'
+ const config = require(`./config/${environment}.ts`)
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true },
ssr: false,
+ runtimeConfig: {
+ public: Object.assign(commonConfig, config.envConfig, { env: { production: environment === 'production', test: false } })
+ },
config/common.js -> .tsに変更
こちらも折角なので、tsに変更します。(jsonでも良いけど、自由度が高いので)
- module.exports = {
+ export const commonConfig = {
// ログインAPI
authSignInURL: '/users/auth/sign_in.json',
<省略>
}
development/test/production.js -> .tsに変更
- module.exports = {
+ export const envConfig = {
debug: true,
<省略>
}
呼び出し方も変わっているので、置換
「$config.」->「$config.public.」
Vuetifyを導入
【公式】Get started with Vuetify 3 — Vuetify
GitHub – vuetifyjs/vuetify: 🐉 Vue Component Framework
-> MIT licensed
% yarn add -D vuetify sass vite-plugin-vuetify @mdi/font
TODO: @mdi/fontは@mdi/jsを使った方が小さくなるらしいけど、先ずは移行が目的なので、後で検討
plugins/vuetify.tsを追加
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(createVuetify({
components,
directives
}))
})
nuxt.config.tsを変更
+ import vuetify from 'vite-plugin-vuetify'
import { commonConfig } from './config/common'
i18n: {
vueI18n: './i18n.config.ts'
- }
+ },
+ css: [
+ 'vuetify/lib/styles/main.sass',
+ '@mdi/font/css/materialdesignicons.css'
+ ],
+ build: {
+ transpile: ['vuetify']
+ },
+ hooks: {
+ 'vite:extendConfig': (config) => {
+ config.plugins!.push(vuetify())
+ }
+ },
+ vite: {
+ ssr: {
+ noExternal: ['vuetify']
+ },
+ define: {
+ 'process.env.DEBUG': false
+ }
+ }
})
Vuetify: $vuetify.breakpoint.width -> $vuetify.display.width
window.innerWidthだと、template内で変更が反映できなかったので、
vuetifyのuseDisplayで取得するように変更しました。
$vuetify.display.widthで取得できました。但し、dataの段階ではundefinedになる。
node_modules/vuetify/lib/composables/display.mjs
state.xs = xs; state.sm = sm; state.md = md; state.lg = lg; state.xl = xl; state.xxl = xxl; state.smAndUp = !xs; state.mdAndUp = !(xs || sm); state.lgAndUp = !(xs || sm || md); state.xlAndUp = !(xs || sm || md || lg); state.smAndDown = !(md || lg || xl || xxl); state.mdAndDown = !(lg || xl || xxl); state.lgAndDown = !(xl || xxl); state.xlAndDown = !xxl; state.name = name; state.height = height.value; state.width = width.value; state.mobile = mobile; state.mobileBreakpoint = mobileBreakpoint; state.platform = platform.value; state.thresholds = thresholds;
暫定対応した置換を変更
「$vuetify?.breakpoint?.width || 1300」->「$vuetify.display.width」
ただ、dataの段階では取得できないので、createdでセットするように変更しています。
data () {
return {
- drawer: this.$vuetify.display.width >= 1264 // NOTE: md(Medium)以下の初期表示はメニューを閉じる
+ drawer: null
- }
+ },
+
+ created () {
+ this.drawer = this.$vuetify.display.width >= 1264 // NOTE: md(Medium)以下の初期表示はメニューを閉じる
+ }
}
pagesが表示されない
layouts/default.vue
- <nuxt />
+ <slot />
【次回】vee-validateを導入
表示はされましたが、vee-validateがないのでエラーになりました。
次回は、ここから記載します。
デザイン崩れもあったりで、まだまだ対応が必要そうな予感。
→ Nuxt BridgeをNuxt3に移行。vee-validateを導入
今回のコミット内容
origin#507 差分を確認して、追加・変更(Nuxt3化)
origin#507 Mixinのディレクトリ変更
origin#507 エラー暫定対応
origin#507 i18nを導入、runtimeConfig設定
origin#507 Vuetifyを導入
origin#507 上に戻るボタン追加、widthの取得方法変更
origin#507 バージョンアップ、リファクタ
“Nuxt BridgeをNuxt3に移行。先ずはVuetifyでページが表示される所まで” に対して2件のコメントがあります。