Express web framework (Node.js/JavaScript)の勉強 part4、 directory-structure
The generated projectを読み進める。
日本語版の資料をかいつまんだような内容なので、詳細を知りたい人はこっちを見ることを勧める。
ディレクトリ構造
express
および関連するコマンドを実行することで以下のようなディレクトリ構造になる。
注意:一部コマンドの出力結果は省略している。
$ express express-locallibrary-tutorial --view=pug --git create : express-locallibrary-tutorial/ create : express-locallibrary-tutorial/public/ create : express-locallibrary-tutorial/public/javascripts/ create : express-locallibrary-tutorial/public/images/ create : express-locallibrary-tutorial/public/stylesheets/ create : express-locallibrary-tutorial/public/stylesheets/style.css create : express-locallibrary-tutorial/routes/ create : express-locallibrary-tutorial/routes/index.js create : express-locallibrary-tutorial/routes/users.js create : express-locallibrary-tutorial/views/ create : express-locallibrary-tutorial/views/error.pug create : express-locallibrary-tutorial/views/index.pug create : express-locallibrary-tutorial/views/layout.pug create : express-locallibrary-tutorial/.gitignore create : express-locallibrary-tutorial/app.js create : express-locallibrary-tutorial/package.json create : express-locallibrary-tutorial/bin/ create : express-locallibrary-tutorial/bin/www change directory: $ cd express-locallibrary-tutorial install dependencies: $ npm install run the app: $ DEBUG=express-locallibrary-tutorial:* npm start $ cd express-locallibrary-tutorial $ npm install up to date, audited 123 packages in 2s 6 packages are looking for funding run `npm fund` for details 3 low severity vulnerabilities To address all issues, run: npm audit fix --force Run `npm audit` for details. $ tree -F . ├── app.js ├── bin/ │ └── www* ├── node_modules/ │ ├── たくさんのサブディレクトリおよびファイル(表示は省略) │ ︙ │ ├── package.json ├── package-lock.json ├── public/ │ ├── images/ │ ├── javascripts/ │ └── stylesheets/ │ └── style.css ├── routes/ │ ├── index.js │ └── users.js └── views/ ├── error.pug ├── index.pug └── layout.pug 405 directories, 4784 files
nodemon
今後express-locallibrary-tutorial
以下を編集していくのだが、編集するたびアプリを起動し直すのは面倒である。
この煩わしさを解消するnodemon
というツールがある
下記コマンドを実行し、nodemon
をインストールする。
npm install -g nodemon
もし開発環境以下(?)にインストールしたい場合は-g
の代わりに--save-dev
を使う。
nodemon
を使ってアプリを起動すると、ファイル編集時に自動で反映してくれるためアプリの再起動の手間が省ける。
nodemon ./bin/www
package.json
package.json
はアプリの依存情報を保持する
nodemon
をインストールした直後のpackage.json
の内容を以下に示す。
タイミングによってバージョン番号は変化するので、次同じコマンドを実行しても下記と同じ結果になるとは限らない(と思う)。
{ "name": "express-locallibrary-tutorial", "version": "0.0.0", "private": true, "scripts": { "start": "node ./bin/www", }, "dependencies": { "cookie-parser": "~1.4.4", "debug": "~2.6.9", "express": "~4.16.1", "http-errors": "~1.6.3", "morgan": "~1.9.1", "nodemon": "^2.0.7", "pug": "2.0.0-beta11" } }
npm run-script
参考:npm-run-script | npm Docs
npm run-script
コマンドによってpackage.json
の"scripts"
オブジェクトに記載されたコマンドを実行できる。
上記の場合、"scripts"
というオブジェクトの中にキー"start"
、バリュー"node ./bin/www"
が存在しているため、npm run-script start
と入力するとnode ./bin/www
が実行される。
引数なしの場合は、以下のように利用可能なコマンドが表示される。
$ npm run-script Lifecycle scripts included in express-locallibrary-tutorial: start node ./bin/www
以下npm run-script -h
の実行結果からわかるようにrun-script
はrun
というエイリアスを持っている。
入力文字の短さからnpm run
を使ったほうが良いだろう(npm run-script
のほうがnpm run
より良いケースってあるのだろうか?)。
$ npm run-script -h npm run-script <command> [-- <args>] aliases: run, rum, urn
scripts
package.json
内のscripts
を以下のように編集する
"scripts": { "start": "node ./bin/www", "devstart": "nodemon ./bin/www", "serverstart": "DEBUG-express-lcallibrary-tutorial:* npm run devstart" }
"start"
で始まる行の末尾にカンマ(,
)が追記されていることに注意する。
以降はnpm run serverstart
と実行することでnodemon
でアプリが実行される
/bin/www
ファイル/bin/www
はアプリケーションのエントリポイントである。
下記コードによって、後述するapp.js
を呼び出す。
#!/usr/bin/env node /** * Module dependencies. */ var app = require('../app');
残りのコードでapp.js
を使用するHTTPサーバの設定、ポートの設定、リスニングやサーバエラーのレポートを開始するらしい。
/app.js
express
アプリケーションオブジェクト(app
という名前が慣習である)を生成、アプリケーションおよびミドルウェアの設定、app
をエクスポートする。
上記した/bin/www
はエクスポートされたapp
を使用する。
var express = require('express'); ... var app = express(); ... module.exports = app;
app.js
の詳細を見ていく。
最初にいくつかのnodeライブラリを取り込む。
var createError = require('http-errors'); var express = require('express'); var path = require('path'); var cookieParser = require('cookie-parser'); var logger = require('morgan');
その後require()
を使い、routes
ディレクトリからモジュールを取り込む。
これらファイルには、特定のURLへのリクエストを受け取った場合の処理が書かれている。
var indexRouter = require('./routes/index'); var usersRouter = require('./routes/users');
次にappオブジェクトをexpress
モジュールを使い作成し、view(template)エンジンを設定する。
エンジンの設定は2段階に分かれる。
最初に値'views'
を使ってテンプレートが保存されているフォルダを指定する。
その後、値'view engine'
を使いテンプレートライブラリを指定する。
参考:Using template engines with Express
var app = express(); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug');
続いてapp.use()
を使いミドルウェアライブラリをリクエストハンドリングの連鎖に加える。
app.use(logger('dev')); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public')));
更に特定のパスへの要求を別のルータへ対応付ける。
app.use('/', indexRouter); app.use('/users', usersRouter);
最後はエラーとHTTP404レスポンスを返却するためのミドルウェアを追加する。
// catch 404 and forward to error handler app.use(function(req, res, next) { next(createError(404)); }); // error handler app.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page res.status(err.status || 500); res.render('error'); });
以上でexpressアプリケーションオブジェクト(app)の設定は完了する。
最後にmodule.exports
にapp
を追加することで、/bin/www
からアクセスできるようにする。
module.exports = app;
Router
/routes
以下にはusers.js
とindex.js
があるが基本的に処理が同じなので、ここではindex.js
のみを見ていく。
最初にexpress
モジュールをロードしexpress.routerオブジェクトを取得する。
var express = require('express'); var router = express.Router(); /* GET users listing. */ router.get('/', function(req, res, next) { res.send('respond with a resource!!'); }); module.exports = router;
Views(templates)
views(template)は/views
ディレクトリに格納され、拡張子.pug
を持つ。
Response.render()メソッドは特定のテンプレートを描画するために使われ、レスポンスとして結果を送信する。
以下/routes/index.js
の例ではルートレンダーはテンプレートindex(index.pug)
を使い、テンプレート変数title
を渡している。
/* GET home page. */ router.get('/', function(req, res, next) { res.render('index', { title: 'Express' }); });
上記コードに対応するテンプレート/views/index.pug
を以下に示す。
ここでは数変title
の箇所に値Express
が挿入される。
extends layout block content h1= title p Welcome to #{title}
まとめ
個人的にこの章は今までメインでやってきたこと(組み込み寄り)と比べて多くの差異を感じた。
特に重要に違いを感じた点を以下にまとめる。
npm express
でアプリケーションの雛形が作成されること。app.js
ではルーターやビューの設定、その他ライブラリのインポートなどを行うこと。routes
ディレクトリ以下にはルーター(router)が配置され、ルーターは特定のパスへの要求を受理したときに対応する処理へのルーティングを担当すること。- 変数
res
はrender
メソッドを使うとテンプレートを使って描画する。 views
ディレクトリにはビュー(view)のテンプレートが配置され、これらは描画の際に使われること。
これらは繰り返し実装しないと身につかなさそうだ。