express-generatorで生成したapp.js のコードを1行ずつ解読

express-generatorで生成したテンプレートのapp.jsのコードを日本語訳する。

コードの意味を解説している記事や公式ドキュメントを参照しながら、できる限り噛み砕いてクドイ言い回しで解釈していく。

>勉強中の関連記事まとめ
>[自分用の勉強記事をまとめた目次　~擬似知識体系~](https://qiita.com/oekaki-hoho-ron/items/3194f560efc461ec03b0)

#勉強に必要な準備

使用するPCに以下のパッケージがインストールされているものとする。

- npm
- Node.js
- Express.js
- express-generator

###勉強に使ったExpressのバージョン確認

```.zsh
$ express --version
4.16.1
```

###テンプレートファイルの生成

```.zsh
$ express myapp
```
###生成されたテンプレートのapp.jsの中身

```app.js
 1 var createError = require('http-errors');
 2 var express = require('express');
 3 var path = require('path');
 4 var cookieParser = require('cookie-parser');
 5 var logger = require('morgan');
 6
 7 var indexRouter = require('./routes/index');
 8 var usersRouter = require('./routes/users');
 9
10 var app = express();
11
12 // view engine setup
13 app.set('views', path.join(__dirname, 'views'));
14 app.set('view engine', 'jade');
15
16 app.use(logger('dev'));
17 app.use(express.json());
18 app.use(express.urlencoded({ extended: false }));
19 app.use(cookieParser());
20 app.use(express.static(path.join(__dirname, 'public')));
21
22 app.use('/', indexRouter);
23 app.use('/users', usersRouter);
24
25 // catch 404 and forward to error handler
26 app.use(function(req, res, next) {
27   next(createError(404));
28 });
29
30 // error handler
31 app.use(function(err, req, res, next) {
32   // set locals, only providing error in development
33   res.locals.message = err.message;
34   res.locals.error = req.app.get('env') === 'development' ? err : {};
35
36   // render the error page
37  res.status(err.status || 500);
38   res.render('error');
39 });
40
41 module.exports = app;
```

#require部分（1~10行）

###1行目

```.js
 1 var createError = require('http-errors');
```

1行目の`var createError = require('http-errors');`は、npmレジストリから入手できるNode.jsモジュールの`http-errors`を`app.js`に読み込んでいる。`createError`という変数に`http-errors`モジュールを`require()`で読み込んで格納している。http-errorモジュールによって404などのhttpエラーを簡単に作成できる。

ここで読み込んでいる`http-error`モジュールはいつのまに用意されていたのかと言うと、`express-generator`でテンプレート生成したときにまとめて用意されている。

>参考文献
>[http-errors （公式ドキュメント）](https://www.npmjs.com/package/http-errors)

`require()`で読み込むファイルパスが省略されてモジュール名だけで済んでいるのは、`require()`の仕組みとして検索優先度があって`node_module/`は優先度が高い検索領域だからパスを記述しなくても見つけてくれる。

>参考文献
>[Node.jsのrequireの検索パス](https://qiita.com/aosho235/items/684cccc64e72b9d714e1)

###2行目

```.js
 2 var express = require('express');
```

2行目の`var express = require('express');`は、`node_module/`にある`express`モジュールを読み込んで変数`express`に格納している。expressモジュールは`express-generator`のテンプレートに最初から含まれている。

expressモジュールとは、Node.jsで[MVC](https://qiita.com/tentom/items/de95f63bc9e2da2bd0bf)を容易に実現するのに必要なコードが書かれたフレームワーク。

>参考文献
>[Node.js モジュール追加（Express）](https://qiita.com/nissato/items/59b4ea744faf9d112d83)
>[MVC とは何かを 1 から学ぶ](https://qiita.com/tentom/items/de95f63bc9e2da2bd0bf)

###3行目

```.js
 3 var path = require('path');
```

3行目の`var path = require('path');`は、Node.jsの標準モジュールの一つである`path`モジュールを読み込んでいる。

pathモジュールとは、ファイルパスの文字列の解析や操作などの機能を提供してくれる。よく分からないが例えば`path.resolve`という関数だと絶対パスに変換するなど。

>参考文献
>[Node.js API (path) - ファイルパスの文字列操作](http://yohshiy.blog.fc2.com/blog-entry-318.html)
>[webpack.config.jsで思ったpath.resolveって何のためにあるの？](https://koukitips.net/post1825/)

###4行目

```.js
 4 var cookieParser = require('cookie-parser');
```

4行目の`var cookieParser = require('cookie-parser');`は、`cookie-parser`モジュールを読み込んでいる。

cookie-parserモジュールとは、`req.cookies`関数によってcookieヘッダーを解析してcookie名をキーとするオブジェクトを生成するもの。

>参考文献
>[cookie-parser （公式ドキュメント）](https://www.npmjs.com/package/cookie-parser)

###5行目

```.js
 5 var logger = require('morgan');
```

`morgan`モジュールを読み込んでいる。morganモジュールとは、簡単にログ出力をするためのもの。

>参考文献
>[morgan （公式ドキュメント）](https://www.npmjs.com/package/morgan)
>[Express4のログ出力(morgan)について](https://qiita.com/mt_middle/items/543f83393c357ad3ab12)

###7行目

```.js
 7 var indexRouter = require('./routes/index');
```

`routes/index.js`を読み込んで、そこに書かれているコードを変数`indexRouter`に格納している。`routes/`ディレクトリに保存されるjsファイルはクライアントのリクエストに対するレスポンスが書かれている。その内容を格納する変数名は`ファイル名Router`とするのが作法っぽい。そして`routex/`ディレクトリにファイルを作成するたびに`app.js`のこの部分で列挙して読み込んでおくらしい。

###8行目

```.js
 8 var usersRouter = require('./routes/users');
```

7行目と同じく`routes/users.js`ファイルを読み込んでいる。`express-generator`で生成したテンプレートは初期状態で`index.js`と`users.js`が作成されている。今後アプリをコーディングしていく過程で独自のファイルを追加していくものと思われる。

###10行目

```.js
10 var app = express();
```

2行目で`express`モジュールを変数`express`に読み込んでおいたものを`express()`で実行し、そのときに生成されたコード群を変数`app`に格納している。今後は`app`という変数からプロパティアクセスする（`app.get()`など）ことで様々な変数やメソッドを呼び出すことができるようになった。メソッドの一覧は[公式ドキュメント](http://expressjs.com/en/4x/api.html)を参照。

簡単な言い回しに直しておくと、`var express = require('express');`は「モジュールの読み込み」と言い、`var app = express();`は「オブジェクトの作成」と言うと分かりやすい。

>参考文献
>[【Node.js入門】初心者のためのExpress入門（GET / POST）](https://www.sejuku.net/blog/74845#Express-4)
>[express() - 4.x API（公式ドキュメント）](http://expressjs.com/en/4x/api.html)

#view engine setup部分（12~23行）

###13行目

```.js
12 // view engine setup
13 app.set('views', path.join(__dirname, 'views'));
```

`app.set()`はアプリケーションに必要な各種設定情報をセットするオブジェクトとメソッドの組み合わせ。ここではviewディレクトリのパスをセットしている。

表示されるView Engineがどこのフォルダに入っているのかを設定。

※まだ具体的な構文の意味を理解できていない。

>参考文献
>[app.set（名前、値） - 4.x API（公式ドキュメント）](http://expressjs.com/en/4x/api.html#app.set)
>[はじめてのExpress.js　〜導入編(2)〜](http://lab.astamuse.co.jp/entry/2016/09/07/114500)
>[Expressオブジェクト app.set()の意味が分からないときに確認する方法](https://e-yota.com/webservice/express_object_app_set/)
>[node.jsでejsというview engineを使ってみる](https://tech-waplus.com/programming/20190408-node-js-ejs-view-engine/#ejs-2)

###14行目

```.js
14 app.set('view engine', 'jade');
```

テンプレートエンジンの`jade`を使えるように設定。`jade`モジュールは`node_modules/`の中に標準インストールされている。

どのview engineを使うのかを設定

ここに表記されているテンプレートエンジンはExpressテンプレートファイルを生成する際に`express myapp --view=ejs`のようにオプションで変更できる。デフォルトでは`jade`になる。変更した場合は`views/`の中に生成されるファイルの拡張子も`.ejs`や`.jade`に書き換わっている。

※まだ具体的な構文の意味を理解できていない。

>参考文献
>[はじめてのExpress.js　〜導入編(2)〜](http://lab.astamuse.co.jp/entry/2016/09/07/114500)
>[Expressオブジェクト app.set()の意味が分からないときに確認する方法](https://e-yota.com/webservice/express_object_app_set/)
>[node.jsでejsというview engineを使ってみる](https://tech-waplus.com/programming/20190408-node-js-ejs-view-engine/#ejs-2)

#app.useでいろいろ設定

###16行目

```.js
16 app.use(logger('dev'));
```

`logger()`はログを出力するミドルウェア。引数の`'dev'`は出力フォーマットの指定らしい。

ここでの`app.use()`は、アプリで`logger('dev')`を使うという処理だと思う。デバッグ用のコードと思われる。

>参考文献
>[Express loggerの使い方](http://dim5.net/nodejs/express3-logger.html)
>[API: dev プロパティ - Nuxt.js公式ドキュメント](https://ja.nuxtjs.org/api/configuration-dev/)

###17行目

```.js
17 app.use(express.json());
```

`express.json()`メソッドは、Body-Parserを基にした機能で、クライアントから送信されたデータを`req.body`経由で取得して操作する。

要は、何かjsonに関するデータを取得して解析して処理をするコードということ。

>参考文献
>[express.json([options]) - 4.x API（公式ドキュメント）](http://expressjs.com/en/4x/api.html#express.json)
>[Body-ParserがExpressにexpress.json()として標準搭載されている話](https://qiita.com/atlansien/items/c587a0bf2f7f9022107c)

###18行目

```.js
18 app.use(express.urlencoded({ extended: false }));
```

URLエンコードとは、URLで使用出来ない文字の変換を行うプロセス。`express.urlencoded()`メソッドはそんな感じの処理をうまくやってくれるやつ。`extended: false`だから拡張せずデフォルトで運用するという意味と思われる。

>参考文献
>[express.urlencoded（オプション） - 4.x API（公式ドキュメント）](https://expressjs.com/ja/api.html#express.urlencoded)

###19行目

```.js
19 app.use(cookieParser());
```

`cookieParser()`は`req.cookies`で`Cookie`ヘッダーを解析してCookie名をキーとするオブジェクトを入力するメソッド。

>参考文献
>[cookie-parser - GitHub](https://github.com/expressjs/cookie-parser)

###20行目

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

`express.static()`は[serve-static](http://expressjs.com/en/resources/middleware/serve-static.html)に基づいて静的ファイルを提供するミドルウェア。

`public/`に入っているのはcssやjsやimgなどの静的ファイルで、それを参照して読み込むための処理なんだと思う。

>参考文献
>[express.static（root、[オプション]） - 4.x API（公式ドキュメント）](http://expressjs.com/en/4x/api.html#express.static)

###22行目

```.js
22 app.use('/', indexRouter);
```

`app.use()`とは、アプリケーションに[ミドルウェア](http://expressjs.com/api.html#middleware)をバインドするためのもの。`app.use('マウントパス', ミドルウェア);`で要求されたパスのみにミドルウェアを適用されるように制限されている。~~22行目のコードでは、`'/'`すなわちトップページに対して変数`indexRouter`に格納しておいたミドルウェアを適用するという内容になっている~~。`'/'`でアクセスしてきたら`indexRouter`の中身を実行する。

パスの`'/'`すなわち`http://domain/`を`get`で受け取った際に変数`indexRouter`に格納しておいた`routes/index.js`のコードを実行する。

つまり`app.js`のこの部分には、アクセスしたパス`'/'`に対応するテンプレートファイル`routes/index.js`に記述された`変数名.get()`によって`res.render()`のプロパティ値を`views/index.jade`に渡すことでアプリ画面をレンダリングする、という処理が書かれている。

下記は`routes/index.js`に書かれた`get()`の部分。`app.get()`は要求されたときに特定のルートを照合して処理するためのもの。

```index.js
indexRouter.get('/', function(req, res, next){
  res.render('index', {title: 'Express'});
});
```
そして下記が`views/index.jade`に書かれたプロパティ値を受け取ってレンダリングする位置の抜粋。プロパティ名の`#{title}`がプロパティ値の`'Express'`に置換される。

```index.jade
  p Welcome to #{title}
```

この場合`<p>`タグで「Welcome to Express」とレンダリングされることになる。

>参考文献
>[はじめてのNode.js 2](http://cidermitaina.hatenablog.com/entry/2018/04/19/023433)
>[node.js – express.jsのapp.useとapp.getの違い](https://codeday.me/jp/qa/20181214/33327.html)

###23行目

```.js
23 app.use('/users', usersRouter);
```

処理の内容は22行目と同じ。

パスの`'/users'`すなわち`http://domain/users/`を`get`で受け取った際に変数`usersRouter`に格納しておいた`routes/users.js`のコードを実行する。

#catch 404 and forward to error handler部分（25~28行）

###26行目

```.js
25 // catch 404 and forward to error handler
26 app.use(function(req, res, next) {
27   （略）
28 });
```

メソッドの引数として無名関数を渡し、その関数の処理結果を`app.use`するというもの。具体的な処理は27行目の方で説明する。

`function(req, res, next)`の引数の順番は入れ替え可能だが、慣習どおりこの順番で書いておくのが無難。第三引数の`next`は何やら処理を終了させず継続させるための云々というものらしい。

>参考文献
>[nodejs express の next()って結局なんですか？](https://teratail.com/questions/156658)

###27行目

```.js
27   next(createError(404));
```

`next(セレクタ)`とは、対象要素の次に配置されている要素だけを取得するメソッド。セレクタとは、`next()`メソッドで取得する合致条件のようなもので、ここのコードではセレクタとして`createError(404)`が指定されている。これは404エラーでメッセージを生成するということ。

つまり26~27行目のコードは、「404エラーが返された際の次の処理を取得するという処理を`app.use()`する」ということ。

>参考文献
>[【jQuery入門】next(),nextAll(),siblings()で兄弟要素を取得する！](https://www.sejuku.net/blog/36740#next)
>[http-errors - npm公式ドキュメント](https://www.npmjs.com/package/http-errors)

#error handler部分（30~39行）

エラー関連の細かい処理らしいが、ちょっと今のレベルではよく分からん。後回し。

>参考文献
>[エラー処理/デフォルトのエラー処理 - 4.x API（公式ドキュメント）](https://expressjs.com/ja/guide/error-handling.html)

###31行目

```.js
30 // error handler
31 app.use(function(err, req, res, next) {
     （略）
39 });
```

###33行目

```.js
32   // set locals, only providing error in development
33   res.locals.message = err.message;
```

###34行目

```.js
34   res.locals.error = req.app.get('env') === 'development' ? err : {};
```

###37行目

```.js
36   // render the error page
37   res.status(err.status || 500);
```

###38行目

```.js
38   res.render('error');
```

エラーをレンダリングする処理。

#exports部分（41行目）

###41行目

```.js
41 module.exports = app;
```

`exports`は、指定した値をモジュール化して外部ファイルから読み込めるようにできる。そしてモジュール化したコードを他のファイルから`require`で読み込むことになる。`exports`と`module.exports`の違いは[参考文献](https://www.sejuku.net/blog/80173)を参照。

このようにNode.jsでは、モジュール化してさまざまな機能を持つプログラムを個別のファイルに分割し、効率的にコードを管理したり、プログラムを再利用しやすくする。Node.jsにおいて、全てのjsファイルの最後の行で`module.exports`しているのはそういうこと。

ここのコードの処理を解読する。これまで`app.js`のコードの10行目で`express()`を読み込み、その他いろいろと`app.set()`やら`app.use()`やらで開発中のアプリケーションの機能を設定してきた。そうしたコード群を改めてモジュール化して外部ファイルと連帯させるために、コードの最後で変数`app`を`module.exports`している。

>参考文献
>[【Node.js入門】exports / module.exportsによるモジュール機能の使い方まとめ！](https://www.sejuku.net/blog/80173)

#app.js全体を日本語訳してみる

当初の目的であった`app.js`全体のコードの解読を行う。できるかぎりわかりやすくするため、まずは日本語に置き換える実験をしてみる。

```.app.js
 1 var createError = require('http-errors');
 2 var express = require('express');
 3 var path = require('path');
 4 var cookieParser = require('cookie-parser');
 5 var logger = require('morgan');
 6
 7 var indexRouter = require('./routes/index');
 8 var usersRouter = require('./routes/users');
 9
10 var app = express();
11
12 // view engine setup
13 app.set('views', path.join(__dirname, 'views'));
14 app.set('view engine', 'jade');
15
16 app.use(logger('dev'));
17 app.use(express.json());
18 app.use(express.urlencoded({ extended: false }));
19 app.use(cookieParser());
20 app.use(express.static(path.join(__dirname, 'public')));
21
22 app.use('/', indexRouter);
23 app.use('/users', usersRouter);
24
25 // catch 404 and forward to error handler
26 app.use(function(req, res, next) {
27   next(createError(404));
28 });
29
30 // error handler
31 app.use(function(err, req, res, next) {
32   // set locals, only providing error in development
33   res.locals.message = err.message;
34   res.locals.error = req.app.get('env') === 'development' ? err : {};
35
36   // render the error page
37  res.status(err.status || 500);
38   res.render('error');
39 });
40
41 module.exports = app;
```

`app.js`を日本語訳にすると、

```アップ.js
 1 サーバー接続やエラーに関するモジュールを読み込む
 2 フレームワークに関するモジュールを読み込む
 3 パス管理に関するモジュールを読み込む
 4 クッキーに関するモジュールを読み込む
 5 ログ出力に関するモジュールを読み込む
 6
 7 トップページの内容を取得しておく
 8 ユーザページの内容を取得しておく
 9
10 'express()'モジュールの処理結果を'app'に入れとく
11
12 // 描画エンジンの設定
13 テンプレートファイルが'views/'に入ってることを把握
14 テンプレートエンジンは'jade'に設定
15
16 ログ出力のフォーマットは'dev'を使う
17 ｊｓｏｎファイルを解析するメソッドを使う
18 ＵＲＬエンコード方式は拡張せずに使う
19 クッキーを解析するメソッドを使う
20 静的ファイルが'public/'に入っていることを把握
21
22 トップページにアクセスしたときは'index.js'を表示
23 ユーザページにアクセスしたときは'users.js'を表示
24
25 // 404エラーだったらエラー表示する処理
26 
27   404エラーが出たらとりあえず次の処理に移行
28 
29
30 // エラー表示する機能について
31 
32   // ローカルにおいて開発者にだけエラー表示する処理
33   res.locals.message = err.message;
34   res.locals.error = req.app.get('env') === 'development' ? err : {};
35
36   // エラーページの表示処理
37  'err.status'の中身のいずれかが500エラーだったら
38   以上のエラー内容を画面に表示
39 
40
41 ここまでのコードをモジュール化して使いやすくする
```

とりあえずExpressで入門用アプリを作るにあたって、

```.js
 7 var indexRouter = require('./routes/index');
```

の部分のように複数のページを追加して読み込み、`routes/~.js`と`views/~.json`ファイルなども作成して、静的なHPを作ってみるといいかも。

アプリ開発する際に、こんな感じでコードの意味を解釈しながら書けたらいい。もっと深い意味もわかるように情報収集せねば。

#その他メモ

もしかしたら補足勉強で必要になりそうな参考文献をメモしとく。

>参考文献
>[node初心者がexpress-generatorで吐き出されたapp.jsを読んでみる](https://qiita.com/mito_log/items/735f7079f99ec78ea7e6)
>[body-parser](https://github.com/expressjs/body-parser)
>[express実践入門](https://gist.github.com/mitsuruog/fc48397a8e80f051a145)