Express.jsを使ってtodo appを作る。
Express.jsフレームワークを使ってTodo Appを作ってみました。
用語の間違いは指摘していただけると幸いです。
よろしくお願いいたします。
使用環境
Arch: x86_64
Docker: 20.10.21
Docker Compose version 2.13.0
node 18.12.1
mongo 4.4.6
Express.jsとは
ExpressとはNodejsで利用できるWebアプリケーションフレームワークです。
高速、革新的、最小限なフレームワーク(公式HPより)
Express.jsを利用することでシングルページ、マルチページ、およびハイブリッドWebアプリケーションを構築することができる。
フレームワークは他にもKoa.js, Nest.js, Meteor-jsなどがあります。
最小限&最軽量の構成なので、ORM、テンプレートエンジンも何もない状態から始め、開発者が必要に応じて、パッケージのインストールやカスタマイズしていくので拡張性が高い
現在はgithubスター数59.1k
- コア機能
- 単一ページ、複数ページ、およびハイブリッド Web アプリケーションの設計
- HTTP リクエストに応答するミドルウェアをセットアップ
- HTTP メソッドと URL に基づいてさまざまなアクションを実行するために使用されるルーティングテーブルを定義
- テンプレートエンジンを使用し、それに引数を渡すことによって動的レンダリングを行う
express-geenrator
create-react-appのようにアプリケーションスケルトンを作成するツール
npm i -g express-generator # グローバルインストールする
express --view=使うview名(ejs, pugなど) app名
まずHello Worldを表示
/にアクセスしたときHell Worldを表示する
req
第一引数で指定されたパスに入ってきたHTTPリクエストを表すオブジェクト
POSTメソッドによるフォームからの入力はreq.body.name名になる
res
指定されたパスに入ってきたリクエストに対するHTTPレスポンスを構成するためのオブジェクト
res.send('Hello World');とすることでHello Worldというレスポンスを返す
import express from 'express';
const app = express();
app.get('/', (req, res) => {
res.send('Hello World');
})
app.listen(3000);
今回はテンプレートエンジンを使わずに作ってみました。
まず使うモジュールをインストールします。
npm init -y
npm i express mongoose method-override nodemon
package.jsonがプロジェクトのルートディレクトリにあるので下記のようにした後、index.jsを作成する
nodemonを使いプログラムをdemon化する
ファイルが更新されると自動で再起動する。
"scripts": {
"start": "nodemon index.js",
}
index.jsに追加
import express from 'express' // expressのインポート
const app = exporess();
const mongoose = require('mongoose'); // mongodbの操作に使用
const methodOverride = require('method-override'); // フォームの入力(PUT, Deleteリクエストの発行に)とかに必要
const Schema = mongoose.Schema; // このSchemaは学習不足で理解が足りない
app.use('methodOverride('_method')'); // ミドルウェアの登録、postとgetリクエストしか通常ないためput, deleteを使えるようにするために拡張機能
app.use('express.urlencoded({extended: true}');
// スキーマの作成 typscriptの型定義に似ていると思った
let todoType = new Schema({
_id: Number,
todo: String,
});
// mongodbに接続
mongoose.connect("mongodb://username:password@mongoのservice名:port番号/database名?authSource=admin") // ご自身のdockerで建てたmongooseのurlを
const Todo = mongoose.model('collection名', todoType); // Todoというモデルを作成
// ここにコードを追加します
app.listen(3000);
1: 全データの取得
for文ですべてのデータのaタグを作りそれを表示する
app.get('/', async(req, res) => {
// thenを使ってデータが見つかったときの処理を書く
await Todo.find().then(docs => { // model.find()空にすることですべてを取得できるもしくはfind({})
let data = '';
let(for i = 0; i < docs.length; i++){
data += `a href=edit/${docs[i]._id}>${documents[i]}</a>` // リンクで各リストの詳細に飛べるようにする
}
res.send(`
<a href="/create">Create</a>
${data} // 一覧を表示
`);
}).catch(e => {throw e})
})
全データを表示した写真↓
2: 新規Todoリストを作成するフォームを表示
app.get('/create', (req, res) => {
// res.sendFile(__dirname + '/public/create.html'); // htmlファイルを表示する場合この表記
res.send(`
<form action="/create" method="post">
<input type="text" name="post" id="post">
<button type="submit">submit</button>
</form>
`)
});
app.post('/create', async(req, res) => {
await Todo.find({}).sort({ _id: -1 }).limit(1).then(products => { // 最後のドキュメントのidを取得しid+1でデータを追加している
const newData = new Todo({
_id: products[0]._id + 1,
todo: req.body.post // フォームの値
});
newData.save().then(() => {
res.redirect('/'); // saveしたあとトップページにリダイレクト
});
});
});
新しいアイテム作成用フォームの写真↓
3: アイテム編集用フォームの表示
app.get('/edit/:id', async(req, res) => { // URIは/edit/1, 2などのtodoリストのidが入ります。
let data = await Todo.findOne({_id: req.params.id}); // req.params.idはURIの1,2が入り、idと合致するアイテムを取得する。
res.send(`
<h1>Edit</h1>
${data}
<form action="/edit/${req.params.id}?_method=PUT" method="POST"> // _method=PUTと指定しアイテムを編集できるようにする
<input type="text" name="edit" id="edit">
<button type="submit">Update</button>
</form>
<form action="/delete/${req.params.id}?_method=Delete" method="POST"> // _method=Deleteと指定しアイテムを削除できるようにする
<button type="submit">Delete</button>
</form>
<a href="/">Back</a>
`);
});
app.put('/edit/:id', async(req: express.Request, res: express.Response) => {
await Todo.updateOne({_id: req.params.id}, {todo: req.body.edit}); // idが一致するアイテムを編集
res.redirect('/'); // トップページにリダイレクト
});
アイテム編集フォームの写真↓
アイテム編集後の写真↓
4: リストの削除用のルート
editページから削除するためgetリクエストはいりません
app.delete('/delete/:id', async(req, res) => {
await Todo.deleteOne({_id: req.params.id}); // idが:idと一致するアイテムを削除する
res.redirect('/'); // トップページにリダイレクト
});
deleteした後の写真↓
今回の反省点は公式ドキュメントから調べずに個人技術ブログ,stackoverflowなどから調べ始めたことで、情報が正しいか正しくないかが判別が難しかったこと。
調べる順番を間違ったことで、この簡単なプログラムに2日もかかってしまった。
なのでこれからはまず公式ドキュメントから調べ補足として個人技術ブログ,stackoverflowを使っていこうと思う。
またHTTPリクエスト、レスポンスやExpress、Nodejsについてももっと理解を深めていこうと思う。
参考にしたサイト一覧
-
Expressjsの基礎知識関するサイト
-
環境構築関連
-
express関連
- Express事始め
- expressパッケージとコマンドのインストール
- node.js TypeError: path must be absolute or specify root to res.sendFile [failed to parse JSON]
- Node/Express - Refused to apply style because its MIME type ('text/html')
- Serving a SPA with Express Server Router
- 【Express】静的HTMLファイルの表示(res.sendFile()、express.static())
- Node.jsでルーティングを行う方法と、やってはいけないこと
- Node.js + Express でPOSTデータを取得後、WebAPIへ問い合わせる
- Can I use res.send() node.js method inside the loop?
- How to get id from URL as variable? In Node.js
- method-override`はルーティングの前に読み込む
- Express のレスポンス関連メソッド「res.end()」「res.send()」「res.json()」の違い
-
nodemon関連
-
method-override関連
-
mongoose、Mongodb操作関連
- はじめてのMongoDB with Docker
- MongoDBとMongo-expressをdocker-composeで立ち上げる
- 【Docker】MongoDBをDockerコンテナで構築する
- MongoDBをDockerで構築する!
- Node.js から MongoDB へ 接続 / 操作 する 方法
- Node.js + express + MongoDBでWebAPIを作ってみる
- MongoDBのデータ構造な簡単な操作など
- TypeScriptでMongooseを使うときの落とし穴とその対策
- mongoose で docker でたてた MongoDB に接続するのにはまった話
- Node.jsからMongoDBに接続してみる
- Node.jsとMongoDBの環境をDockerで構築
- Node.js用MongoDBライブラリ mongooseの基本操作まとめ(すぐ試せるサンプル付き)
- How to Find All Documents in Mongoose
- Updating Documents in Mongoose
- How to Delete By Id in Mongoose
- Node.jsでMongoDBへ接続
- Mongoose connection authentication failed
- Using Node.js & Express.js to save data to MongoDB Database
- What is the "__v" field in Mongoose
- mongoDB, mongooseを使ってCRUDを実装する
- How to get last record's one value in mongoose
- How to Use findOneAndUpdate() in Mongoose
Discussion