LoginSignup
1
1

More than 1 year has passed since last update.

Vuetify v3.0(Beta) 導入メモ

Posted at

はじめに

2022年4月頃に見たら、Vuetify 3がそろそろリリース予定(当時は2022年6月予定と書かれていたような)だったので、Vue 3をぼちぼち触り始めたのですが、なかなかリリースされませんね。。。
ドキュメンテーションに時間がかかっているのでしょうか。

痺れを切らしたので、まだBeta版ですが使い始めてみました。
Vue 2 の頃のコードのコピペでは上手くいかなかったところをメモしておきます。

インストール

Vite / Vue3 でセットアップ済のプロジェクトに Vuetify 3 を後から追加してます。

$ vue add vuetify

いくつかファイルの追加や上書きがされています。

$ git status
On branch add_vuetify
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   index.html
        modified:   package-lock.json
        modified:   package.json
        modified:   src/App.vue
        modified:   src/main.ts
        modified:   vite.config.ts

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        src/assets/logo.svg
        src/components/HelloWorld.vue
        src/plugins/vuetify.ts
        src/plugins/webfontloader.ts
        src/views/HomeView.vue

no changes added to commit (use "git add" and/or "git commit -a")

特に上書きされているものは、元のコードが消されてしまっていたりするので要修正でした。

package.json
{
  "name": "firebase-test",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "serve": "vite preview",  // 追記されたが、previewと被ってるので後から削除した
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview",
    "test": "vitest"
  },
  "dependencies": {
    "@mdi/font": "5.9.55", // 追記された
    "firebase": "^9.8.3",
    "roboto-fontface": "*", // 追記された
    "vue": "^3.2.25",
    "vue-router": "^4.0.16",
    "vuetify": "^3.0.0-beta.0", // 追記された
    "webfontloader": "^1.0.0" // 追記された
  },
  "devDependencies": {
    "@testing-library/vue": "^6.6.1",
    "@types/webfontloader": "^1.0.0", // 追記された
    "@vitejs/plugin-vue": "^3.0.3",
    "@vue/test-utils": "^2.0.2",
    "jsdom": "^20.0.0",
    "typescript": "^4.5.4",
    "vite": "^3.0.8", // アップデートされた
    "vite-plugin-vuetify": "^1.0.0-alpha.12", // 追記された
    "vitest": "^0.22.1",
    "vue-cli-plugin-vuetify": "~2.5.5", // 追記された
    "vue-tsc": "^0.29.8"
  }
}
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin
import vuetify from 'vite-plugin-vuetify' // 追記された

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
		vue(),
		vuetify({ autoImport: true }), // 追記された
	],
})
src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router' // named exportにしてたらdefault export前提({}なし)に変えられたので後から調整した
import vuetify from './plugins/vuetify'  // 追記された
import { loadFonts } from './plugins/webfontloader'  // 追記された

loadFonts()  // 追記された

createApp(App) // 自作pluginのuseが消されてしまったので後から追記した
  .use(router)
  .use(vuetify)
  .mount('#app')  
src/App.vue
// まるっと以下に置き換わってたので後から修正した
<template>
  <v-app>
    <v-main>
      <router-view/>
    </v-main>
  </v-app>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  name: 'App',

  data () {
    return {
      //
    }
  },
})
</script>

また、実行すると以下のWARNが出力されました。

