📑
Vue3+REST API(JSON Server)でのモックアップ作成
はじめに
今回は、前回作成したToDoアプリを、JSON ServerでREST APIのモックサーバを立ち上げ、モックアップ画面を構築する手順について紹介します。単純にVue.jsだけでモックアップを作成してしまうと、モック用の不要なソースコードが増えてしまうため、お勧めしません。
JSON Server
まずは、JSON Serverを利用し、REST APIのモックサーバを立ち上げます。
- 環境設定として、JSON Serverをインストールして、node.jsを実装できるように、eslintの設定を追加します。
npm install -g json-server
.eslintrc.cjs
module.exports = {
root: true,
env: {
// requireが使えるように、node.jsを有効化
browser: true,
node: true,
},
...
- モックで使うJSONファイルを作成します。今回は、大量データもfor文を活用することで生成できるようにjavascriptで生成しています。
mock/makeDB.cjs
var db = {
task: [],
};
db.task.push({
id: 1,
title: "Get bananas",
done: false
});
db.task.push({
id: 2,
title: "Eat bananas",
done: false
});
// JSONファイルへ出力
require("fs").writeFileSync("db.json", JSON.stringify(db, null, 2));
node makeDB.cjs
mock/db.json
{
"task": [
{
"id": 1,
"title": "Get bananas",
"done": false
},
{
"id": 2,
"title": "Eat bananas",
"done": false
}
]
}
- 単純なCRUD処理であれば、以下のコマンドだけでREST APIのモックサーバが起動する。
json-server db.json
また、今回は利用しませんが、個別にPOSTのリスクエストをカスタマイズしたい場合は、server.cjsを作成し、node.js経由でのカスタム実行も可能である。
mock/server.cjs
const jsonServer = require("json-server");
const server = jsonServer.create();
const router = jsonServer.router("db.json");
server.post("/api/task/search", (req, res) => {
res.jsonp(router.db.get("task").value());
});
server.use("/api", router);
server.listen(3000, () => {
console.log("JSON Server is running");
});
package.json
{
...
"scripts": {
...
"json-server": "cd mock && node server.cjs"
},
Paste JSON as Code
作成したJSONからTypeScriptやJavaの型定義を変換するVS Codeのプラグインを紹介します。これにより、フロントエンドとバックエンドの型定義を作成する際のタイプミスをなくすことができます。
- VS Codeの推奨プラグインにPaste JSON as Codeを追加する。
.vscode/extensions.json
{
"recommendations": [
...
// Paste JSON as Code
"quicktype.quicktype"
]
}
- db.jsonを開き、コマンドパレット[F1]で、以下のコマンドを実行すると、Typescriptの型定義が自動生成される。JSONのデータ量が多いと、enum型も自動作成してくる。
> Set quicktype target language
→ Typescript
> Open quicktype for JSON
→ QuickType.tsが自動生成される。この内容の一部をコピーして、型定義ファイルを作成する。
REST API化
ToDoリストを、JSON ServerのREST APIを利用し、GET/POST/DELETEできるようにサービス化を行う。この状態で、ToDoを変更するとmock/db.jsonがリアルタイムに内容が更新される。
services/TodoService.ts
import { reactive } from "vue";
import axios from "axios";
export interface Task {
id?: number;
title: string;
done: boolean;
}
class TodoService {
private tasks: Task[] = reactive([]);
get getTasks(): Task[] {
return this.tasks;
}
public getAllTasks(): void {
axios.get<Task[]>("/api/task").then((res) => {
this.tasks.length = 0;
Array.prototype.push.apply(this.tasks, res.data);
});
}
public deleteTask(index: number) {
axios.delete<Task>("/api/task/" + this.tasks[index].id);
this.tasks.splice(index, 1);
}
public addTask(title: string) {
const newTask: Task = {
title: title,
done: false,
};
axios.post<Task>("/api/task", newTask).then((res) => {
this.tasks.push(res.data);
});
}
}
export default new TodoService();
views/TodoView.vue
<script setup lang="ts">
import service from "@/services/TodoService";
import { ref } from "vue";
import { useQuasar } from "quasar";
service.getAllTasks();
const $q = useQuasar();
const tasks = service.getTasks;
const newTask = ref("");
const deleteTask = (index: number) => {
$q.dialog({
title: "Confirm",
message: "Really delete?",
cancel: true,
persistent: true,
}).onOk(() => {
service.deleteTask(index);
$q.notify({ message: "Task deleted.", color: "info" });
});
};
const addTask = () => {
if (newTask.value.length == 0) {
$q.notify({ message: "Add Task is required.", color: "negative" });
} else {
service.addTask(newTask.value);
newTask.value = "";
}
};
</script>
...以下同じ
JSON Serverを同一PORT上から呼び出せるように、Proxyを追加。
vite.config.ts
...
export default defineConfig({
...
server: {
proxy: {
"/api": {
target: "http://localhost:3000/",
rewrite: (path) => path.replace(/^\/api/, ""),
},
},
},
終わりに
今までモックアップ用に実装している方は、ぜひJSON ServerやPaste JSON as Codeを使いこなて、よりシンプルな開発を進めていただければ幸いです。
Discussion