Help us understand the problem. What is going on with this article?

Node.jsとExpressでローカルサーバーを構築する(2) ―Expressでルーティング―

More than 1 year has passed since last update.

リンク一覧

  1. Node.jsとExpressでローカルサーバーを構築する(1) ―Node.jsとnpmの導入―
  2. Node.jsとExpressでローカルサーバーを構築する(2) ―Expressでルーティング―(本記事)
  3. Node.jsとExpressでローカルサーバーを構築する(3) ―JSONを返すスタブAPI―
  4. Node.jsとExpressでローカルサーバーを構築する(4) ―他サーバーから画像を取得する―

概要

この記事の概要

  • 目的
    • Node.jsとExpressを利用して、PC上にローカルサーバーを立ち上げる
  • 本記事のゴール
    • ブラウザで「localhost:8080」にアクセスすると、HTMLファイルが取得できる
    • HTMLファイルからリンクしている、CSS,JS,IMGファイルも取得できる
  • 対象者
    • WEBフロント担当者
    • HTML,CSS,JavaScript(es2015含む)の基本的な構文を理解している人
    • HTTP通信、GET、POSTなどについて、ある程度理解している人(ざっくりで良いです)
    • 黒い画面にコマンドを打ち込むことに抵抗がない方
  • 環境・バージョン
    • Windows10
    • Node.js(推奨版) 10.15.01
    • npm 6.4.1
    • Express 4.16.4

フレームワークの利用

Node.jsのコアモジュールは、最低限の機能に留めた簡素なものです。
リクエストに対して適切なレスポンスを選択するルーティング作業などを一から書くのは少々面倒そうなので、Expressというフレームワークを利用したいと思います。
webアプリケーションを構築するのに便利なものがいろいろ詰まっており、公式サイトは一応日本語版も存在します!(2019年2月現在、APIリファレンスは翻訳されていません)
Express(日本語)

なお、Eexpressを利用したWEBアプリを制作する際の雛形を生成してくれる、express-generatorなる便利ツールが存在します。
ざっくりと仕組みを把握したら、次からはそういったツールを利用して構築すると良いかと思います。
Express のアプリケーション生成プログラム
今回は、単純に予め用意された静的ファイルを返すだけの機能しか求めていないので、見送ります。

Expressのインストール

npmを利用してインストールします。
プロジェクトの作業用フォルダに移動して、下記コマンドを実行します。
npmさん、expressをインストールしてください。その際、package.jsonに記帳してください。」

$ npm install express --save

--saveが、package.jsonへの書き込みを指示するコマンドです。
インストールが無事完了すると、package.jsonは下記のようになります。

{
  "name": "sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.16.4"
  }
}

dependencies(依存関係)の項目に、expressの名前とインストールしたバージョンが記載されています。
そして、作業フォルダ内にnode_modulesというフォルダが出現しています。
このプロジェクト用にインストールしたパッケージのファイル群は、ここへ格納されます。
もう一つ、package-lock.jsonというファイルも作成されています。
このファイルは依存関係をもっと厳密に管理するためのものですが、とりあえず放っておきましょう。(削除はしないで)
気になる方はこちらの質問の回答をご覧ください。
npm-package-lock-json-がなぜ必要なのかがわからない | stackoverflow

devDependencies
上記では、dependenciesに記録されていますが、よく似た名前のdevDependenciesという項目もあります。
本記事では一貫してdependenciesのみ扱いますが、npmインストールに関する記事ではdevDependenciesもよく登場しますので、下記記事を一読されることをお勧めします。
【いまさらですが】package.jsonのdependenciesとdevDependencies - Qiita

サーバーを構築する

フォルダとファイルの準備

まずは、静的ファイルたちを用意しておきましょう。作業フォルダに以下の構成でフォルダとファイルを準備します。

sample/
  ├ public/
  │    ├ css/
  │    │   └ sample.css 
  │    ├ js/
  │    │   └ sample.js 
  │    ├ img/
  │    │   └ sample.png 
  │    └ index.html
  └ app.js

/public/index.htmlには、css・js・imgファイルへのリンクを貼っておきます。(ルートパスで)

<!DOCTYPE html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>TEST</title>
    <link rel="stylesheet" href="/css/sample.css">
  </head>

  <body>
    <h1>Hello World!</h1>
    <p id="hoge"></p>
    <div>
      <img src="/img/sample.png">
    </div>
    <script src="/js/sample.js"></script>
  </body>
</html>

/public/css/sample.css/public/js/sample.jsにて、適当なコードを記述します。

/* /public/css/sample.css */
h1 {
  font-size: 1.5rem;
  color: #0000ff;
}
img {
  max-width: 100%;
}
/* /public/js/sample.js */
{
  const el = document.getElementById('hoge');
  el.innerText = 'HAHAHAHAHAHAHA!!!!';
}

