🌱

TypeScript、Vue3、Nuxt3 、Vuetify3初心者開発ガイド

2023/05/15に公開

はじめに

個人開発でVue3を初めて触るメンバー向けに、開発ガイドを記します。
私自身、バックエンドメインのエンジニアかつ、かなり噛み砕いて書きますので、多少の誤謬はお許しください。コメントにてご指摘いただけますと幸いです。

前提知識

TypeScript

TypeScriptは、静的型付けの拡張機能を提供するJavaScriptのスーパーセットです。
以下にTypeScriptの基本的な特徴をいくつか記します。

静的型付け

TypeScriptの最大の特徴は、静的型付けをサポートしていることです。これは、変数、関数引数、オブジェクト、クラスなど、プログラムのさまざまな部分に対して期待される型(string,number等)を明示的に宣言できることを意味します。これにより、コードがコンパイルされるときに型の問題が検出され、ランタイムエラーを予防することができます。

クラス

TypeScriptは、クラスベースのオブジェクト指向プログラミングをサポートしています。一方JavaScriptのプロトタイプベースの言語です。

プロトタイプベースのオブジェクト指向プログラミングでは、オブジェクトは他のオブジェクトから直接作成され、その作成元のオブジェクトを「プロトタイプ」と呼びます。オブジェクトが別のオブジェクトから派生するとき、プロトタイプのプロパティとメソッドが新しいオブジェクトに継承されます。JavaScriptでは、オブジェクトはObject.create()関数を使用して他のオブジェクトから直接作成できます。

var animal = {
    type: "Invertebrates", 
    displayType: function() {  
        console.log(this.type);
    }
}

var fish = Object.create(animal);
fish.displayType();

クラスベースのオブジェクト指向プログラミングでは、オブジェクトはクラスからインスタンス化されます。クラスはオブジェクトの「設計図」であり、オブジェクトが持つべきプロパティとメソッドを定義します。新しいオブジェクトは、そのクラスの「新しいインスタンス」として作成され、クラスで定義されたすべてのプロパティとメソッドを継承します。

class Animal {
    type: string;

    constructor(type: string) {
        this.type = type;
    }

    displayType() {
        console.log(this.type);
    }
}

let fish = new Animal("Invertebrates");
fish.displayType(); // Output: Invertebrates

インターフェース

インターフェース(Interface)は、TypeScriptが提供する強力な機能の一つで、特定の形状(プロパティとメソッドの集合)を持つオブジェクトを定義するための契約または規格を作成します。

インターフェイスは具体的な実装を持たず、クラスやオブジェクトが満たすべき契約を定義します。オブジェクトが特定のインターフェイスを実装していると宣言すると、そのオブジェクトはインターフェイスで定義されたプロパティとメソッドを持つことが要求されます。(実装されていない場合エラーとなります。)

interface Person {
    firstName: string;
    lastName: string;
    age: number;
    greet(): void;
}

let john: Person = {
    firstName: "Jack",
    lastName: "Smith",
    age: 30,
    greet() {
        console.log(`Hello, my name is ${this.firstName} ${this.lastName}.`);
    }
};

john.greet(); // 出力: Hello, my name is Jack Smith.

SOLIDの原則の一つに「インターフェース分離の原則」があります。興味があれば勉強してみてください。
ちなみに、interfaceを用いることで、ユニットテスト(単体テスト)コードを書くことが容易になります。下位モジュールを記載する際にモックを作成しやすくなるからですが、長くなるので詳しいことはここには記載しません。

トランスパイル

TypeScriptはJavaScriptにトランスパイル(一種のコンパイル)されます。これにより、TypeScriptは任意のJavaScript環境で実行でき、既存のJavaScriptライブラリやフレームワークと互換性を持ちます。

基礎文法

参考になりそうな記事を記しておきます。
最初は見ながら実装する形で大丈夫です。
TypeScript基礎まとめ

Vue3

Vue.js(通常はVueと呼ばれます)は、JavaScriptを使用したフロントエンドフレームワークで、ユーザインターフェースの構築に使用されます。
セマンティックバージョニングではメジャーバージョン(1.0.0の一番左)は後方互換性がないことを意味するので、敢えてVue3と記載しています。
世間的にはVue2の記事が多いので安易に参照しないでください。
公式ドキュメント:https://ja.vuejs.org/

Nuxt3

Nuxt.jsは、Vue.jsのフレームワークであり、ウェブアプリケーションの開発を容易にし、高度に最適化されたアプリケーションを構築することができます。Nuxt.jsはサーバーサイドレンダリング(SSR)や静的サイト生成(SSG)、SPA (Single Page Application) などの様々なレンダリングモードをサポートしています。
Nuxt.jsのバージョン3(Nuxt 3)は、Nuxt.jsの最新バージョンで、多くの新機能と改善が導入されています。(ビルドツールViteのサポートなどなど)
こちらもNuxt2の記事が多いので安易に参照しないでください。
公式ドキュメント:https://nuxt.com/

Vuetify3

Vuetifyは、Vue.jsのための人気のあるマテリアルデザインコンポーネントフレームワークです。それは開発者が綺麗で機能的なユーザーインターフェースを効率的に構築するのを助けます。Vuetifyは80以上の再利用可能なコンポーネントとあらゆる種類のレイアウトを提供します。
こちらもVuetify2の記事が多いので安易に参照しないでください。
公式ドキュメント:https://vuetifyjs.com/

