TypeScript、Vue3、Nuxt3 、Vuetify3初心者開発ガイド
はじめに
個人開発で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
を使います。
ページ遷移したい場合はuseRouter
を使います。
他にもたくさんあるので見てみてください。
UI作成
Vuetifyはマテリアルデザインのコンポーネントを提供してくれます。
例えばナビゲーションドロワーを作りたい場合は下記の公式ページを参照すれば、簡単にドロワーを作成できます。(サンプルコードが付いてます。)
導入手順
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