express-generatorで生成したテンプレートのapp.jsのコードを日本語訳する。
コードの意味を解説している記事や公式ドキュメントを参照しながら、できる限り噛み砕いてクドイ言い回しで解釈していく。
勉強中の関連記事まとめ
自分用の勉強記事をまとめた目次 ~擬似知識体系~
#勉強に必要な準備
使用するPCに以下のパッケージがインストールされているものとする。
- npm
- Node.js
- Express.js
- express-generator
###勉強に使ったExpressのバージョン確認
$ express --version
4.16.1
###テンプレートファイルの生成
$ express myapp
###生成されたテンプレートの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行目
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
でテンプレート生成したときにまとめて用意されている。
require()
で読み込むファイルパスが省略されてモジュール名だけで済んでいるのは、require()
の仕組みとして検索優先度があってnode_module/
は優先度が高い検索領域だからパスを記述しなくても見つけてくれる。
参考文献
Node.jsのrequireの検索パス
###2行目
2 var express = require('express');
2行目のvar express = require('express');
は、node_module/
にあるexpress
モジュールを読み込んで変数express
に格納している。expressモジュールはexpress-generator
のテンプレートに最初から含まれている。
expressモジュールとは、Node.jsでMVCを容易に実現するのに必要なコードが書かれたフレームワーク。
###3行目
3 var path = require('path');
3行目のvar path = require('path');
は、Node.jsの標準モジュールの一つであるpath
モジュールを読み込んでいる。
pathモジュールとは、ファイルパスの文字列の解析や操作などの機能を提供してくれる。よく分からないが例えばpath.resolve
という関数だと絶対パスに変換するなど。
参考文献
Node.js API (path) - ファイルパスの文字列操作
webpack.config.jsで思ったpath.resolveって何のためにあるの?
###4行目
4 var cookieParser = require('cookie-parser');
4行目のvar cookieParser = require('cookie-parser');
は、cookie-parser
モジュールを読み込んでいる。
cookie-parserモジュールとは、req.cookies
関数によってcookieヘッダーを解析してcookie名をキーとするオブジェクトを生成するもの。
###5行目
5 var logger = require('morgan');
morgan
モジュールを読み込んでいる。morganモジュールとは、簡単にログ出力をするためのもの。
###7行目
7 var indexRouter = require('./routes/index');
routes/index.js
を読み込んで、そこに書かれているコードを変数indexRouter
に格納している。routes/
ディレクトリに保存されるjsファイルはクライアントのリクエストに対するレスポンスが書かれている。その内容を格納する変数名はファイル名Router
とするのが作法っぽい。そしてroutex/
ディレクトリにファイルを作成するたびにapp.js
のこの部分で列挙して読み込んでおくらしい。
###8行目
8 var usersRouter = require('./routes/users');
7行目と同じくroutes/users.js
ファイルを読み込んでいる。express-generator
で生成したテンプレートは初期状態でindex.js
とusers.js
が作成されている。今後アプリをコーディングしていく過程で独自のファイルを追加していくものと思われる。
###10行目
10 var app = express();
2行目でexpress
モジュールを変数express
に読み込んでおいたものをexpress()
で実行し、そのときに生成されたコード群を変数app
に格納している。今後はapp
という変数からプロパティアクセスする(app.get()
など)ことで様々な変数やメソッドを呼び出すことができるようになった。メソッドの一覧は公式ドキュメントを参照。
簡単な言い回しに直しておくと、var express = require('express');
は「モジュールの読み込み」と言い、var app = express();
は「オブジェクトの作成」と言うと分かりやすい。
参考文献
【Node.js入門】初心者のためのExpress入門(GET / POST)
express() - 4.x API(公式ドキュメント)
#view engine setup部分(12~23行)
###13行目
12 // view engine setup
13 app.set('views', path.join(__dirname, 'views'));
app.set()
はアプリケーションに必要な各種設定情報をセットするオブジェクトとメソッドの組み合わせ。ここではviewディレクトリのパスをセットしている。
表示されるView Engineがどこのフォルダに入っているのかを設定。
※まだ具体的な構文の意味を理解できていない。
参考文献
app.set(名前、値) - 4.x API(公式ドキュメント)
はじめてのExpress.js 〜導入編(2)〜
Expressオブジェクト app.set()の意味が分からないときに確認する方法
node.jsでejsというview engineを使ってみる
###14行目
14 app.set('view engine', 'jade');
テンプレートエンジンのjade
を使えるように設定。jade
モジュールはnode_modules/
の中に標準インストールされている。
どのview engineを使うのかを設定
ここに表記されているテンプレートエンジンはExpressテンプレートファイルを生成する際にexpress myapp --view=ejs
のようにオプションで変更できる。デフォルトではjade
になる。変更した場合はviews/
の中に生成されるファイルの拡張子も.ejs
や.jade
に書き換わっている。
※まだ具体的な構文の意味を理解できていない。
参考文献
はじめてのExpress.js 〜導入編(2)〜
Expressオブジェクト app.set()の意味が分からないときに確認する方法
node.jsでejsというview engineを使ってみる
#app.useでいろいろ設定
###16行目
16 app.use(logger('dev'));
logger()
はログを出力するミドルウェア。引数の'dev'
は出力フォーマットの指定らしい。
ここでのapp.use()
は、アプリでlogger('dev')
を使うという処理だと思う。デバッグ用のコードと思われる。
###17行目
17 app.use(express.json());
express.json()
メソッドは、Body-Parserを基にした機能で、クライアントから送信されたデータをreq.body
経由で取得して操作する。
要は、何かjsonに関するデータを取得して解析して処理をするコードということ。
参考文献
express.json([options]) - 4.x API(公式ドキュメント)
Body-ParserがExpressにexpress.json()として標準搭載されている話
###18行目
18 app.use(express.urlencoded({ extended: false }));
URLエンコードとは、URLで使用出来ない文字の変換を行うプロセス。express.urlencoded()
メソッドはそんな感じの処理をうまくやってくれるやつ。extended: false
だから拡張せずデフォルトで運用するという意味と思われる。
###19行目
19 app.use(cookieParser());
cookieParser()
はreq.cookies
でCookie
ヘッダーを解析してCookie名をキーとするオブジェクトを入力するメソッド。
###20行目
20 app.use(express.static(path.join(__dirname, 'public')));
express.static()
はserve-staticに基づいて静的ファイルを提供するミドルウェア。
public/
に入っているのはcssやjsやimgなどの静的ファイルで、それを参照して読み込むための処理なんだと思う。
###22行目
22 app.use('/', indexRouter);
app.use()
とは、アプリケーションにミドルウェアをバインドするためのもの。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()
は要求されたときに特定のルートを照合して処理するためのもの。
indexRouter.get('/', function(req, res, next){
res.render('index', {title: 'Express'});
});
そして下記がviews/index.jade
に書かれたプロパティ値を受け取ってレンダリングする位置の抜粋。プロパティ名の#{title}
がプロパティ値の'Express'
に置換される。
p Welcome to #{title}
この場合<p>
タグで「Welcome to Express」とレンダリングされることになる。
###23行目
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行目
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
は何やら処理を終了させず継続させるための云々というものらしい。
###27行目
27 next(createError(404));
next(セレクタ)
とは、対象要素の次に配置されている要素だけを取得するメソッド。セレクタとは、next()
メソッドで取得する合致条件のようなもので、ここのコードではセレクタとしてcreateError(404)
が指定されている。これは404エラーでメッセージを生成するということ。
つまり26~27行目のコードは、「404エラーが返された際の次の処理を取得するという処理をapp.use()
する」ということ。
参考文献
【jQuery入門】next(),nextAll(),siblings()で兄弟要素を取得する!
http-errors - npm公式ドキュメント
#error handler部分(30~39行)
エラー関連の細かい処理らしいが、ちょっと今のレベルではよく分からん。後回し。
###31行目
30 // error handler
31 app.use(function(err, req, res, next) {
(略)
39 });
###33行目
32 // set locals, only providing error in development
33 res.locals.message = err.message;
###34行目
34 res.locals.error = req.app.get('env') === 'development' ? err : {};
###37行目
36 // render the error page
37 res.status(err.status || 500);
###38行目
38 res.render('error');
エラーをレンダリングする処理。
#exports部分(41行目)
###41行目
41 module.exports = app;
exports
は、指定した値をモジュール化して外部ファイルから読み込めるようにできる。そしてモジュール化したコードを他のファイルからrequire
で読み込むことになる。exports
とmodule.exports
の違いは参考文献を参照。
このようにNode.jsでは、モジュール化してさまざまな機能を持つプログラムを個別のファイルに分割し、効率的にコードを管理したり、プログラムを再利用しやすくする。Node.jsにおいて、全てのjsファイルの最後の行でmodule.exports
しているのはそういうこと。
ここのコードの処理を解読する。これまでapp.js
のコードの10行目でexpress()
を読み込み、その他いろいろとapp.set()
やらapp.use()
やらで開発中のアプリケーションの機能を設定してきた。そうしたコード群を改めてモジュール化して外部ファイルと連帯させるために、コードの最後で変数app
をmodule.exports
している。
#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
を日本語訳にすると、
1 サーバー接続やエラーに関するモジュールを読み込む
2 フレームワークに関するモジュールを読み込む
3 パス管理に関するモジュールを読み込む
4 クッキーに関するモジュールを読み込む
5 ログ出力に関するモジュールを読み込む
6
7 トップページの内容を取得しておく
8 ユーザページの内容を取得しておく
9
10 'express()'モジュールの処理結果を'app'に入れとく
11
12 // 描画エンジンの設定
13 テンプレートファイルが'views/'に入ってることを把握
14 テンプレートエンジンは'jade'に設定
15
16 ログ出力のフォーマットは'dev'を使う
17 jsonファイルを解析するメソッドを使う
18 URLエンコード方式は拡張せずに使う
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で入門用アプリを作るにあたって、
7 var indexRouter = require('./routes/index');
の部分のように複数のページを追加して読み込み、routes/~.js
とviews/~.json
ファイルなども作成して、静的なHPを作ってみるといいかも。
アプリ開発する際に、こんな感じでコードの意味を解釈しながら書けたらいい。もっと深い意味もわかるように情報収集せねば。
#その他メモ
もしかしたら補足勉強で必要になりそうな参考文献をメモしとく。
参考文献
node初心者がexpress-generatorで吐き出されたapp.jsを読んでみる
body-parser
express実践入門