Node.js
Express
70
どのような問題がありますか?

この記事は最終更新日から3年以上が経過しています。

投稿日

更新日

Organization

Express(Node.js)チュートリアル

概要

  • MDNのExpressについてのチュートリアルを参考にまとめてみました。
  • Nodeのインストールについては、別の記事をみてください。

まずNode.jsについて

  • JavaScriptのサーバーサイドのツールかつアプリケーション。
  • JavaScriptはブラウザ上で動くイメージがあるが、サーバサイドもかける!!
  • ブラウザ用のAPIは取り除き、OS用のAPI(ファイルへのアクセスとか)やHTTP用のAPI群を持っている。

Node.jsのウェブサーバとしての利点

  • スループットとスケーラビリティを持っている。
  • ブラウザとサーバサイド両方ともJavaScriptで記述できる。
  • node package manager (NPM) を利用すれば、優れたパッケージを再利用できる。パッケージの依存関係なども扱える。楽。

簡単なwebサーバのコード例

  • 以下で簡単にNodeのHTTPモジュールで、ウェブサーバを起動できる。
app.js
// Httpのモジュールの読み込み
var http = require("http");

// 8000番ポートでHTTPサーバ起動
http.createServer(function(request, response) {

   // レスポンスで返すHTTP header(with HTTP status Content type)
   response.writeHead(200, {'Content-Type': 'text/plain'});

   // レスポンスで返すbody
   response.end('Hello World\n');
}).listen(8000);

// 起動ログ
console.log('Server running at http://127.0.0.1:8000/');
// サーバプロセス起動
$ node app.js

http://127.0.0.1:8000/
にアクセスすると、HelloWorldのテキストが返されます。

Expressについて

  • ExpressはもっともポピュラーなNodeのウェブフレームワーク。
  • 他の有名なNodeのウェブフレームワークの元にもなっている。
  • 以下の仕組みを提供する。

    • リクエストに対して、異なるURLパスで、HTTP verbsと共にハンドラーを書く。
    • "view" というrendering enginesをよく利用する。(GUIを伴う場合)
    • テンプレートの場所や、ポートなどの一般的なwebアプリケーションの設定を扱う。
    • リクエストを扱う過程で、"middleware"という付加的なリクエスト処理を加えることができる。(middle ware pattern)
  • Expressのmiddlewareとして、たくさんのライブラリが作られている。

    • cookies, sessions, user logins, URL parameters, POST data, security headersなどを扱うライブラリ

HelloWorld Express(簡単に使ってみる)

  • ExpressでHelloWorld。
app.js
const express = require('express');
const app = express();

app.get('/', function(req, res) {
  res.send('Hello World!');
});

app.listen(8000, function() {
  console.log('Example app listening on port 8000!');
});
  • app(慣例の名前付け)のオブジェクトは、アプリケーションの振る舞いの操作に関するメソッドを持つ。

    • HTTPルーティングのメソッド
    • middlewareの設定
    • viewのレンダリング
    • テンプレートエンジンの登録
    • アプリケーションの設定変更など
  • app.get()

    • 「/」のパスにアクセスされるたびに呼び出されるコールバック関数(functionの部分)を定義する。
    • コールバック関数はrequestとresponseを引数として持ち、responseでsend()を呼び出すことで、「Hello World!」を返す。

Node.jsのモジュールについて

  • モジュールはJavaScriptのライブラリで、require()関数でインポート可能。
  • Express自体もモジュールで、ExpressアプリケーションでDBやミドルウェアのライブラリを利用可能。
  • メンテナンスの観点から、自作でモジュールを作りたくなるはず。

  • 以下のようにexportsすることでmoduleとして利用できる。

square.js
exports.area = function(width) { return width * width; };
exports.perimeter = function(width) { return 4 * width; };
  • インポートはこう。
app.js
var square = require('./square'); // Here we require() the name of the file without the (optional) .js file extension
console.log('The area of a square with a width of 4 is ' + square.area(4));
  • module.exportsを使うことで、一度にオブジェクトとしてexport可能。
square.js
module.exports = {
    area: function(width) {
        return width * width;
    },

    perimeter: function(width) {
        return 4 * width;
    }
};

非同期APIについて

  • JavaScriptは同期処理APIより非同期処理APIの方がよく利用される。
  • Nodeはシングルスレッドで動く。
    • シングルスレッドということは全てのサーバへのリクエストを一つのスレッドで捌く。
    • これはスピードとルーティングの観点で利点があるが、同期的な関数を実行して、時間がかかるとパフォーマンスに大きく影響する。
  • 非同期処理APIの完了通知を受ける方法はいくつかある。
    • もっとも一般的な方法は、完了時に呼び出されるコールバック関数を登録すること。
  • 時々コールバック地獄(ネストしまくること)にハマるが、減らせる解決方法もあるので調べること。(Promiseとか)