DevTools がソースマップの読み込みに失敗しました(http://localhost:5173/materialdesignicons.css.map のコンテンツを読み込めませんでした(HTTP エラー: ステータス コード 404、net::ERR_HTTP_RESPONSE_CODE_FAILURE))

これは以下を追記したら解消しました。

vite.config.ts
export default defineConfig({
  plugins: [
	vue(),
	vuetify({ autoImport: true }),
  ],
  // 以下追加
  css: {
    devSourcemap: true,
  },
})

Upgrade Guide

ドキュメントに少しだけガイドの記載があったので確認しましたが、やけに少ないので、今後追記されていくのでは。

Components

# General changes

  • light and dark props have been removed from all components. Use theme prop instead
  • value prop has been replaced by model-value on components that support v-model usage
  • @input event has been replaced by @update:model-value on components that support v-model usage

# v-alert

  • border prop values left and right have been replaced by start and end
  • colored-border prop has been replaced by border-color
  • dismissable prop has been replaced by closeable
  • outlined and text props have been replaced by single prop variant
  • text prop has new purpose. It represents the text content of the alert, if default slot is not used

# v-app

  • id prop has been removed

https://next.vuetifyjs.com/en/getting-started/upgrade-guide/#general-changes

  • lightdarkを使ってた部分は、個別の色の設定はやめてthemeベースで設定するように変えました。
  • v-alertに限らず、dismissableclosableの変更やvariantでのタイプ指定はよく出てきました。

[Vue warn]: Failed to resolve component

Vuetify 3 では削除されたり置き換わったcomponentを使用しているとWARNが出たので、1つ1つ修正していきました。例えば以下。

Formのバリデーション

Vue 2 の頃はこんな感じで書いていました。

<template>
...
  <v-form ref="form">
    ...
  </v-form>
...
</template>

<script lang="ts">
import { Vue, Component, Emit } from 'vue-property-decorator';

type VForm = Vue & {
  validate: () => boolean;
  reset: () => void;
  resetValidation: () => void;
};

@Component({})
export default class ItemForm extends Vue {

  ...

  public $refs!: {
    form: VForm;
  };

  private submitItem(): void {
    if (this.$refs.form.validate()) {
      this.submit(this.item));
    }
  }

  @Emit('submit')
  private submit(item): void {
    this.$refs.form.resetValidation();
  }
}
</script>

setupだとthisが使えないので、validateなどをどう呼ぶのかな?と思いましたが、setup内でrefで定義した変数をv-formのrefプロパティにセットすればよいようです。

<script setup lang="ts">
import { ref } from 'vue';

import { useItem } from '../composables/useItem';

const { submit } = useItem();

const item = ref('');

const form = ref();

const onSubmit = async () => {
  const result = await form.value.validate();
  if(result.valid) {
    submit(item.value);
    form.value.reset();
  }
};
</script>

<template>
...
  <v-form ref="form">
    ...
  </v-form>
...
</template>

バンドルサイズが大きい

Vuetify対応後にビルドすると以下のWARNが出ました。

$ npm run build

> firebase-test@0.0.0 build
> vue-tsc --noEmit && vite build

vite v3.1.0 building for production...
✓ 368 modules transformed.
dist/assets/materialdesignicons-webfont.9bdfaf27.eot     1002.34 KiB
dist/assets/materialdesignicons-webfont.da7fba3c.woff2   317.62 KiB
dist/assets/materialdesignicons-webfont.8bded8f4.woff    454.29 KiB
dist/assets/materialdesignicons-webfont.c14484cf.ttf     1002.13 KiB
dist/index.html                                          0.42 KiB
dist/assets/webfontloader.b777d690.js                    12.42 KiB / gzip: 4.98 KiB
dist/assets/index.63c32017.css                           573.56 KiB / gzip: 82.09 KiB
dist/assets/index.1005b1e3.js                            628.15 KiB / gzip: 173.54 KiB

(!) Some chunks are larger than 500 KiB after minification. Consider:
- Using dynamic import() to code-split the application
- Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/guide/en/#outputmanualchunks
- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.

ちなみにVuetifyを入れる前は以下です。

$ npm run build

> firebase-test@0.0.0 build
> vue-tsc --noEmit && vite build

vite v3.1.0 building for production...
✓ 97 modules transformed.
dist/index.html                 0.36 KiB
dist/assets/index.e91a8232.js   466.58 KiB / gzip: 121.12 KiB

