読者です 読者をやめる 読者になる 読者になる

ottatiのブログ

無職学生がネットにクソアプリをまき散らしていく様子

【node】express-generatorの出力をみてみるの段

node express

f:id:ottati:20150103125718g:plain     🍣

はじめに

express-generatorはExpressアプリケーションのひな形を作るツール。 大変参考になるのでざっと確認しておく

実際に出力してみた

GitHubにexpress-generator@4.12.1の生出力をあげた

expressコマンドない

ここに従っていけば始められるかも

install

上からコピった

$ npm install express-generator -g
$ express myapp
$ cd myapp
$ DEBUG=myapp npm start

構成

上からコピった

.
├── app.js
├── bin
│   └── www
├── package.json
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes
│   ├── index.js
│   └── users.js
└── views
    ├── error.jade
    ├── index.jade
    └── layout.jade

npm startってなんだ

npm startって何, node appじゃないのか、と思うわけです。

package.jsonを見ると"start": "node ./bin/www"と書いてあるのでこれが実行されるようだ。ここに書いてある。

package.jsonのコード

{
  "name": "express-generator-output",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "express": "~4.8.6",
    "body-parser": "~1.6.6",
    "cookie-parser": "~1.3.2",
    "morgan": "~1.2.3",
    "serve-favicon": "~2.0.1",
    "debug": "~1.0.4",
    "jade": "~1.5.0"
  }
}

bin/wwwの中身

中身はくコ:彡のようになっている

#!/usr/bin/env node
var debug = require('debug')('express-generator-output');
var app = require('../app');

app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function() {
  debug('Express server listening on port ' + server.address().port);
});

debugモジュールはconsole.logの代わりに使うとハッピーになれそう。さっきの起動の仕方, DEBUNG=myapp npm startのようにするとデバッグモードになってdebug()内が出力される

appって

app.js内でexpress()で生成されたオブジェクトなんでしょう。app.jsをモジュールとしてrequireしてる。 app.set('port', ...)Application Settingsにportという値を突っ込む

サーバの開始

nodeのhttpモジュールのサーバにappを紐付けてサーバを動かす。

var server = app.listen(app.get('port'), function() {
  debug('Express server listening on port ' + server.address().port);
});

ちなみにくコ:彡の2つのコードのすることはまったく一緒みたい。

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

//app.configure, app.use etc

var server = app.listen(1234);
var express = require('express'), http = require('http');
var app = express();
var server = http.createServer(app);

//app.configure, app.use etc

server.listen(1234);

processって

nodeのどこからでもアクセスできるグローバルオブジェクト。

process.envより環境変数PORTにアクセスしてる。設定されてなかったら3000番に設定。

ちなみにここで環境変数に書き込んでもそのプロセスが生きている時のみ有効なのでくコ:彡のコードではなにもechoらない。

node -e 'process.env.FOOD = "sushi"' && echo $FOOD

app.js

メインディッシュ。bin/wwwからapp.jsを読み込んでいたのでそれを見てく。

コード

60行しかないのではっつけ

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});


module.exports = app;

モジュール達

requireされているモジュール達を見ていく

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

serve-favicon

ファビコンを簡単に提供できるモジュール

var express = require('express');
var favicon = require('serve-favicon');

var app = express();
app.use(favicon(__dirname + '/public/favicon.ico'));

// Add your routes here, etc.

app.listen(3000);

morgan

ロガー

app.use(logger('dev'));

cookie-parser

cookie-parserは簡単にクッキーにアクセスできるモジュール

var express      = require('express')
var cookieParser = require('cookie-parser')

var app = express()
app.use(cookieParser())

app.get('/', function(req, res) {
  console.log("Cookies: ", req.cookies)
})
  
app.listen(8080)
  
// curl command that sends an HTTP request with two cookies
// curl http://127.0.0.1:8080 --cookie "Cho=Kim;Greet=Hello

body-parser

このモジュールはくコ:彡のパーサを含む

  • JSON body parser
  • Raw body parser
  • Text body parser
  • URL-encoded form body parser

Error handlers

404

ここまで来てしまったリクエストに対してerrに404を設定してそれを次のエラーハンドラに回す。

app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

開発環境でのエラーハンドラ

開発時のみに有効なエラーハンドラを設定する。

if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

プロダクションでのエラーハンドラ

本番環境でののエラーハンドラを設定。 renderで指定されているerrorプロパティが空のオブジェクトにしてトレース内容を隠している。

app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});

もう一度構成の確認

(;´Д`)

.
├── app.js
├── bin
│   └── www
├── package.json
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes
│   ├── index.js
│   └── users.js
└── views
    ├── error.jade
    ├── index.jade
    └── layout.jade

publicディレクトリ

静的ファイルが入っている

app.js内でapp.use(express.static(path.join(__dirname, 'public')));しているのでここのディレクトリが読み込まれる。

viewsディレクトリ

テンプレートディレクトリ。

  • ディレクトリの指定はapp.set('views', path.join(__dirname, 'views'));
  • app.set('view engine', 'jade');しているのでjadeで記述

routes

index.jsusers.jsがapp.jsで読み込まれている。これらは実際にレスポンスを返すコードを含む

app.jsでは以下のようになてる

app.use('/', routes);
app.use('/users', users);

index.js

express.Router()でrouterオブジェクトを生成している。これはapp.use('/example', router)という風に読み込むとrouter内のルーティングが/exampleの下で展開されるイメージ。公式ドキュメントでもmini-appと読んだりしている。

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res) {
  res.render('index', { title: 'Express' });
});

module.exports = router;

res.renderでindex.jadeを読み込み。コンテクストとしてtitleにExpressとしている。

users.js

大体いっしょ。こっちはテキストを送ってる。

var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function(req, res) {
  res.send('respond with a resource');
});

module.exports = router;`

そんなかんじ

express-generatorの出力ファイルをひと通り見た気分になりました