route handlers

  • Hello Worldの例で、ルーティングメソッド(get)でコールバックを実装したが、send()の他にもレスポンス用のメソッドがある。
    • res.json()
    • res.sendFile()
  • 参考: https://expressjs.com/en/guide/routing.html#response-methods

  • もちろんgetの他にもルーティングメソッドが用意されている(HTTP verbsに対応するもの)

    • post(), put(), delete() etc
  • app.all()という特別なルーティングメソッドもある

    • すべてのHTTP methodのレスポンスで呼ばれる
app.js
app.all('/secret', function(req, res, next) {
    console.log('Accessing the secret section ...');
    next();  // pass control to the next handler
    });
  • グループルーティングのハンドラーも便利。(express.Router)
    • 例: a site with a Wiki might have all wiki-related routes in one file and have them accessed with a route prefix of /wiki/
wiki.js
// wiki.js - Wiki route module

const express = require('express');
const router = express.Router();

// Home page route
router.get('/', function(req, res) {
    res.send('Wiki home page');
    });

// About page route
router.get('/about', function(req, res) {
    res.send('About this wiki');
    });

module.exports = router;
  • ふたつのrouterができている。
    • '/wiki/'
    • '/wiki/about/'
app.js
const wiki = require('./wiki.js');
const express = require('express');
const app = express();

app.use('/wiki', wiki);

app.listen(8000, () => {
    console.log('Example app listening on port 8000');
});

middlewareを使う

  • MiddlewareはExpressアプリの中で多岐に渡り利用される。
    • 静的ファイルのサービングや、エラーハンドリングetc
  • route関数はHTTPのリクエストレスポンスのサイクルを、HTTPクライアントになにかしらを返して終わらせるが、middleware関数は大抵リクエスト中、レスポンス中に何かしらの処理を実行し、次の関数(middlewareとかhandlerとか)を呼び出す。
  • middlewareが呼ばれる順番は開発者次第。
  • サイクルを終了させない場合は、next()メソッドを呼んで、次のmiddleware関数にコントロールを渡さなければならない。そのままあとリクエストがhangingするから注意。

  • 多くのアプリはthird-partyのmiddlewareを利用するはず。

    • できるだけcookieやlogging, sessionなどめんどくさいことは簡潔にしたいから。
  • third-partyのmiddlewareを利用するにはまずNPMでインストール必須。

例: morgan(HTTPリクエストのlogger middleware)

まずインストール

$ npm install morgan

use()を呼ぶことでmiddlewareを追加する

app.js
var express = require('express');
var logger = require('morgan');
var app = express();
app.use(logger('dev'));
...
  • (Note): middlewareとrouting関数は宣言された順番に呼ばれる。

    • middlewareの中には呼ばれる順番が重要なものがあるので注意。
      • session middleware はcokie middlewareに依存する→cookie middlewareを先に呼ばなければならない
  • 自分でmiddlewareを作成できる。

  • middleware functionとroute handler callbackの違いは、middlewareは3つ目の引数nextを持つ。

  • app.use()もしくはapp.add()で連鎖的にmiddlewareを追加できる。

    • 追加の仕方は、「middlewareをすべてのレスポンスに適用したいか」もしくは「特定のHTTPverb(GET,POST etc)のレスポンスに適用したいか」で変わってくる
    • どちらの場合でも、app.use()を呼ぶ際にroutesを明示する必要がある。routeはオプションだけど。
app.js
const express = require('express');
const app = express();

// middleware functionの例
const a_middleware_function = function(req, res, next) {
    // ... ここで何かしらの処理
    console.log('a_middleware_functionが呼ばれた');
    next();
}

// Function added with use() for all routes and verbs
app.use(a_middleware_function);

// Function added with use() for a specific route
app.use('/someroute', a_middleware_function);

// A middleware function added for a specific HTTP verb and route
app.get('/', a_middleware_function);

app.listen(8000);

databasesの利用

  • ExpressはNodeが使えるdatabaseなら利用可能。
    • PostgreSQL, MySQL, Redis, SQLite, MongoDB, etc.
  • npmでdriverを入れる必要がある。
$ npm install mongodb
ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
marchin_1989
Android Developer
yumemi
みんな知ってるあのサービスも、ゆめみが一緒に作ってます。スマホアプリ/Webサービスの企画・UX/UI設計、開発運用の内製化支援。Swift, Kotlin, PHP, Vue.js, React.js, Node.js, AWS等エンジニア・クリエイターの会社です。Twitterで情報配信中https://twitter.com/yumemiinc
この記事は以下の記事からリンクされています

コメント

この記事にコメントはありません。
あなたもコメントしてみませんか :)
ユーザー登録
すでにアカウントを持っている方はログイン
70
どのような問題がありますか?
ユーザー登録して、Qiitaをもっと便利に使ってみませんか

この機能を利用するにはログインする必要があります。ログインするとさらに下記の機能が使えます。

  1. ユーザーやタグのフォロー機能であなたにマッチした記事をお届け
  2. ストック機能で便利な情報を後から効率的に読み返せる
ユーザー登録ログイン
ストックするカテゴリー