21
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

NuxtAdvent Calendar 2022

Day 2

Nuxt3 で Vuetify3 を使う

Last updated at Posted at 2022-05-04

外部モジュールを使うと簡単にできます。

上記方法は SASS/SCSS も動くことを確認しました。

この方法は SASS/SCSS の設定がうまくできませんでした(2023/12 現在, Nuxt 3.8.2 / Vuetify 3.4.6)。うまくいく方法があったら教えてください。

そんなわけで、下記の記事はあまり意味がなくなった気はしますが、参考のために残しておきます。

以下の記事は、外部のモジュールに頼らずに Nuxt3 に Vuetify3 を導入する方法について記述しています。SASS/SCSS についても記述しています。

主旨

理解は後でいいから、とりあえずコピペで動けばOKという場合は、ページ末尾の「全部盛り」を見てください。

npm でなく yarn を使ってます。

windows (not WSL) で実行する場合は、yarn や nuxi などのコマンドは、npx 付きで実行します。

たとえば、

> npx nuxi init app
> cd app
> npx yarn install

こんなかんじです。

準備

linx/windows WSL2/mac os でやります。

$ npm -v
9.6.7
$ node -v
v16.16.0
$ nuxi -v
Nuxi 3.5.3      
$ yarn -v
1.22.19

nuxi がない場合はインストールします。

$ sudo npm i -g nuxt@latest

手順

アプリの作成とモジュールのインストール

$ nuxi init nuxt3-vuetify3-stable
$ cd nuxt3-vuetify3-stable/
$ yarn add vuetify@next
$ yarn add sass
$ yarn install

vuetify は @next とするか、@3.8.0 などとバージョンを指定します。記事を書いている時点では、バージョンを指定しないと vuetify@2.x が入ってしまいます。

vuetify のインストール中にバージョンを選択のリストが出たときは、最新版(2023/11時点では3.4.0)を選びます。

plugins/vuetify.js の追加

vuetify.js
import { createVuetify } from 'vuetify';
import * as components from 'vuetify/components'

export default defineNuxtPlugin( nuxtApp => {
    const vuetify = createVuetify({
        components
    });

    nuxtApp.vueApp.use( vuetify );
});

app.vue の編集

下記ページにある Basic のところにあるコードをそのまま app.vue にコピペします。

app.vue
<template>
<template>
  <v-app>
    <v-container>
      <v-card
        width="400"
        title="This is a title"
        subtitle="This is a subtitle"
        text="This is content"
      ></v-card>

      <div class="mt-4 text-subtitle-2">With slots</div>

      <v-card width="400">
        <template v-slot:title>
          This is a title
        </template>

        <template v-slot:subtitle>
          This is a subtitle
        </template>

        <template v-slot:text>
          This is content
        </template>
      </v-card>

      <div class="mt-4 text-subtitle-2">With markup</div>

      <v-card width="400">
        <v-card-item>
          <v-card-title>This is a title</v-card-title>

          <v-card-subtitle>This is a subtitle</v-card-subtitle>
        </v-card-item>

        <v-card-text>
          This is content
        </v-card-text>
      </v-card>
    </v-container>
  </v-app>
</template>

nuxt.config.ts の編集

nuxt.consif.ts
// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
    css: [
        "vuetify/lib/styles/main.sass"
    ],
    build: {
        transpile: ["vuetify"]
    },
    vite: {
        define: {
            "process.env.DEBUG": false
        },
        // for HMR
        server: {
            watch: {
                usePolling: true
            }
        },
    }
});

テスト

$ npm run dev

または

$ yarn dev

これで http://localhost:3000/ にブラウザでアクセスして、下記のようなページが表示されたら成功です。

image.png

ルーティング機能のテスト

現状の app.vue を pages/index.vue に移動します。

$ mkdir pages
$ mv app.vue pages/index.vue

新たに app.vue を作ります。

app.vue
<template>
  <div>
    <NuxtPage />
  </div>
</template>

pages/about.vue を下記の内容で作ります。

pages/about.vue
<template>
    <v-container>
        <h2>{{ title }}</h2>
        <v-btn @click="pushButton">
            PUSH!
        </v-btn>
    </v-container>
</template>
<script>
export default {
    data: () => ({
        title: "This is the test page."
    }),
    methods: {
        pushButton(){
            this.title = "PUSHED!";
        }
    }
}
</script>

これで yarn dev しなおします。(HMR だけではエラーになる)

http;//localhost:3000 で表示される内容は、pages/index.vue の中身になるはずです。

http;//localhost:3000/about にアクセスすると、下記のページが表示されるはずです。

image.png

PUSH を押すと、下記のように変わるはずです。

image.png

こんなかんじになれば、正常に動いてます(多分)。

おまけ

mdi-font を使う場合

$ yarn add @mdi/font

としてから、nuxt.config.ts を編集します。

nuxt.config.ts
    css: [
        "vuetify/lib/styles/main.sass",
        "@mdi/font/css/materialdesignicons.css"
    ],

primary/secondary の色を 2.x と同じにする

vuetify3 のデフォルトのテーマ light の primary / secondary の色は下図のようにになります。

image.png

2.x のテーマと同じ色にしたければ、plugins/vuetify.js を下記のようにします。

vuetify.js
import { createVuetify } from 'vuetify';
import * as components from 'vuetify/components'

export default defineNuxtPlugin( nuxtApp => {
    const vuetify = createVuetify({
        components,
        theme: {
            themes: {
                light: {
                    colors: {
                        primary: '#1976D2',
                        secondary: '#424242',
                        accent: '#82B1FF',
                        error: '#FF5252',
                        info: '#2196F3',
                        success: '#4CAF50',
                        warning: '#FFC107',
                    },
                },
            },
        }
    });

    nuxtApp.vueApp.use( vuetify );
});