WEBサーバーのアプリケーションファイルを作成する

app.jsファイルの概要

/app.jsにサーバーの処理を記述していきます。

/**
 * /app.js
 */ 
// express モジュールのインスタンス作成
const express = require('express');
const app = express();
// パス指定用モジュール
const path = require('path');

// 8080番ポートで待ちうける
app.listen(8080, () => {
  console.log('Running at Port 8080...');
});

// 静的ファイルのルーティング
app.use(express.static(path.join(__dirname, 'public')));

// その他のリクエストに対する404エラー
app.use((req, res) => {
  res.sendStatus(404);
});

先ほどインストールしたexpressのモジュールを読み込みます。
httpモジュールではhttp.createServerメソッドでサーバを生成していましたが、expressは読み込んだモジュールをそのまま実行して、生成しています。

const express = require('express');
const app = express();

そして生成されたサーバオブジェクトのlistenメソッドを実行してリクエストの受付を開始します。
1番目の引数はポート番号、2番目の引数は開始後のコールバック関数です。

app.listen(8080, () => {...

公式ガイド:Express Hello Worldの例

Expressでルーティング

ここまではhttpモジュールを利用した場合とそう変わりません。次のコードで、Expressを利用したルーティングを行っています。

app.use(express.static(path.join(__dirname, 'public'))));

useメソッド
useメソッドはルーティグを行うミドルウェア(中間処理を行う関数)を受け取ります。自分で書くことも出来ますが、ここではexpressの静的メソッドstaticを利用します。
このメソッドに、静的ファイル群のルートパスとなるフォルダのパスを渡すと、その配下に格納されているファイルに対するリクエストを、よしなに捌いてくれるミドルウェアを生成してくれます。

pathモジュール
staticメソッドに引き渡しているところで利用しているpathモジュールは、Node.jsのコアモジュールです。ファイルパスの文字列を操作するためのツールが含まれています。ファイル自体の操作は出来ません。
node.jsでパスの操作 | 山本隆の開発日誌
公式リファレンス:Path(英語)

__dirname
__dirnameは、Node.jsで用意されている事前読み込み不要のモジュールで、記述されたファイルのパスを返します。
app.jsC:/sample/app.jsにある場合、C:/sampleが返ってきます。
そしてそのパスと、静的ファイルが格納されているフォルダ名publicpath.joinメソッドでつなげて完全なパス文字列C:/sample/publicを生成しています。

整理をすると、

  1. publicフォルダまでのパス文字列を作成
  2. 1.の文字列をexpress.staticメソッドに渡して静的ファイルをルーティングするミドルウェアを作成
  3. 2.のミドルウェアをapp.useメソッドに渡して、8080へのアクセス時に利用されるようにする

これによりpublic/が実質サイトのルートとなります。
そのため、localhost:8080/へのアクセスは、public/直下のindex.htmlが返されます。
ルートパスで/common/css/sample.cssと指定すると、C:/sample/public/common/css/sample.cssが返されます。

ここではstaticに丸投げしていますが、もっと細かく「このパスの場合はこのフォルダ」と指定することも可能です。
第一引数に該当のサイトパス、第二引数にミドルウェアを渡します。

app.use(`/fuga/piyo`, express.static(path.join(__dirname, 'moi'))));

上記の例では、/fuga/piyoへアクセスするとmoi/フォルダのファイルが返ってきます。

公式ガイド:ルーティング
公式ガイド:Expressでの静的ファイルの提供

404Not Found

最後のコードは、該当ファイルが存在しないときに404エラーを返すように設定しています。「Not Found」の文字列を返すだけの簡素なものです。

公式リファレンス:res.sendStatus(英語)[]()

動作確認

では、コマンドプロンプト上で下記コマンドを実行します。(作業用フォルダに移動した上で)
「nodeさん、app.jsファイルを実行してください!」

$ node app.js

これでサーバーが立ち上がりました。コンソールにRunning...と出力されていると思います。
そして、ブラウザよりlocalhost:8080へアクセスしてみます。

localhost02.gif

無事にレスポンスを受け取れました!!
CSS、JS、IMGファイルも実行結果から読み込めていることが分かりますね。

終了する場合は、サーバーを立ち上げるコマンドを実行したコマンドプロンプト上でCtrl+Cを入力して、プロセスを終了させます。
サーバー起動中は、起動させたコマンドプロンプト上で別のコマンドを入力することは出来ません。新たにもうひと窓開いてください。

初心者の拙い記事を読んでいただき、ありがとうございました。お役に立てていたら幸いです。
次回は、JSONデータを返すAPIを実装していきたいと思います。

参考情報

Express公式サイト(英語)
Node.jsとExpressでWeb APIを作ってみよう

koedamon
WEBフロント
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away