概要
Nuxt 3 が 2022年4月にRC(Release Candidate)になったことで、今後、Nuxt 3での開発が中心になることも予想される。
また、それにあわせて、Vuetify3(執筆時点ではbeta版)、TypeScriptを組み合わせて、開発の環境設定+躓きそうなポイントをメモをしておく。
ドキュメント
環境
-
macOS Monterey 12.3.1 / Apple M1
-
Visual Studio Code / Volar-plugin
-
Node.JS
$ node -v
v16.13.1
- npm
$ npm --v
8.1.2
- Vueコマンド
$ vue --version
@vue/cli 5.0.4
手順
プロジェクト作成
まずはプロジェクトを作成してみましょう。nuxt3-test-app
はプロジェクト名称ですので、お好きなものをつけてください。
$ npx nuxi init nuxt3-test-app
コマンドを実行してみましょう。nuxi
がインストールされていない場合には、インストールするか聞かれますので、指示に従ってインストールしてください。実行結果が次のように出るはずです。/path/to/your/working/directory/
はあなたが実行したディレクトリ配下のものが表示されます。
Nuxt CLI v3.0.0-rc.3
ℹ cloned nuxt/starter#v3 to /path/to/your/working/directory/nuxt3-test-app
✨ Your stellar Nuxt project is just created! Next steps:
📁 cd nuxt3-test-app
💿 Install dependencies with npm install or yarn install or pnpm install --shamefully-hoist
🚀 Start development server with npm run dev or yarn dev or pnpm run dev ```
絵文字などと一緒に出ているのはとてもかわいいですよね。
さて、nuxt 3
で作成されたデフォルトのセットをみてみますしょう。
$ cd nuxt3-test-app
$ code .
Visual Studio Code が入っているのにもかかわらず、macOS で code .
でVisual Studio Code が立ち上がらない場合には、環境変数が通っていないことが考えられます。
参考:M1 MacでVS Codeをターミナルから起動できるようにするまで
Visual Stuido Code を起動すると エクスプローラーに以下のように表示されているはずです。
どうです?最低限ですよね。
Nuxtの起動
ターミナルに戻ってnpm install
をやってみましょう。
$ npm install # working directoryで実行すること
npm WARN deprecated node-pre-gyp@0.13.0: Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future
added 647 packages, and audited 648 packages in 26s
77 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
続いてテスト実行してみましょう。
$ npm run dev
> Local: http://localhost:3000/
> Network: http://192.168.x.x:3000/
ℹ Vite server warmed up in 165ms
ℹ Vite client warmed up in 579ms
✔ Vite server built in 396ms
✔ Nitro built in 185 ms
これが出たら成功です。ちなみに、Nitro
は、Nuxt 3から搭載された実行エンジンです。詳しくは説明しませんが、公式サイトに以下のようなメリットがあると書かれています。
- Cross-platform support for Node.js, Browsers, service-workers and more.
- Serverless support out-of-the-box.
- API routes support.
- Automatic code-splitting and async-loaded chunks.
- Hybrid mode for static + serverless sites.
- Development server with hot module reloading.
さて、ブラウザで確認してみましょう。
http://localhost:3000/
こちらの画像が出れば、実行ができたということが確認できます。
ターミナルでcommand+cで実行を停止してみましょう。
Vuetify3のインストール
Vuetify3は執筆段階では、beta版です。なので、製品などへの組み込みは注意が必要です。
$ yarn add vuetify@next sass
パッケージのインストール後、Visual Studio Codeに戻り、以下のpluginを作成してください。Nuxt 3は現段階ではVuetifyのプラグインがないため、自作する必要があるそうです。
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
import { createVuetify } from 'vuetify'
export default defineNuxtPlugin((nuxtApp) => {
const vuetify = createVuetify({
components,
directives,
})
nuxtApp.vueApp.use(vuetify)
})
import { defineNuxtConfig } from 'nuxt'
// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
css: ['vuetify/lib/styles/main.sass'],
build: {
transpile: ['vuetify'],
},
})
ページを作ってみる
app.vueをいじってみましょう。以前のNuxt2ではApp.vueでしたが、小文字になったようです。
app.vueはレイアウトファイルの元のような振る舞いをしているようです。
みていきましょう。
デフォルトだとシンプルなものになっています。真ん中のdivタグの中にある<NuxtWelcome />
を<NuxtPage />
に変更してみてください。こうすることで、app.vueを使いつつ、具体的な中身はpagesディレクトリの配下を参照することができます。
<template>
<div>
<NuxtPage />
</div>
</template>
pagesディレクトリ配下に2つファイルを作ってみましょう。
<template>
<h1>About us page</h1>
</template>
<template>
<h1>Welcome to Our Nuxt 3 first page</h1>
</template>
これらを配置した上で、ターミナルからnpm run dev
で実行をしてみると、
http://localhost:3000/welcome
http://localhost:3000/aboutus
にアクセスできるようになります。
少し複雑なページにしてみる
コンポーネントを作ってみます。
v-app-bar
をラップしたHeader
のコンポーネントを作ってみました。pages
の以下のページは変更なしでよく、http://localhost:3000/aboutus
にアクセスできることを確認してみましょう。
<template>
<v-app-bar color="primary" id="app-bar">
<template v-slot:prepend>
<v-app-bar-nav-icon></v-app-bar-nav-icon>
</template>
<v-app-bar-title>Photos</v-app-bar-title>
<v-menu open-on-hover>
<template v-slot:activator="{ props }">
<v-btn v-bind="props" icon="mdi-dots-vertical">
</v-btn>
</template>
<v-list dark dense>
<v-list-item v-for="menu in items" :key="menu.no" link>
<v-list-item-title>{{ menu.title }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-app-bar>
</template>
<script>
export default {
data: () => ({
items: [
{ no: 1, title: 'About us' },
{ no: 2, title: 'プライバシーポリシー' },
{ no: 3, title: '利用規約' },
{ no: 4, title: 'ログアウト' },
],
closeOnContentClick: true,
}),
}
</script>
<template>
<v-app>
<div>
<header>
<Header />
</header>
<v-main>
<slot />
</v-main>
</div>
</v-app>
</template>
<script setup>
import Header from "@/componets/header/Header.vue";
</script>
<template>
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css" rel="stylesheet">
<NuxtLayout name="custom">
<NuxtPage />
</NuxtLayout>
</template>
<template>
<h1>About us page</h1>
This is aboutus page 1<br />
This is aboutus page 2<br />
This is aboutus page 3<br />
This is aboutus page 4<br />
This is aboutus page 5<br />
This is aboutus page 6<br />
</template>
ちゃんとできるかと思ったのですが、私の環境・Vuetifyのバージョン(beta 2)では、次のようになってしまいました。
ロード後にappbarが画面幅よりも小さいのが出て、しばらくしてから画面幅最大にappbarが引き延ばされるという仕様でした。
違う方法でappbarっぽいのを実装してみる
v-toolbar
/ v-btn
を利用して、v-app-bar
っぽいものを実装してみました。Vuetify 3.0
が正式版になればなおるであろうことではありますが、今少し困っているので無理矢理対応してみました。
しかし、こちらのソースコードでは、ナビバーの右側のボタンが反応しませんでした。
(左側のハンバーガーメニューはそもそも実装していませんので、反応しません。)
<template>
<v-toolbar color="primary">
<v-btn color="white" icon="mdi-menu">
</v-btn>
<v-toolbar-title>xxxシステム</v-toolbar-title>
<v-spacer></v-spacer>
<v-menu open-on-hover>
<template v-slot:activator="{ on }">
<v-btn v-on="on">
<v-icon icon="mdi-dots-vertical"></v-icon>
</v-btn>
</template>
<v-list dark dense>
<v-list-item v-for="item in items" :key="item.no" link>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-toolbar>
</template>
<script>
export default {
data: () => ({
items: [
{ no: 1, title: 'About us' },
{ no: 2, title: 'プライバシーポリシー' },
{ no: 3, title: '利用規約' },
{ no: 4, title: 'ログアウト' },
],
closeOnContentClick: true,
}),
}
</script>
<template>
<v-app>
<OriginalHeader />
<v-main>
<slot />
</v-main>
</v-app>
</template>
<script setup>
import OriginalHeader from "@/components/header/OriginalHeader.vue";
</script>
成功例appbar
v-menuのところの書き方をv-btnを親タグとして書き、それを参照する形でv-menuを内包する書き方だと、hoverがうまく動きました。ただ、メニューが少し切れてしまっております。left offset-xなどを試してみましたが、うまく反応しておりません。
<template>
<v-toolbar color="primary">
<v-btn color="white" icon="mdi-menu">
</v-btn>
<v-toolbar-title>xxxシステム</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn color="white" dark>
<v-icon icon="mdi-dots-vertical"></v-icon>
<v-menu activator="parent" :open-on-hover="true" left offset-x nudge-left="100">
<v-list>
<v-list-item v-for="item in items" :key="item.no" link>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-btn>
</v-toolbar>
</template>
<script>
export default {
data: () => ({
sticky: false,
items: [
{ no: 1, title: 'About us' },
{ no: 2, title: 'プライバシーポリシー' },
{ no: 3, title: '利用規約' },
{ no: 4, title: 'ログアウト' },
],
closeOnContentClick: true,
}),
}
</script>
おわりに
Vuetify 3.0 beta2で試してみましたが、まだまだ情報が少ないのが現状です。そのうち修正される内容だらけだと思いますが、何かの参考になれば幸いです。(間違い、認識間違いがあったら申し訳ございません。)