これで、下記のように色が 2.x のデフォルトと同じになります。

image.png

Roboto フォントにする

デフォルトでは Roboto フォントが読み込まれないので、2.x とは違うフォントになります。下記は Roboto フォントを使えるようにする方法のひとつです。

webfontloader を使う

$ yarn add webfontloader

plugins/webfontloader.client.js を作成します。

plugins/webfontloader.client.js
import webFontLoader from 'webfontloader';

export default defineNuxtPlugin( nuxtApp => {
  webFontLoader.load({
    google: {
      families: ['Roboto:100,300,400,500,700,900&display=swap'],
    },
  })
});

これで Roboto フォントになります。

image.png

@nuxt/google-fonts でもできそうなのですが、nuxt3 でうまく読み込ませられませんでした。わかる方がいましたら教えてください。

directive

ディレクティブを使う場合は、vuetify.js に追記が必要です。

vuetify.js
import { createVuetify } from 'vuetify';
import * as components from 'vuetify/components';
import * as directives from 'vuetify/directives';

export default defineNuxtPlugin( nuxtApp => {
    const vuetify = createVuetify({
        components,
        directives,
    });
    nuxtApp.vueApp.use( vuetify );
});

SASS/SCSS を使う

現状 (Nuxt 3.8.2 + Vuetify 3.4.6 の組み合わせで)使うには vite-vuetify-plugin を追加する必要があります。

$ yarn add vite-plugin-vuetify

nuxt.config.ts に追記します。

nuxt.config.ts
import vuetify from "vite-plugin-vuetify";
export default defineNuxtConfig({
  ...
  css: [
    "vuetify/styles"
  ],
  hooks: {
    'vite:extendConfig': (config) => {
      config.plugins!.push(
        vuetify({
          autoImport: true,
          styles: {
            configFile: 'styles/settings.scss',
          },
        })
      );
    },
  },
}
styles/settings.scss
@use 'vuetify/settings' with (
  $button-height: 100px,
);

これで使えるようになります。ただし yarn dev すると大量のワーニングがコンソールに出力されます。このワーニングは、下記のようにすると一応消すことはできます。

nuxt.config.ts
export default defineNuxtConfig({
  ...
  sourcemap: {
    client: false,
    server: false,
  },
  ssr: false,

これだと ssr が無効化されてしまうのですが、ssr を有効にすると、どうしてもワーニングが出ることは避けられないようです。ssr を有効化してもワーニングが出るだけで動作自体には問題はないのですが、気持ち悪くはあります。

なお ssr: true としても yarn buildyarn generate ではワーニングはでないので、気にしなければOKなのかもしれません。

一方で、下記のように vue ファイル内にダイレクトに @use などを書く方法は、現状うまくいかないようです。

test.vue
<template>
  <v-container class="h-100">
    <v-btn>
      Test
    </v-btn>
  </v-container>
</template>

<style lang="scss">
@use 'vuetify/settings' with (
  $button-height: 100px,
);
</style>

一応、下記を nuxt.config.ts に追記し、なおかつ styles/setting.scss を使わない場合は動くように見えます。しかし styles/setting.scss との共存はどうしてもうまくいかないようです。

nuxt.config.ts
  experimental: {
    inlineSSRStyles: false
  }

こんな感じで SASS/SCSS 周りの動作は怪しいところが多いです。

なお vuetify-nuxt-module を使うとこのあたりの問題は(ワーニング出る部分以外は)解決しているようです。SASS/SCSS を使うならその選択肢一択かもしれません。

全部盛り

とりあえず Vuetify2 と同じ見た目になれば OK という場合は、下記をコピペすれば幸せになれます(多分)。sass 周りはワーニングが出てしまうので追加してません。必要なら、前述の sass/scss の項目を見て追記してください。

$ nuxi init nuxt3-vuetify3-stable
$ cd nuxt3-vuetify3-stable/
$ yarn add vuetify@next sass @mdi/font webfontloader
nuxt.configs.ts
export default defineNuxtConfig({
    css: [
        "vuetify/lib/styles/main.sass",
        "@mdi/font/css/materialdesignicons.css"
    ],
    build: {
        transpile: ["vuetify"]
    },
    
    vite: {
        define: {
            "process.env.DEBUG": false
        },
        // for HMR
        server: {
            watch: {
                usePolling: true
            }
        },
    },
})
plugins/vietify.js
import { createVuetify } from 'vuetify';
import * as components from 'vuetify/components';
import * as directives from 'vuetify/directives';

export default defineNuxtPlugin( nuxtApp => {
    const vuetify = createVuetify({
        components,
        directives,
        theme: {
            themes: {
                light: {
                    colors: {
                        primary: '#1976D2',
                        secondary: '#424242',
                        accent: '#82B1FF',
                        error: '#FF5252',
                        info: '#2196F3',
                        success: '#4CAF50',
                        warning: '#FFC107',
                    },
                },
            },
        }
    });

    nuxtApp.vueApp.use( vuetify );
});
plugins/webfontloader.client.js
import webFontLoader from 'webfontloader';

export default defineNuxtPlugin( nuxtApp => {
  webFontLoader.load({
    google: {
      families: ['Roboto:100,300,400,500,700,900&display=swap'],
    },
  })
});

関連記事

つぶやき

nuxt で開発するなら、作業用のディスクは SSD (できれば PCIe) を使うことを強くお勧めします(HDDだと非常に遅いです。

21
13
1

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
21
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?