開発の開始

macでhomebrewがインストールされている前提です。

Node.jsのインストール

brew install node

Node,jsとnpm(Node.jsのバージョン管理ツール)のバージョンを確認します。

node -v
npm -v

プロジェクトの作成

npx nuxi create {プロジェクト名}

依存関係のインストール

cd {プロジェクト名}
npm install

ちなみにpackage.jsonというファイルが作成されていると思いますが、ここにはプロジェクトに必要なモジュールなどが記載されます。
package-lock.jsonには依存関係ツリー(package.jsonに記載されたモジュールは別のモジュールを使用しています。この依存関係が)記載されています。これはnpm installによって作成されます。
node_modulesディレクトリには、プロジェクトの依存関係がインストールされます。具体的には、package.jsonで指定された依存関係をnpm installコマンドでインストールすると、それらのパッケージのコードがnode_modulesディレクトリにダウンロードされます。また、依存関係が他のパッケージに依存している場合、それらのパッケージもこのディレクトリにインストールされます。通常このディレクトリは.gitignoreでgitの管理対象外にします。

アプリケーションの実行

npm run dev

http://localhost:3000 にてアプリケーションが起動します。

ディレクトリ構成

プロジェクトによってディレクトリ構成は異なりますが、以下に一例を示します。

/my-nuxt-app
├── .nuxt/             # Nuxt自動生成ファイル、gitignoreするのが通常
├── assets/            # 非コンパイルアセット(SCSS、画像など)
│   └── main.scss      # グローバルスタイル
├── components/        # 再利用可能なVueコンポーネント (.vue or .ts)
│   └── MyComponent.vue
├── layouts/           # レイアウトコンポーネント(ページの共通部分)
│   └── default.vue
├── middleware/        # ミドルウェアコンポーネント
│   └── auth.ts
├── pages/             # Vueコンポーネント(View)
│   └── index.vue
├── plugins/           # Vueのプラグイン
│   └── vuetify.ts     # Vuetifyプラグイン
├── public/            # 静的ファイル
│   └── favicon.ico
├── store/             # Pinia(状態管理ライブラリ)等ストアファイル (.ts or .js)
│   └── index.ts
│   types/
│   └── index.ts       # 型定義ファイル
├── app.vue            # 大元のVueファイル
├── tsconfig.json      # TypeScriptの設定ファイル
├── package.json       # プロジェクトの依存関係とスクリプトを記述
├── package-lock.json  # 正確な依存関係ツリーを記述(npm用)
└── nuxt.config.ts     # Nuxt.jsの設定ファイル

app.vueはなくてもページ作成できます。

ルーティングの定義

なんとルーテイングはファイルに記述する必要はありません。
pagesディレクトリの構造がそのままパスになります。
例えば以下のディレクトリ構成の場合は/auth/loginになります。

├── pages/             # Vueコンポーネント(View)
│   └── auth/
│        └── login.vue

Nuxt3のAPI

Nuxt3は便利な機能がデフォルトで提供されています。
例えば、Cookieを操作するには以下のuseCookieを使います。
https://nuxt.com/docs/api/composables/use-cookie

ページ遷移したい場合はuseRouterを使います。
https://nuxt.com/docs/api/composables/use-router

他にもたくさんあるので見てみてください。

UI作成

Vuetifyはマテリアルデザインのコンポーネントを提供してくれます。
例えばナビゲーションドロワーを作りたい場合は下記の公式ページを参照すれば、簡単にドロワーを作成できます。(サンプルコードが付いてます。)
https://vuetifyjs.com/en/components/navigation-drawers/

導入手順

npm install vuetify@next sass mdi

pluginsに追加します。
plugins/vuetify.ts

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);
});

設定ファイルにも記載します。

nuxt.config.ts

export default defineNuxtConfig({
  css: ["vuetify/lib/styles/main.sass", "mdi/css/materialdesignicons.min.css"],
  build: {
    transpile: ["vuetify"],
  },
  // 略
})

状態管理

Vue.jsでは、コンポーネント間でデータを共有するための基本的な仕組みとして、PropsとEmitを使った親子間のデータの受け渡しがあります。しかし、これは親と直接的な子コンポーネント間のやり取りに限られ、兄弟間や全く関係のないコンポーネント間でのデータの共有には適していません。例えば、ユーザーがログインしているかという状態は全コンポーネントで共有しなくてはなりませんが、これにPropsを用いるのは適していません。

こうした複雑な状況に対処するための一つの解決策が、状態管理ライブラリの導入です。Vue.jsのアプリケーションでは、Vuexが一般的でしたが、現在サポートされていません。

そこで、選択肢としてはデフォルトのuseStateを使うか、Piniaなどのその他状態管理ライブラリが残ります。

Piniaを用いた状態管理の例として、ログイン機能の記事を書いたので読んでみてください。

終わりに

Nuxt3はまだまだ日本語の記事が少なく、公式ドキュメントを読んで自分でなりに手探りで実装を進めているので、至らない点もあると思いますが、参考になると幸いです。
記事を書いておいてなんですが、フロントエンドの進化は凄まじいので安易に記事を参照せず、公式ドキュメントを参照するようにしてください。
ChatGPTは2021年9月までの情報なのであまり参考になりません。

Discussion