Express.jsとは
Express.jsは、Node.jsのための軽量で柔軟なWebアプリケーションフレームワークです。
Express.jsを使用すると、Node.jsを使用してWebアプリケーションを作成するための様々な機能を簡単に実装できます。
MVCアーキテクチャを採用し、ルーティング、テンプレートエンジン、ミドルウェア、セッション、Cookieの処理、静的ファイルの提供、データベースの操作など、Webアプリケーション開発に必要な基本的な機能を提供しています。
また、豊富なサードパーティーモジュールを使用することで、より高度な機能を追加することも可能です。
Express.jsの使い方
事前準備
Node.jsをインストールし、npmを使用できる環境を作っておく必要があります。
>node -v
v14.16.0
>npm -v
6.14.11
環境構築
1. プロジェクトの作成
新しいディレクトリを作成し、そのディレクトリでnpmプロジェクトを初期化します。
>mkdir my-express-project
>cd my-express-project
>npm init --yes
Wrote to C:\【path】\my-express-project\package.json:
{
"name": "my-express-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
2. Express.jsのインストール
npmを使用して、以下のコマンドを実行してExpress.jsをインストールします。
>npm install express
+ express@4.18.2
added 57 packages from 42 contributors and audited 57 packages in 2.353s
7 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
3. サーバーの作成
index.js
ファイルを作成して、以下コードを作成します。
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
package.json
にstartコマンドを追加します。
{
"name": "my-express-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2"
}
}
動作確認
1. サーバ起動
以下のコマンドを実行してサーバを起動します。
>npm start
> my-express-project@1.0.0 start C:\【path】\my-express-project
> node index.js
Server listening on port 3000
2. サーバ確認
curl
コマンドを使用してサーバの実行を確認します。
>curl http://localhost:3000
Hello World!
3. サーバ停止
ctrl + c
でサーバを停止できます。
(Macでは control + c
)
ルーティング
Express.jsにおけるルーティングとは、HTTPリクエストのURLに応じて、アプリケーション内で実行する処理を決定する仕組みです。ルーティングは、HTTPメソッド(GET、POST、PUT、DELETEなど)とURLパターンによって定義されます。
Express.jsでは、app.【HTTPメソッド名】()
関数を使用してルートを定義します。
app.get()
、app.post()
、app.put()
、app.delete()
などのHTTPメソッドに対応した関数を使用することができます。
以下は、GETリクエストのルートを定義する例です。
app.get('/', function (req, res) {
res.send('Hello World!')
})
上記の例では、ルートに対するGETリクエストを定義しています。
ルートに対するリクエストが発生した場合、第2引数に指定されたコールバック関数が呼び出されます。
この関数内で、レスポンスを返すための処理を行います。
各コールバック関数の第1引数 req
はリクエストオブジェクト、第2引数 res
はレスポンスオブジェクトです。
また、URLパラメータを使用して、動的なルートを定義することもできます。
app.get('/users/:id', function (req, res) {
res.send('User ID: ' + req.params.id)
})
この例では、/users/:id
というパスを定義しています。
:id
はURLパラメータで、リクエストURLに含まれる任意の文字列にマッチします。
このURLパラメータは、req.params
オブジェクトを介して取得することができます。
また、複数のハンドラ関数を使用して、ルートに対する処理を定義することもできます。
app.get('/users/:id', function (req, res, next) {
// ミドルウェアの処理
next()
}, function (req, res) {
res.send('User ID: ' + req.params.id)
})
この例では、2つのハンドラ関数を使用しています。
最初のハンドラ関数は、リクエストに対するミドルウェアの処理を行います。
このミドルウェアの処理が完了した後、次のハンドラ関数が実行され、レスポンスが返されます。
Express.jsのルーティングを用いてREST APIを実装することができます。
REST APIとは
REST (Representational State Transfer) APIは、Webサービスを開発するためのアーキテクチャスタイルの1つで、HTTPプロトコルを使用してWeb上でのデータのやりとりを行うための方法論です。
REST APIでは、リソースを一意の識別子(URI)によって表現し、HTTPメソッド(GET、POST、PUT、DELETEなど)を使用してリソースに対して操作を行います。
HTTPメソッド | 操作 |
---|---|
GET | リソースを取得する |
POST | リソースを作成する |
PUT | 指定したIDのリソースを更新する |
DELETE | 指定したIDのリソースを削除する |
REST API実装
index.js
を以下のように修正すると、 GET
, POST
, PUT
, DELETE
のHTTPメソッドを使用してリクエストを処理するようにできます。
const express = require('express');
const app = express();
// GETリクエスト
app.get('/', (req, res) => {
res.send({
msg:'GET request'
});
});
// POSTリクエスト
app.post('/', (req, res) => {
res.send({
msg:'POST request'
});
});
// PUTリクエスト
app.put('/:id', (req, res) => {
res.send({
id: req.params.id,
msg:'PUT request'
});
});
// DELETEリクエスト
app.delete('/:id', (req, res) => {
res.send({
id: req.params.id,
msg:'DELETE request'
});
});
app.listen(3000, () => {
console.log('Server started on port 3000');
});
curl
コマンドを使用してサーバの実行を確認できます。
>curl -X GET http://localhost:3000/
{"msg":"GET request"}
>curl -X POST http://localhost:3000/
{"msg":"POST request"}
>curl -X PUT http://localhost:3000/123
{"id":"123","msg":"PUT request"}
>curl -X DELETE http://localhost:3000/123
{"id":"123","msg":"DELETE request"}
ミドルウェア
Express.jsにおけるミドルウェアとは、HTTPリクエストとレスポンスの間に挟まる処理を指します。
ミドルウェアは、アプリケーション全体で共通の処理や、特定のルートで実行する必要がある処理などに使用されます。
Express.jsでは、app.use()
関数を使用してミドルウェアを登録します。
登録されたミドルウェアは、HTTPリクエストが発生するたびに呼び出されます。
ミドルウェアの実装方法は、以下のようになります。
// ミドルウェアの実装
const myMiddleware = function(req, res, next) {
// ミドルウェアの処理
next(); // 次のミドルウェアへ処理を移す
};
// ミドルウェアの登録
app.use(myMiddleware);
このように、app.use()
関数に登録するミドルウェア関数には、req
、res
、next
という3つの引数が渡されます。
req
はリクエストオブジェクト、res
はレスポンスオブジェクト、next
は次のミドルウェア関数へ処理を移すための関数です。
ミドルウェア実装
index.js
を以下のように修正すると、 HTTPリクエストのメソッドとURLをログに出力するようにできます。
const express = require('express');
const app = express();
const loggerMiddleware = function(req, res, next) {
console.log(`[${new Date()}] ${req.method} ${req.url}`);
next();
};
app.use(loggerMiddleware);
// GETリクエスト
app.get('/', (req, res) => {
res.send({
msg:'GET request'
});
});
// POSTリクエスト
app.post('/', (req, res) => {
res.send({
msg:'POST request'
});
});
// PUTリクエスト
app.put('/:id', (req, res) => {
res.send({
id: req.params.id,
msg:'PUT request'
});
});
// DELETEリクエスト
app.delete('/:id', (req, res) => {
res.send({
id: req.params.id,
msg:'DELETE request'
});
});
app.listen(3000, () => {
console.log('Server started on port 3000');
});
curl
コマンドを使用してサーバの実行を確認できます。
>curl -X GET http://localhost:3000/
{"msg":"GET request"}
>curl -X POST http://localhost:3000/
{"msg":"POST request"}
>curl -X PUT http://localhost:3000/123
{"id":"123","msg":"PUT request"}
>curl -X DELETE http://localhost:3000/123
{"id":"123","msg":"DELETE request"}
上記コマンド実行時にサーバ側のコンソールで以下のログが表示されます。
[Sun Mar 19 2023 01:42:24 GMT+0900 (日本標準時)] GET /
[Sun Mar 19 2023 01:42:29 GMT+0900 (日本標準時)] POST /
[Sun Mar 19 2023 01:42:34 GMT+0900 (日本標準時)] PUT /123
[Sun Mar 19 2023 01:42:39 GMT+0900 (日本標準時)] DELETE /123
静的ファイル
Webアプリケーションでは、静的ファイル(画像、CSS、JavaScriptなど)を扱うことが一般的です。
以下では、Express.jsで静的ファイルを扱う方法について解説します。
静的ファイルの配置場所を指定する
まず、静的ファイルが配置されている場所を指定する必要があります。
Express.jsでは、express.static
ミドルウェアを使用して、静的ファイルのディレクトリを指定できます。
例えば、以下のように記述することで、publicディレクトリ内の静的ファイルを使用できます。
app.use(express.static('public'))
ルーティングの設定による静的ファイルの提供
ルーティングを設定して、public/imagesディレクトリ内のファイルを提供しています。
options
オブジェクトには、ファイル送信時の設定が含まれています。
fileName
には、リクエストパラメータのファイル名が格納されます。
app.get('/images/:filename', function(req, res) {
var options = {
root: __dirname + '/public/images/',
dotfiles: 'deny',
headers: {
'x-timestamp': Date.now(),
'x-sent': true
}
};
var fileName = req.params.filename;
res.sendFile(fileName, options, function (err) {
if (err) {
next(err);
} else {
console.log('Sent:', fileName);
}
});
});
この例では、/images/:filenameというパスに対して、public/imagesディレクトリ内のファイルを提供するルーティングを設定しています。
options
オブジェクトには、ファイル送信時の設定が含まれています。
root
には、ファイルのルートディレクトリを指定します。
dotfiles
には、ドットで始まるファイルの扱い方を指定します。
この例では、denyを指定して、ドットで始まるファイルを送信しないようにしています。
headers
には、レスポンスヘッダーを指定します。この例では、x-timestampとx-sentを指定しています。
fileName
には、リクエストパラメータのファイル名が格納されます。res.sendFile
メソッドを使用して、ファイルを送信します。
送信が完了したら、コールバック関数が実行されます。エラーが発生した場合は、next関数にエラーを渡します。
静的ファイルのキャッシュ
Express.jsでは、静的ファイルのキャッシュ機能を提供しています。キャッシュを使用することで、同じファイルに対して複数のリクエストがあった場合でも、サーバーからのレスポンス時間を短縮することができます。
キャッシュを有効化するには、maxAge
オプションを使用します。以下は、キャッシュを有効化する例です。
app.use(express.static('public', { maxAge: 86400000 }));
maxAge
には、キャッシュの有効期限をミリ秒単位で指定します。上記の例では、1日間キャッシュを有効化しています。
キャッシュを有効化することで、同じファイルに対して複数回のリクエストがあった場合でも、サーバーからのレスポンス時間を短縮することができます。
ただし、キャッシュ期間が長すぎると、ファイルの変更が反映されない場合があるので、適切な期間を設定する必要があります。
静的ファイルの実装
index.js
を以下のように修正すると、 /test-image
パスにアクセスして public/images/test.png
が返却するようにできます。
const express = require('express');
const app = express();
const path = require('path');
const loggerMiddleware = function(req, res, next) {
console.log(`[${new Date()}] ${req.method} ${req.url}`);
next();
};
app.use(loggerMiddleware);
// 静的ファイルの提供とキャッシュの有効化
app.use(express.static('public', { maxAge: 86400000 }));
// test-imageリクエスト
app.get('/test-image', (req, res) => {
res.sendFile(path.join(__dirname, 'public/images/test.png'));
});
// GETリクエスト
app.get('/', (req, res) => {
res.send({
msg:'GET request'
});
});
// POSTリクエスト
app.post('/', (req, res) => {
res.send({
msg:'POST request'
});
});
// PUTリクエスト
app.put('/:id', (req, res) => {
res.send({
id: req.params.id,
msg:'PUT request'
});
});
// DELETEリクエスト
app.delete('/:id', (req, res) => {
res.send({
id: req.params.id,
msg:'DELETE request'
});
});
app.listen(3000, () => {
console.log('Server started on port 3000');
});
このコードでは、/test-image
パスにアクセスするとpublic/images/test.png
が返却されます。
path.join(__dirname, 'public/images/test.png')
を使用して、現在のディレクトリからの相対パスでファイルを指定しています。
localhost:3000/test-imageにアクセスしてサーバの実行を確認できます。
GitHub
今回の記事で紹介したソースコードをGitHubで公開しています。