気にしてませんでしたが、もともと結構大きかったようです。
以下を参考に確認したところ、Firebaseまわりが大きすぎですね。。。
https://miyauchi.dev/ja/posts/firebase-bundle-size/
https://zenn.dev/meijin/articles/vite-bundle-analyzer

Firestore Liteというのもあるようですが、リアルタイムアップデートが使えないのが厳しいです。
https://firebase.google.com/docs/firestore/solutions/firestore-lite

とは言え、materialdesignicons-webfontもかなり大きいので、以下を参考に、アイコンは必要なものだけ個別にimportするようにしてみました。
https://next.vuetifyjs.com/en/features/icon-fonts/#material-design-icons-js-svg

$ npm i -D @mdi/js
src/plugins/vuetify.ts
// まずこれを削除。冒頭のソースマップの設定も不要になる
// import '@mdi/font/css/materialdesignicons.css'

// Styles
import 'vuetify/styles'
import { aliases, mdi } from 'vuetify/iconsets/mdi-svg' // 追加

// Vuetify
import { createVuetify } from 'vuetify'

export const vuetify = createVuetify({
  // 以下を追加
  icons: {
    defaultSet: 'mdi',
    aliases,
    sets: {
      mdi,
    },
  },
});

各コンポーネントで使用するアイコンをimportします。

src/components/ItemLine.vue
<script setup lang="ts">
import { mdiDelete } from '@mdi/js'; // これを追加

import { Item } from '../domain/models/Item';

import { useItem } from '../composables/useItem';

const props = defineProps<{
  item: Item
}>();

const { deleteItem } = useComic();
</script>

<template>
  <v-list-item>
    <v-list-item-title>
      {{ item.name }}
    </v-list-item-title>
    
    <template v-slot:append>
      <v-btn
        icon
        variant="plain"
        @click.stop="deleteItem(comic)"
      >
        <!-- <v-icon>mdi-delete</v-icon> -->
        <v-icon>{{ mdiDelete }}</v-icon>
      </v-btn>
    </template>
  </v-list-item>
</template>

修正後のビルド結果です。

$ npm run build

> firebase-test@0.0.0 build
> vue-tsc --noEmit && vite build

vite v3.1.0 building for production...
✓ 369 modules transformed.
dist/index.html                         0.42 KiB
dist/assets/webfontloader.b777d690.js   12.42 KiB / gzip: 4.98 KiB
dist/assets/index.b127324a.css          311.74 KiB / gzip: 38.67 KiB
dist/assets/index.aa7ed990.js           633.31 KiB / gzip: 175.68 KiB

(!) Some chunks are larger than 500 KiB after minification. Consider:
- Using dynamic import() to code-split the application
- Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/guide/en/#outputmanualchunks
- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.

materialdesignicons-webfontはなくなりましたが、メインのバンドルはアイコンを組みこんだせいか更に大きくなりましたね。

あとはviewの単位でdynamic importにしたりすれば、viewごとにファイルが分割されて、1ファイルあたりのサイズは小さくなりますが、シンプルなアプリだとあまり分けられる要素もなく、なかなか500KBはきれませんでした。。。
やはりFirebaseが大きい。

単に上記のWARNを出さなくするだけであれば、メッセージ記載のとおり、build.chunkSizeWarningLimitを上げればよいのですが、根本的な解決ではないので微妙なところです。ビルドエラーになるわけではないので、いったんそのままにしました。

おわりに

シンプルなアプリで試したので、あまり使いこめてはいませんが、それほど大きな変更の印象はなかったです。
ただ、まだドキュメントが出揃っておらず、APIリファレンスへのリンクもほぼ404だったりするので、細かいプロパティ設定の仕方などは調べづらかったです。それでも2.0と同じように設定すれば大体動いたりしました。
正式リリース時に大きな変更が発生したりしなければ大丈夫そうな気がします。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1