著者は、Write for DOnationsプログラムの一部として寄付を受け取るためにSoftware in the Public Interest Incを選択しました。
前書き
Nest.jsは、TypeScriptで構築されたスケーラブルなサーバーサイドJavaScriptフレームワークであり、JavaScriptとの互換性を維持しているため、効率的で信頼性の高いバックエンドアプリケーションを構築するための効果的なツールになります。 Node.js開発の世界に成熟した構造設計パターンを提供するモジュラーアーキテクチャを備えています。
Vue.jsは、ユーザーインターフェイスを構築するためのフロントエンドJavaScriptフレームワークです。 シンプルでありながら非常に強力なAPIと優れたパフォーマンスを備えています。 Vue.js is capable of powering the front-end layer and logic of any web application irrespective of the size. 他のライブラリまたは既存のプロジェクトと簡単に統合できるため、ほとんどの最新のWebアプリケーションに最適です。
このチュートリアルでは、Nest.jsアプリケーションを構築して、そのビルディングブロックと最新のWebアプリケーションを構築するための基本原則を理解します。 このプロジェクトにアプローチするには、アプリケーションを2つの異なるセクション(フロントエンドとバックエンド)に分けます。 まず、Nest.jsで構築されたRESTfulバックエンドAPIに集中します。 次に、Vue.jsで構築するフロントエンドに焦点を当てます。 両方のアプリケーションは異なるポートで実行され、個別のドメインとして機能します。
ユーザーが新しい投稿を作成して保存し、ホームページで保存した投稿を表示し、投稿の編集や削除などの他のプロセスを実行できるブログアプリケーションを構築します。 さらに、アプリケーションを接続し、そのデータをMongoDBで永続化します。これは、JSONドキュメントを受信して保存できるスキーマのないNoSQLデータベースです。 このチュートリアルは、開発環境でのアプリケーションの構築に焦点を当てています。 実稼働環境では、アプリケーションのユーザー認証も考慮する必要があります。
前提条件
このチュートリアルを完了するには、次のものが必要です。
-
Node.js(少なくともv6)およびnpm(少なくともv5.2)のローカルインストール。 Node.js is a JavaScript run-time environment that allows you to run your code outside of the browser.
npm
と呼ばれるパッケージマネージャーがプリインストールされており、パッケージをインストールおよび更新できます。 これらをmacOSまたはUbuntu18.04にインストールするには、How to Install Node.js and Create a Local Development Environment on macOSの手順またはHow To Install Node.js on Ubuntu 18.04の「PPAを使用したインストール」セクションに従います。 -
マシンにインストールされたMongoDB。 指示hereに従って、選択したオペレーティングシステム用にダウンロードしてインストールします。 MongoDBを正常にインストールするには、MacでHomebrewを使用するか、MongoDB website.からダウンロードしてインストールします。
-
TypeScriptとJavaScriptの基本的な理解。
-
Visual Studio Code、Atom、Sublime Textなどのテキストエディタがインストールされています。
[.note]#Note:このチュートリアルでは、開発にmacOSマシンを使用します。 別のオペレーティングシステムを使用している場合は、チュートリアル全体でnpm
コマンドにsudo
を使用する必要がある場合があります。
#
[[step-1 -—- installing-nest-js-and-other-dependencies]] ==ステップ1—Nest.jsとその他の依存関係のインストール
このセクションでは、アプリケーションと必要な依存関係をローカルマシンにインストールすることで、Nest.jsを使い始めます。 Nest.jsが提供するCLIを使用するか、GitHubからスタータープロジェクトをインストールすることで、Nest.jsを簡単にインストールできます。 このチュートリアルでは、CLIを使用してアプリケーションをセットアップします。 開始するには、ターミナルから次のコマンドを実行して、マシンにグローバルにインストールします。
npm i -g @nestjs/cli
次のような出力が表示されます。
Output@nestjs/[email protected]
added 220 packages from 163 contributors in 49.104s
Nest CLIのインストールを確認するには、ターミナルから次のコマンドを実行します。
nest --version
マシンにインストールされている現在のバージョンを示す出力が表示されます。
Output5.8.0
nest
コマンドを使用してプロジェクトを管理し、それを使用して、コントローラー、モジュール、プロバイダーなどの関連ファイルを生成します。
このチュートリアルのプロジェクトを開始するには、nest
コマンドを使用して、ターミナルから次のコマンドを実行し、blog-backend
という名前の新しいNest.jsプロジェクトを作成します。
nest new blog-backend
コマンドを実行した直後に、nest
は、description
、version
、author
などの基本情報を提供するように要求します。 先に進み、適切な詳細を提供します。 各プロンプトに応答した後、続行するには、コンピューターでENTER
を押します。
次に、パッケージマネージャーを選択します。 このチュートリアルでは、npm
を選択し、ENTER
を押してNest.jsのインストールを開始します。
これにより、ローカル開発フォルダー内のblog-backend
フォルダーに新しいNest.jsプロジェクトが生成されます。
次に、ターミナルから新しいプロジェクトフォルダーに移動します。
cd blog-backend
次のコマンドを実行して、他のサーバーの依存関係をインストールします。
npm install --save @nestjs/mongoose mongoose
MongoDBのオブジェクトモデリングツール用のNest.js専用パッケージである@nestjs/mongoose
と、Mongoose用のパッケージであるmongoose
をインストールしました。
次に、次のコマンドを使用してアプリケーションを起動します。
npm run start
これで、お気に入りのブラウザーからhttp://localhost:3000
に移動すると、アプリケーションが実行されていることがわかります。
Nest CLIコマンドの可用性を活用して、プロジェクトを正常に生成しました。 その後、アプリケーションの実行に進み、ローカルマシンのデフォルトポート3000
でアクセスしました。 次のセクションでは、データベース接続の構成を設定して、アプリケーションをさらに詳しく説明します。
[[step-2 -—- configuring-and-connecting-with-the-database]] ==ステップ2—構成とデータベースへの接続
このステップでは、MongoDBを構成してNest.jsアプリケーションに統合します。 MongoDBを使用して、アプリケーションのデータを保存します。 MongoDBは、データをdocumentsにfield : valueペアとして格納します。 このデータ構造にアクセスするには、Mongooseを使用します。これは、MongoDBデータベースが格納するデータのタイプを表すスキーマを定義できるオブジェクトドキュメントモデリング(ODM)です。
MongoDBを起動するには、アプリケーションが実行を継続できるように別のターミナルウィンドウを開き、次のコマンドを実行します。
sudo mongod
これにより、MongoDBサービスが開始され、マシンのバックグラウンドでデータベースが実行されます。
テキストエディタでプロジェクトblog-backend
を開き、./src/app.module.ts
に移動します。 インストールされたMongooseModule
をルートApplicationModule
に含めることにより、データベースへの接続を設定できます。 これを実現するには、app.module.ts
のコンテンツを次の強調表示された行で更新します。
~/blog-backend/src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MongooseModule } from '@nestjs/mongoose';
@Module({
imports: [
MongooseModule.forRoot('mongodb://localhost/nest-blog', { useNewUrlParser: true }),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule { }
このファイルでは、forRoot()
メソッドを使用してデータベースへの接続を提供します。 編集が終了したら、ファイルを保存して閉じます。
これで、MongoDB用のMongooseモジュールを使用してデータベース接続をセットアップしました。 次のセクションでは、Mongooseライブラリ、TypeScriptインターフェイス、およびデータ転送オブジェクト(DTO)スキーマを使用してデータベーススキーマを作成します。
[[step-3 -—- creating-a-database-schema-interfaces-and-dto]] ==ステップ3—データベーススキーマ、インターフェイス、およびDTOの作成
このステップでは、Mongooseを使用して、データベース用にschema、interface、およびdata transfer objectを作成します。 Mongooseは、データ間の関係の管理に役立ち、データ型のスキーマ検証を提供します。 アプリケーションのデータベース内のデータの構造とデータ型を定義しやすくするために、以下を決定するファイルを作成します。
-
database schema:これは、データベースに格納する必要のあるデータの構造とタイプを定義するための青写真としてのデータの編成です。
-
interfaces:TypeScriptインターフェイスはタイプチェックに使用されます。 アプリケーションに渡す必要のあるデータのタイプを定義するために使用できます。
-
data transfer object:これは、データがネットワークを介して送信される方法を定義し、プロセス間でデータを伝送するオブジェクトです。
開始するには、アプリケーションが現在実行されているターミナルに戻り、CTRL + C
でプロセスを停止してから、./src/
フォルダーに移動します。
cd ./src/
次に、blog
という名前のディレクトリと、その中にschemas
フォルダを作成します。
mkdir -p blog/schemas
schemas
フォルダーに、blog.schema.ts
という名前の新しいファイルを作成し、テキストエディターを使用して開きます。 次に、次のコンテンツを追加します。
~/blog-backend/src/blog/schemas/blog.schema.ts
import * as mongoose from 'mongoose';
export const BlogSchema = new mongoose.Schema({
title: String,
description: String,
body: String,
author: String,
date_posted: String
})
ここでは、Mongooseを使用して、データベースに保存するデータのタイプを定義しました。 すべてのフィールドに文字列値のみが格納され、受け入れられるように指定しました。 編集が終了したら、ファイルを保存して閉じます。
これで、データベーススキーマが決定されたので、インターフェイスの作成に進むことができます。
開始するには、blog
フォルダーに戻ります。
cd ~/blog-backend/src/blog/
interfaces
という名前の新しいフォルダーを作成し、そのフォルダーに移動します。
mkdir interfaces
interfaces
フォルダーに、post.interface.ts
という名前の新しいファイルを作成し、テキストエディターを使用して開きます。 次のコンテンツを追加して、Post
のデータのタイプを定義します。
~/blog-backend/src/blog/interfaces/post.interface.ts
import { Document } from 'mongoose';
export interface Post extends Document {
readonly title: string;
readonly description: string;
readonly body: string;
readonly author: string;
readonly date_posted: string
}
このファイルでは、Post
型のデータ型を文字列値として正常に定義しています。 ファイルを保存して終了します。
アプリケーションはデータベースにデータを送信する機能を実行するため、ネットワークを介してデータを送信する方法を定義するデータ転送オブジェクトを作成します。
これを実現するには、./src/blog
フォルダー内にフォルダーdto
を作成します。 新しく作成したフォルダー内に、create-post.dto.ts
という名前の別のファイルを作成します
blog
フォルダーに戻ります。
cd ~/blog-backend/src/blog/
次に、dto
という名前のフォルダーを作成し、そのフォルダーに移動します。
mkdir dto
dto
フォルダーに、create-post.dto.ts
という名前の新しいファイルを作成し、テキストエディターを使用して開いて、次のコンテンツを追加します。
~/blog-backend/src/blog/dto/create-post.dto.ts
export class CreatePostDTO {
readonly title: string;
readonly description: string;
readonly body: string;
readonly author: string;
readonly date_posted: string
}
CreatePostDTO
クラスの個々のプロパティのそれぞれに、データ型がstring
であり、不必要な変更を避けるためにreadonly
としてマークされています。 編集が終了したら、ファイルを保存して終了します。
この手順では、データベースのデータベーススキーマ、インターフェイス、およびデータベースに保存するデータのデータ転送オブジェクトを作成しました。 次に、ブログ用のモジュール、コントローラー、およびサービスを生成します。
[[step-4 -—- creating-the-module-controller-and-service-for-the-blog]] ==ステップ4—ブログのモジュール、コントローラー、およびサービスの作成
このステップでは、ブログ用のモジュールを作成して、アプリケーションの既存の構造を改善します。 このモジュールは、アプリケーションのファイル構造を整理します。 次に、ルートを処理し、クライアントからのHTTPリクエストを処理するコントローラーを作成します。 最後に、アプリケーションのコントローラーが処理するには複雑すぎるビジネスロジックをすべて処理するサービスを設定します。
モジュールの生成
AngularフロントエンドWebフレームワークと同様に、Nest.jsはモジュラー構文を使用します。 Nest.js applications have a modular design; it comes installed with a single root module, which is often sufficient for a small application. しかし、アプリケーションが成長し始めると、Nest.jsはコードを関連機能に分割する複数モジュールの組織を推奨します。
Nest.jsのmoduleは、@Module()
デコレータによって識別され、controllers
やproviders
などのプロパティを持つオブジェクトを取り込みます。 これらの各プロパティは、それぞれcontrollers
とproviders
の配列を取ります。
構造をより整理するために、このブログアプリケーション用の新しいモジュールを生成します。 開始するには、まだ~/blog-backend
フォルダーで、次のコマンドを実行します。
nest generate module blog
次のような出力が表示されます。
OutputCREATE /src/blog/blog.module.ts
UPDATE /src/app.module.ts
このコマンドは、アプリケーション用にblog.module.ts
という名前の新しいモジュールを生成し、新しく作成されたモジュールをアプリケーションのルートモジュールにインポートしました。 これにより、Nest.jsはルートモジュール以外の別のモジュールを認識することができます。
このファイルには、次のコードが表示されます。
~/blog-backend/src/blog/blog.module.ts
import { Module } from '@nestjs/common';
@Module({})
export class BlogModule {}
このBlogModule
は、チュートリアルの後半で必要なプロパティで更新します。 ファイルを保存して終了します。
サービスの生成
serviceは、Nest.jsではプロバイダーとも呼ばれ、コントローラーからロジックを削除するように設計されています。これは、HTTPリクエストのみを処理し、より複雑なタスクをサービスにリダイレクトすることを目的としています。 サービスはプレーンなJavaScriptクラスであり、その上に@Injectable()
デコレータがあります。 新しいサービスを生成するには、プロジェクトディレクトリ内にいる間にターミナルから次のコマンドを実行します。
nest generate service blog
次のような出力が表示されます。
Output CREATE /src/blog/blog.service.spec.ts (445 bytes)
CREATE /src/blog/blog.service.ts (88 bytes)
UPDATE /src/blog/blog.module.ts (529 bytes)
ここで使用されるnest
コマンドは、テストに使用できるblog.service.spec.ts
ファイルを作成しました。 また、新しいblog.service.ts
ファイルを作成しました。このファイルは、このアプリケーションのすべてのロジックを保持し、MongoDBデータベースへのドキュメントの追加と取得を処理します。 また、新しく作成されたサービスを自動的にインポートし、blog.module.tsに追加しました。
サービスは、アプリケーション内のすべてのロジックを処理し、データベースとのやり取りを行い、適切な応答をコントローラーに返します。 これを行うには、テキストエディタでblog.service.ts
ファイルを開き、内容を次のように置き換えます。
~/blog-backend/src/blog/blog.service.ts
import { Injectable } from '@nestjs/common';
import { Model } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';
import { Post } from './interfaces/post.interface';
import { CreatePostDTO } from './dto/create-post.dto';
@Injectable()
export class BlogService {
constructor(@InjectModel('Post') private readonly postModel: Model) { }
async getPosts(): Promise {
const posts = await this.postModel.find().exec();
return posts;
}
async getPost(postID): Promise {
const post = await this.postModel
.findById(postID)
.exec();
return post;
}
async addPost(createPostDTO: CreatePostDTO): Promise {
const newPost = await this.postModel(createPostDTO);
return newPost.save();
}
async editPost(postID, createPostDTO: CreatePostDTO): Promise {
const editedPost = await this.postModel
.findByIdAndUpdate(postID, createPostDTO, { new: true });
return editedPost;
}
async deletePost(postID): Promise {
const deletedPost = await this.postModel
.findByIdAndRemove(postID);
return deletedPost;
}
}
このファイルでは、最初に必要なモジュールを@nestjs/common
、mongoose
、および@nestjs/mongoose
からインポートしました。 また、Post
という名前のインターフェイスとデータ転送オブジェクトCreatePostDTO
をインポートしました。
constructor
に、@InjectModel(
を追加しました。これにより、'
Post'
)Post
モデルがこのBlogService
クラスに挿入されます。 これで、この注入されたモデルを使用して、すべての投稿を取得し、単一の投稿を取得し、他のデータベース関連のアクティビティを実行できます。
次に、次のメソッドを作成しました。
-
getPosts()
:データベースからすべての投稿をフェッチします。 -
getPost()
:データベースから単一の投稿を取得します。 -
addPost()
:新しい投稿を追加します。 -
editPost()
:単一の投稿を更新します。 -
deletePost()
:特定の投稿を削除します。
完了したら、ファイルを保存して終了します。
バックエンドAPIからMongoDBデータベースとの適切な対話を処理するいくつかのメソッドのセットアップと作成が完了しました。 次に、フロントエンドクライアントからのHTTP呼び出しを処理する必要なルートを作成します。
コントローラーの生成
巣の中。 js、controllersは、アプリケーションのクライアント側からの着信要求を処理し、適切な応答を返す責任があります。 他のほとんどのWebフレームワークと同様に、アプリケーションがリクエストをリッスンし、それに応答することが重要です。
ブログアプリケーションのすべてのHTTPリクエストに対応するには、nest
コマンドを利用して新しいコントローラーファイルを生成します。 プロジェクトディレクトリblog-backend
にいることを確認し、次のコマンドを実行します。
nest generate controller blog
次のような出力が表示されます。
OutputCREATE /src/blog/blog.controller.spec.ts (474 bytes)
CREATE /src/blog/blog.controller.ts (97 bytes)
UPDATE /src/blog/blog.module.ts (483 bytes)
出力は、このコマンドがsrc/blog
ディレクトリ内に2つの新しいファイルを作成したことを示しています。 それらはblog.controller.spec.ts
とblog.controller.ts
です。 前者は、新しく作成されたコントローラーの自動テストを作成するために使用できるファイルです。 後者はコントローラーファイル自体です。 Nest.jsのコントローラーは、@Controller
メタデータで装飾されたTypeScriptファイルです。 このコマンドは、新しく作成されたコントローラーもインポートし、ブログモジュールに追加しました。
次に、テキストエディタでblog.controller.ts
ファイルを開き、次の内容で更新します。
~/blog-backend/src/blog/blog.controller.ts
import { Controller, Get, Res, HttpStatus, Param, NotFoundException, Post, Body, Query, Put, Delete } from '@nestjs/common';
import { BlogService } from './blog.service';
import { CreatePostDTO } from './dto/create-post.dto';
import { ValidateObjectId } from '../shared/pipes/validate-object-id.pipes';
@Controller('blog')
export class BlogController {
constructor(private blogService: BlogService) { }
@Get('posts')
async getPosts(@Res() res) {
const posts = await this.blogService.getPosts();
return res.status(HttpStatus.OK).json(posts);
}
@Get('post/:postID')
async getPost(@Res() res, @Param('postID', new ValidateObjectId()) postID) {
const post = await this.blogService.getPost(postID);
if (!post) throw new NotFoundException('Post does not exist!');
return res.status(HttpStatus.OK).json(post);
}
@Post('/post')
async addPost(@Res() res, @Body() createPostDTO: CreatePostDTO) {
const newPost = await this.blogService.addPost(createPostDTO);
return res.status(HttpStatus.OK).json({
message: "Post has been submitted successfully!",
post: newPost
})
}
}
このファイルでは、最初に、@nestjs/common
モジュールからのHTTP要求を処理するために必要なモジュールをインポートしました。 次に、BlogService
、CreatePostDTO
、およびValidateObjectId
の3つの新しいモジュールをインポートしました。 その後、アクセスを取得し、BlogService
ファイル内ですでに定義されている関数を利用するために、コンストラクターを介してBlogService
をコントローラーに挿入しました。 これは、効率を高め、アプリケーションのモジュール性を高めるためにNest.jsで使用されるdependency injectionと見なされるパターンです。
最後に、次の非同期メソッドを作成しました。
-
getPosts()
:このメソッドは、クライアントからHTTP GET要求を受信してデータベースからすべての投稿をフェッチし、適切な応答を返す機能を実行します。@Get(
で装飾されています。'
posts'
) -
getPost()
:これはパラメーターとしてpostID
を取り、データベースから単一の投稿をフェッチします。 このメソッドに渡されるpostID
パラメータに加えて、ValidateObjectId()
という名前の追加のメソッドが追加されていることに気づきました。 このメソッドは、Nest.jsのPipeTransform
インターフェースを実装します。 その目的は、postID
パラメーターがデータベースで見つかることを検証および確認することです。 このメソッドは次のセクションで定義します。 -
addPost()
:このメソッドは、データベースに新しい投稿を追加するためのPOSTHTTPリクエストを処理します。
特定の投稿を編集および削除できるようにするには、blog.controller.ts
ファイルにさらに2つのメソッドを追加する必要があります。 これを行うには、以前にblog.controller.ts
に追加したaddPost()
メソッドの直後に次のeditPost()
およびdeletePost()
メソッドを含めます。
~/blog-backend/src/blog/blog.controller.ts
...
@Controller('blog')
export class BlogController {
...
@Put('/edit')
async editPost(
@Res() res,
@Query('postID', new ValidateObjectId()) postID,
@Body() createPostDTO: CreatePostDTO
) {
const editedPost = await this.blogService.editPost(postID, createPostDTO);
if (!editedPost) throw new NotFoundException('Post does not exist!');
return res.status(HttpStatus.OK).json({
message: 'Post has been successfully updated',
post: editedPost
})
}
@Delete('/delete')
async deletePost(@Res() res, @Query('postID', new ValidateObjectId()) postID) {
const deletedPost = await this.blogService.deletePost(postID);
if (!deletedPost) throw new NotFoundException('Post does not exist!');
return res.status(HttpStatus.OK).json({
message: 'Post has been deleted!',
post: deletedPost
})
}
}
ここに追加しました:
-
editPost()
:このメソッドはpostID
のクエリパラメータを受け入れ、単一の投稿を更新する機能を実行します。 また、ValidateObjectId
メソッドを使用して、編集する必要のある投稿を適切に検証しました。 -
deletePost()
:このメソッドはpostID
のクエリパラメータを受け入れ、データベースから特定の投稿を削除します。
BlogController
と同様に、ここで定義した各非同期メソッドにはメタデータデコレータがあり、Nest.jsがルーティングメカニズムとして使用するプレフィックスを受け取ります。 どのコントローラーがどのリクエストを受信するかを制御し、リクエストを処理してレスポンスを返すメソッドをそれぞれポイントします。
たとえば、このセクションで作成したBlogController
には、プレフィックスblog
と、プレフィックスposts
を受け取るgetPosts()
という名前のメソッドがあります。 これは、blog/posts
(http:localhost:3000/blog/posts
)のエンドポイントに送信されたGET要求は、 `getPosts()`メソッドによって処理されることを意味します。 この例は、他のメソッドがHTTP要求を処理する方法に似ています。
ファイルを保存して終了します。
完全なblog.controller.ts
ファイルについては、このアプリケーションのDO Community repositoryにアクセスしてください。
このセクションでは、アプリケーションをより整理した状態に保つためのモジュールを作成しました。 また、データベースと対話して適切な応答を返すことにより、アプリケーションのビジネスロジックを処理するサービスを作成しました。 最後に、コントローラーを生成し、クライアント側からGET
、POST
、PUT
、DELETE
などのHTTP要求を処理するために必要なメソッドを作成しました。 次のステップでは、バックエンドのセットアップを完了します。
[[step-5 -—- creating-an-extra-validation-for-mongoose]] ==ステップ5—Mongooseの追加の検証を作成する
ブログアプリケーションの各投稿は、PostID
とも呼ばれる一意のIDで識別できます。 つまり、投稿を取得するには、このIDをクエリパラメータとして渡す必要があります。 このpostID
パラメータを検証し、投稿がデータベースで利用可能であることを確認するには、BlogController
内の任意のメソッドから初期化できる再利用可能な関数を作成する必要があります。
これを構成するには、./src/blog
フォルダーに移動します。
cd ./src/blog/
次に、shared
という名前の新しいフォルダーを作成します。
mkdir -p shared/pipes
pipes
フォルダーで、テキストエディターを使用して、validate-object-id.pipes.ts
という名前の新しいファイルを作成して開きます。 次のコンテンツを追加して、受け入れられるpostID
データを定義します。
~/blog-backend/src/blog/shared/pipes/validate-object-id.pipes.ts
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
import * as mongoose from 'mongoose';
@Injectable()
export class ValidateObjectId implements PipeTransform {
async transform(value: string, metadata: ArgumentMetadata) {
const isValid = mongoose.Types.ObjectId.isValid(value);
if (!isValid) throw new BadRequestException('Invalid ID!');
return value;
}
}
ValidateObjectId()
クラスは、@nestjs/common
モジュールのPipeTransform
メソッドを実装します。 これには、パラメーターとして値を受け取るtransform()
という名前の単一のメソッドがあります。この場合はpostID
です。 上記の方法では、データベースで見つからないpostID
を含むこのアプリケーションのフロントエンドからのHTTPリクエストは、無効と見なされます。 ファイルを保存して閉じます。
サービスとコントローラーの両方を作成した後、BlogSchema
に基づくPost
モデルをセットアップする必要があります。 この構成はルートApplicationModule
内でセットアップできますが、この場合、BlogModule
でモデルを構築すると、アプリケーションの組織が維持されます。 ./src/blog/blog.module.ts
を開き、次の強調表示された行で更新します。
~/blog-backend/src/blog/blog.module.ts
import { Module } from '@nestjs/common';
import { BlogController } from './blog.controller';
import { BlogService } from './blog.service';
import { MongooseModule } from '@nestjs/mongoose';
import { BlogSchema } from './schemas/blog.schema';
@Module({
imports: [
MongooseModule.forFeature([{ name: 'Post', schema: BlogSchema }])
],
controllers: [BlogController],
providers: [BlogService]
})
export class BlogModule { }
このモジュールは、MongooseModule.forFeature()
メソッドを使用して、モジュールに登録するモデルを定義します。 これがないと、@injectModel()
デコレータを使用してBlogService
内にPostModel
を挿入することはできません。 コンテンツの追加が終了したら、ファイルを保存して閉じます。
このステップでは、Nest.jsを使用して完全なバックエンドRESTful APIを作成し、MongoDBと統合しました。 次のセクションでは、フロントエンドアプリケーションが別のポートで実行されるため、別のサーバーからのHTTPリクエストを許可するようにサーバーを構成します。
[[step-6 -—- enableing-cors]] ==ステップ6—CORSを有効にする
1つのドメインから別のドメインへのHTTP要求は、サーバーによって許可されるように指定されている場合を除き、多くの場合デフォルトでブロックされます。 フロントエンドアプリケーションがバックエンドサーバーにリクエストを送信するには、Cross-origin resource sharing(CORS)を有効にする必要があります。これは、Webページ上の制限されたリソースのリクエストを許可する手法です。
Nest.jsでCORSを有効にするには、main.ts
ファイルに単一のメソッドを追加する必要があります。 ./src/main.ts
にあるテキストエディタでこのファイルを開き、次の強調表示されたコンテンツで更新します。
~/blog-backend/src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors();
await app.listen(3000);
}
bootstrap();
ファイルを保存して終了します。
バックエンドのセットアップが完了したので、フロントエンドに焦点を移し、Vue.jsを使用して、これまでに構築されたAPIを使用します。
[[step-7 -—- creating-the-vue-js-frontend]] ==ステップ7—Vue.jsフロントエンドの作成
このセクションでは、Vue.jsを使用してフロントエンドアプリケーションを作成します。 Vue CLIは、手間をかけずに新しいVue.jsプロジェクトをすばやく生成してインストールできる標準ツールです。
まず、Vue CLIをマシンにグローバルにインストールする必要があります。 別のターミナルを開き、blog-backend
フォルダーから作業する代わりに、ローカルプロジェクトの開発フォルダーに移動して次のコマンドを実行します。
npm install -g @vue/cli
インストールプロセスが完了したら、vue
コマンドを使用して新しいVue.jsプロジェクトを作成します。
vue create blog-frontend
このコマンドを入力すると、短いプロンプトが表示されます。 manually select features
オプションを選択し、コンピューターでSPACE
を押して複数の機能を強調表示することにより、このプロジェクトに必要な機能を選択します。 Babel
、Router
、およびLinter / Formatter
を選択します。
次の手順では、y
と入力して、ルーターの履歴モードを使用します。これにより、ルーターファイル内で履歴モードが有効になり、このプロジェクト用に自動的に生成されます。 さらに、ESLint with error prevention only
を選択して、リンター/フォーマッター構成を選択します。 次に、追加のLint機能のLint on save
を選択します。 次に、将来のプロジェクトのために構成をdedicated config file
で保存することを選択します。 vueconfig
のように、プリセットの名前を入力します。
Vue.js will then start creating the application and all its required dependencies in a directory named blog-frontend
.
インストールプロセスが完了したら、Vue.jsアプリケーション内をナビゲートします。
cd blog-frontend
次に、次を使用して開発サーバーを起動します。
npm run serve
アプリケーションはhttp://localhost:8080
で実行されます。
このアプリケーション内でHTTPリクエストを実行するので、Axiosをインストールする必要があります。Axiosは、ブラウザ用の約束ベースのHTTPクライアントです。 ここでAxiosを使用して、アプリケーション内のさまざまなコンポーネントからHTTPリクエストを実行します。 コンピューターの端末からCTRL + C
を押してフロントエンドアプリケーションを停止し、次のコマンドを実行します。
npm install axios --save
フロントエンドアプリケーションは、アプリケーション内のさまざまなコンポーネントから特定のドメインのバックエンドAPIに対してAPI呼び出しを行います。 このアプリケーションの適切な構造を確保するために、helper
ファイルを作成し、サーバーbaseURL
を定義できます。
まず、まだblog-frontend
内にあるターミナルから、./src/
フォルダーに移動します。
cd ./src/
utils
という名前の別のフォルダーを作成します。
mkdir utils
utils
フォルダーで、テキストエディターを使用して、helper.js
という名前の新しいファイルを作成して開きます。 次のコンテンツを追加して、バックエンドNest.jsプロジェクトのbaseURL
を定義します。
~blog-frontend/src/utils/helper.js
export const server = {
baseURL: 'http://localhost:3000'
}
baseURL
を定義することで、Vue.jsコンポーネントファイル内のどこからでも呼び出すことができます。 URLを変更する必要がある場合は、アプリケーション全体ではなく、このファイルのbaseURL
を更新する方が簡単です。
このセクションでは、新しいVue.jsアプリケーションを作成するためのツールであるVue CLIをインストールしました。 このツールを使用して、blog-frontend
アプリケーションを作成しました。 さらに、アプリケーションを実行し、Axiosという名前のライブラリをインストールしました。これは、アプリケーション内でHTTP呼び出しが行われるたびに使用します。 次に、アプリケーションのコンポーネントを作成します。
[[step-8 -—- creating-reusable-components]] ==ステップ8—再利用可能なコンポーネントの作成
次に、アプリケーションの再利用可能なコンポーネントを作成します。これは、Vue.jsアプリケーションの標準構造です。 Vue.jsのコンポーネントシステムにより、開発者は独自の状態、マークアップ、スタイルを持つことができるインターフェイスの単一の独立したユニットを構築できます。 これにより、Vue.jsのコンポーネントが再利用可能になります。
すべてのVue.jsコンポーネントには、3つの異なるセクションが含まれています。
-
<template>
:HTMLコンテンツが含まれています -
<script>
:すべての基本的なフロントエンドロジックを保持し、関数を定義します -
<style>
:個別のコンポーネントごとのスタイルシート
最初に、コンポーネントを作成して新しい投稿を作成します。 これを行うには、./src/components
フォルダー内にpost
という名前の新しいフォルダーを作成します。このフォルダーには、投稿に必要な再利用可能なコンポーネントが格納されます。 次に、テキストエディタを使用して、新しく作成したpost
フォルダ内に別のファイルを作成し、Create.vue
という名前を付けます。 新しいファイルを開き、次のコードを追加します。このコードには、投稿を送信するために必要な入力フィールドが含まれています。
~blog-frontend/src/components/post/Create.vue
Create Post
これは、CreatePost
コンポーネントの<template>
セクションです。 新しい投稿を作成するために必要なHTML入力要素が含まれています。 各入力フィールドには、入力属性としてv-model
ディレクティブがあります。 これは、Vue.jsがユーザーの入力を簡単に取得できるように、各フォーム入力で双方向のデータバインディングを確保するためです。
次に、前のコンテンツの直後にある同じファイルに<script>
セクションを追加します。
~blog-frontend/src/components/post/Create.vue
...
ここでは、createPost()
という名前のメソッドを追加して、新しい投稿を作成し、Axiosを使用してサーバーに送信します。 ユーザーが新しい投稿を作成すると、アプリケーションはホームページにリダイレクトされ、ユーザーは作成された投稿のリストを表示できます。
このチュートリアルの後半でリダイレクトを実装するようにvue-routerを構成します。
編集が終了したら、ファイルを保存して閉じます。 完全なCreate.vue
ファイルについては、このアプリケーションのDO Community repositoryにアクセスしてください。
次に、特定の投稿を編集するための別のコンポーネントを作成する必要があります。 ./src/components/post
フォルダーに移動し、別のファイルを作成して、Edit.vue
という名前を付けます。 <template>
セクションを含む次のコードを追加します。
~blog-frontend/src/components/post/Edit.vue
Edit Post
このテンプレートセクションには、CreatePost()
コンポーネントと同様のコンテンツが含まれています。唯一の違いは、編集が必要な特定の投稿の詳細が含まれていることです。
次に、Edit.vue
の</template>
セクションの直後に `
ここでは、特定の投稿を識別するためのルートパラメータid
を取得しました。 次に、getPost()
という名前のメソッドを作成して、データベースからこの投稿の詳細を取得し、それを使用してページを更新しました。 最後に、editPost()
メソッドを作成して、編集した投稿をPUTHTTPリクエストでバックエンドサーバーに送信します。
ファイルを保存して終了します。 完全なEdit.vue
ファイルについては、このアプリケーションのDO Community repositoryにアクセスしてください。
次に、./src/components/post
フォルダー内に新しいコンポーネントを作成し、Post.vue
という名前を付けます。 これにより、ホームページから特定の投稿の詳細を表示できます。 次のコンテンツをPost.vue
に追加します。
~blog-frontend/src/components/post/Post.vue
{{ post.title }}
Post by {{post.author}}, {{post.date_posted}}.
{{ post.body }}
このコードは、title
、author
、および投稿body
を含む投稿の詳細をレンダリングします。
ここで、</template>
の直後に、次のコードをファイルに追加します。
~blog-frontend/src/components/post/Post.vue
...
投稿編集コンポーネントの<script>
セクションと同様に、ルートパラメータid
を取得し、それを使用して特定の投稿の詳細を取得しました。
コンテンツの追加が終了したら、ファイルを保存して閉じます。 完全なPost.vue
ファイルについては、このアプリケーションのDO Community repositoryにアクセスしてください。
次に、作成されたすべての投稿をユーザーに表示するには、新しいコンポーネントを作成します。 src/views
のviews
フォルダーに移動すると、Home.vue
コンポーネントが表示されます。このファイルが存在しない場合は、テキストエディターを使用して作成し、次のコードを追加します。
~blog-frontend/src/views/Home.vue
Nest Blog Tutorial
This is the description of the blog built with Nest.js, Vue.js and MongoDB
No post found at the moment
{{ post.title }}
{{ post.body }}
View Post
Edit Post
ここでは、<template>
セクション内で、<router-link>
を使用して、post._id
をクエリパラメーターとして渡して、編集および投稿の表示用のリンクを作成しました。 また、v-if
ディレクティブを使用して、ユーザーの投稿を条件付きでレンダリングしました。 データベースからの投稿がない場合、ユーザーには次のテキストのみが表示されます:No post found at the moment。
ファイルを保存して終了します。 完全なHome.vue
ファイルについては、このアプリケーションのDO Community repositoryにアクセスしてください。
ここで、Home.vue
の</template>
セクションの直後に、次の</script>
セクションを追加します。
~blog-frontend/src/views/Home.vue
...
このファイルの<script>
セクション内で、データベースからすべての投稿をフェッチするfetchPosts()
という名前のメソッドを作成し、サーバーから返されたデータでページを更新しました。
次に、フロントエンドアプリケーションのApp
コンポーネントを更新して、Home
およびCreate
コンポーネントへのリンクを作成します。 src/App.vue
を開き、次のように更新します。
~blog-frontend/src/App.vue
Home
コンポーネントとCreate
コンポーネントの両方へのリンクを含めるほかに、このコンポーネントのスタイルシートであり、上のいくつかの要素のスタイルの定義を保持する<Style>
セクションも含めました。ページ。 ファイルを保存して終了します。
このステップでは、アプリケーションに必要なすべてのコンポーネントを作成しました。 次に、ルーターファイルを構成します。
[[step-9 -—- setting-up-routing]] ==ステップ9—ルーティングの設定
必要なすべての再利用可能なコンポーネントを作成した後、作成したすべてのコンポーネントへのリンクでコンテンツを更新することにより、ルーターファイルを適切に構成できるようになりました。 これにより、フロントエンドアプリケーション内のすべてのエンドポイントが適切なアクションのために特定のコンポーネントにマップされます。 ./src/router.js
に移動し、その内容を次のように置き換えます。
~blog-frontend/src/router.js
import Vue from 'vue'
import Router from 'vue-router'
import HomeComponent from '@/views/Home';
import EditComponent from '@/components/post/Edit';
import CreateComponent from '@/components/post/Create';
import PostComponent from '@/components/post/Post';
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{ path: '/', redirect: { name: 'home' } },
{ path: '/home', name: 'home', component: HomeComponent },
{ path: '/create', name: 'Create', component: CreateComponent },
{ path: '/edit/:id', name: 'Edit', component: EditComponent },
{ path: '/post/:id', name: 'Post', component: PostComponent }
]
});
vue-router
モジュールからRouter
をインポートし、mode
およびroutes
パラメーターを渡してインスタンス化しました。 vue-router
のデフォルトモードはハッシュモードです。ハッシュモードでは、URLハッシュを使用して完全なURLをシミュレートし、URLが変更されたときにページが再読み込みされないようにします。 ハッシュを不要にするために、ここでは履歴モードを使用して、ページをリロードすることなくURLナビゲーションを実現しています。 最後に、routes
オプション内で、エンドポイントのパスを指定しました。これは、ルートの名前と、アプリケーション内でルートが呼び出されたときにレンダリングされるコンポーネントです。 ファイルを保存して終了します。
アプリケーションへのルーティングを設定したので、Bootstrapファイルを含めて、アプリケーションのユーザーインターフェイスの事前に構築されたスタイル設定を支援する必要があります。 これを実現するには、テキストエディタで./public/index.html
ファイルを開き、ファイルに次のコンテンツを追加して、ブートストラップ用のCDNファイルを含めます。
~blog-frontend/public/index.html
...
blog-frontend
...
ファイルを保存して終了し、アプリケーションが現在実行されていない場合は、blog-frontend
に対してnpm run serve
を使用してアプリケーションを再起動します。
[.note]#Note:バックエンドサーバーとMongoDBインスタンスの両方が実行されていることを確認します。 それ以外の場合は、別の端末からblog-backend
に移動し、npm run start
を実行します。 また、新しいターミナルからもsudo mongod
を実行して、MongoDBサービスを開始します。
#
http://localhost:8080
でアプリケーションに移動します。 これで、投稿を作成および編集してブログをテストできます。
アプリケーションでCreateをクリックして、CreateComponent
ファイルに関連してレンダリングするCreate Post画面を表示します。 入力フィールドに値を入力し、Create Postボタンをクリックして投稿を送信します。 完了すると、アプリケーションはホームページにリダイレクトします。
アプリケーションのホームページはHomeComponent
をレンダリングします。 このコンポーネントには、データベースからすべての投稿を取得してユーザーに表示するHTTP呼び出しを送信するメソッドがあります。
特定の投稿のEdit Postボタンをクリックすると、編集ページに移動し、変更を組み込んで投稿を保存できます。
このセクションでは、アプリケーションのルーティングを構成および設定しました。 これで、ブログアプリケーションの準備が整いました。