Node.js 再入門メモ(その 4)

はじめに

かつて、Web アプリケーションを構築する際の定番構成といえば LAMP だったらしい。

近年は、LAMP とともに MEAN という言葉を耳にするようになって久しい。 こちらも Web アプリケーションを構築する際の定番の組み合わせを意味しており、 MongoDB、 Express、 Angular、そして Node.js の頭文字を繋いだものである。

というわけで、今日は Express に挑戦してみる。 最終地点は Express と React を連携させて Hello, World を表示するところまで。

例によって、人様に読んで頂けるような書き方はしていない。 あくまで自分用のメモなので、大して整理もせずロクな解説もない。

Expressとは

公式によると、こういうシロモノらしい。

特定の意見に固執しない、Node.js 向けの高速で最小限の Web フレームワーク

(Fast, unopinionated, minimalist web framework for Node.js)

Node.js の生の API をそのまま叩くよりもいろいろ便利とのことだし、何をするにせよ定番中の定番らしいので触れておいて損は無かろう。

想定環境

今回使用した Node.js と npm のバージョンは以下の通り。

$ node --version
v6.11.2

$ npm --version
5.3.0

また、Express は 4.15.4 を使用している。

前準備(プロジェクトの初期化)

とりあえず、新規に作成したプロジェクトディレクトリに cd して、以下のコマンドを叩く*1

npm init -y
npm install --save express

すると、package.json に以下の依存関係が自動的に登録される。

{
  (中略)
  "dependencies": {
    "express": "^4.15.4"
  }
}

プレーンテキストで Hello, World

まずは肩慣らしに Hello, World をベタで返してみよう。

app.js
const express = require('express')
const app = express()

// パス '/' にアクセスされたら、
// 'Hello, Express' を返す
app.get('/', (request, response) => {
  response.send('Hello, Express')
})

app.listen(3000)

app.js を保存したら以下のコマンドを叩き、 http://localhost:3000 にアクセスすると素敵なことが起こる。

$ node app.js

静的な HTML の表示

今度は、別ファイルの HTML を返す例を試す。

まず、HTML を配置しておくための public ディレクトリを、プロジェクトディレクトリ直下に作る。

$ mkdir public

次に、表示したい HTML を適当に書く。

public/index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta http-equiv="content-type"
    content="text/html; charset=UTF-8">
    <title>Hello!</title>
  </head>
  <body>
    <div id="Content">Hello, Html</div>
  </body>
</html>

Express で静的ファイルを返すには、express.static ミドルウェア関数を使用するらしい。と、公式に書いてある

server.js
const express = require('express')
const app = express()

app.use(express.static(__dirname + '/public'))
app.listen(3000)
実行コマンド
$ node server.js

ブラウザで http://localhost:3000 にアクセスすると、無事 index.html が表示される。

EJS 連携

この調子で EJS との連携も試そう。 ちなみに EJS については前々回少しだけ触れた。

tercel-s.hatenablog.jp

今回使用した EJS のバージョンは 2.5.7 である。

$ npm install --save ejs

テンプレート用の EJS ファイルは views ディレクトリ内に置くことになっているらしいので、とりあえずディレクトリを作っておく。

$ mkdir views
views/index.ejs
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta http-equiv="content-type"
    content="text/html; charset=UTF-8">
    <title><%=title %></title>
  </head>
  <body>
    <p><%=content %></p>
  </body>
</html>

あとは Express 側のコード。 テンプレートエンジンを使う場合は、app.engine前捌きが必要らしい。

app.js
const express = require('express')
const ejs = require('ejs')
const app = express()

// 第1引数: レンダリング対象の拡張子
// 第2引数: レンダリング用の関数
app.engine('ejs', ejs.renderFile)

app.get('/', (request, response) => {
  response.render('index.ejs',
    {
      title: 'Express + EJS',
      content: 'Hello, Express + EJS'
    })
})

app.listen(3000)

これも、以下のコマンドで実行できる。

$ node app.js

React と連携

最後に React 連携。 これは足回りの整備が少々手強い。

React ほか諸々のインストール

まずは React まわりのモジュールをインストールする。 BabelWebpack も入れる。

$ npm i --save react react-dom
$ npm i --save-dev webpack
$ npm i --save-dev babel-loader babel-core
$ npm i --save-dev babel-preset-es2015 babel-preset-react

ひととおりインストールが完了すると、package.json の依存モジュールはこんな感じになるはず。

package.json (抜粋)
{
  (中略)
  "dependencies": {
    "express": "^4.15.4",
    "react": "^15.6.1",
    "react-dom": "^15.6.1"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "webpack": "^3.5.5"
  }
}
ディレクトリの作成

次に、プロジェクトディレクト直下に 2 つのディレクトリを作る。

mkdir public src

src はビルド前のソース(JSX とか)を置くためのディレクトリ、public はビルド後のファイルが配置されるディレクトリだ。

続いて Webpack の設定を行う。 ここは、いつまで経ってもソラで書けるようになる気がしない。

webpack.config.js
const path = require('path')
module.exports = {
  entry: path.join(__dirname, 'src/index.js'),  // ソースファイル
  output: {
    path: path.join(__dirname, 'public'),       // 出力ディレクトリ
    filename: 'app.js'                          // 出力ファイル名
  },
  devtool: 'inline-source-map',
  module: {
    rules:[
      {
        test: /.js$/,           // ファイルのパターン
        loader: 'babel-loader', // 使用するプラグイン
        options: {              // プラグインのオプション
          presets: ['es2015', 'react']
        }
      }
    ]
  }
}

続いてクライアントサイドの実装。 ここは何の変哲もない React のコードだ。

public/index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta http-equiv="content-type"
    content="text/html; charset=UTF-8">
    <title>Hello!</title>
  </head>
  <body>
    <div id="Content"></div>
    <script src="./app.js"></script>
    <!-- src/index.js はビルド後に app.js になる -->
  </body>
</html>
src/index.js
import React from 'react'
import ReactDOM from 'react-dom'

const App = () => <div>Hello, React</div>

ReactDOM.render(<App />, document.getElementById('Content'))

最後にサーバサイドの実装。 これは先ほどの HTML の表示の例と全く同一である。

server.js
const express = require('express')
const app = express()

app.use(express.static(__dirname + '/public'))
app.listen(3000)
ビルド

ターミナル上で以下のコマンドを叩く。

$ $(npm bin)/webpack

成功すると、ターミナルにだいたいこんな表示が出る。

Hash: 5dadee6372365c90c227
Version: webpack 3.5.5
Time: 7827ms
 Asset     Size  Chunks                    Chunk Names
app.js  2.41 MB       0  [emitted]  [big]  main
  [81] ./src/index.js 503 bytes {0} [built]
    + 183 hidden modules

続いてサーバを起動。

$ node server.js

ブラウザに「Hello, React」と表示されたら成功。

*1:ちなみに Visual Studio Code を使用している場合は Ctrl + Shift + @ で統合ターミナルが開く。べんり。