26
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Expressを使うテンプレ覚書(最後にSocket.IO用のカスタマイズ一例を置いておく)

Last updated at Posted at 2016-05-24

#目的
・Expressのテンプレがどのような構造、役割を果たしているのかをまとめておき、改造が必要な時などに思い出しやすくする。

・個人的な解釈です。くれぐれも過信しないでください。(間違っていたら意見を頂けると幸いです)

#環境
・node -v 5.4.1

#必要な予備知識(準備)
・NodeJS
・npmについて
・Expressのインストール(かつexpressコマンドが使えるようにパスを通す)

#Expressのテンプレの中身
-app.js
-bin
-www
-package.json
-public
-routes
-views

##app.js
###どういうところか?
・URLリクエストを受け取り、修飾を施したのちに希望したディレクトリのページがあれば返し、なければerrを返す。

###処理内容
・基本上から

1、モジュールの読み込み(必要な材料を揃える)
	・node_moduleの読み込み
	・routesフォルダにあるオリジナルjsファイル(モジュール)の読み込み
	・自分で入れたjsファイル(モジュール)の読み込み
2、Expressインスタンスの作成。個人的に「モジュールはここまでだよ」という目印にしている。ここからExpressインスタンスを加工していく。(調理スタート)
3、レンダラーエンジンの指定(MVCの内、Vを指定する)
4、ミドルウェアの追加(nodeモジュール(材料)を組み込んで、Expressインスタンス自体は完成)
5、ルーティングの追加(配達先を指定しておく。)
6、エラー処理(配達先が見つからない場合、廃棄する)
7、最後にExpressインスタンスをエクスポート

という流れになる(と解釈)

###コードに当てはめると

//1、モジュールの読み込み
//node_module
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');

//オリジナルjsファイル
var routes = require('./routes/index');
var users = require('./routes/users');

//自分で入れる場合はここに

//2、Expressインスタンスの作成
var app = express();

//3、レンダラーエンジンの指定
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

//4、ミドルウェアの追加
//app.use(favicon(path.join(__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')));

//5、ルーティングの追加
app.use('/', routes);
app.use('/users', users);

//6、エラー処理
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
    });
  });
}

// 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: {}
  });
});

//7、最後にExpressインスタンスをエクスポート
module.exports = app;

##www
###どういうところか?
・テンプレなら、一番最初に起動されるexecファイル。
・ポート番号の指定、サーバーの立ち上げ、サーバーのlistenを行っている

###処理内容
・基本上から

1、appモジュールをrequireする
2、debugモジュールをrequireする
3、httpモジュールをrequireする
4、port番号の宣言、appへのport番号のセット
5、httpモジュールでappを引数にcreateServerし、server変数に格納
6、serverをportへlistenさせる
7、その他(エラー処理など)

という流れになる(と解釈)

###コードに当てはめると

#!/usr/bin/env node

//1、appモジュールをrequireする
var app = require('../app');

//2、debugモジュールをrequireする
var debug = require('debug')('ReactServer:server');

//3、httpモジュールをrequireする
var http = require('http');

//4、port番号の宣言、appへのport番号のセット
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

//5、httpモジュールでappを引数にcreateServerし、server変数に格納
var server = http.createServer(app);

//6、serverをportへlistenさせる
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

//7、その他(エラー処理など)
function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
}

##routesファイル
###どういうところか?
・app.jsで振り分けられたあとの処理が詰まったモジュールが入っている
・基本的にはExpressのindex.jsのテンプレを真似ればいいが、役割がいくつか別れる

①URLを判定して、特定のページを表示させるもの。
②サーバー側で実行するビジネスモデルモジュール(SocketIOなど)

・両者とも、大まかには

・必要なモジュールを読み込む
・関数、インスタンスを作成
・module.exportsでそれを送信

という流れになる。

##viewsファイル
###どういうところか?
・レンダーするひな型ファイルが入っている。
・デフォルトはjade。設定でejsにも変更可能

#カスタマイズの一例
・Socket.IOを使うようにカスタマイズしたものを一応あげておく

##app.js

//node_module(材料)
var express = require('express'),
    compression = require('compression'),
    path = require('path'),
    logger = require('morgan'),
    bodyParser = require('body-parser');

//オリジナルと自分で作ったモジュール
var routes = require('./routes/index'),
    PC = require('./routes/PC'),
    smartphone = require('./routes/smartphone');

//Expressインスタンス
var app = express();

//レンダラーエンジンの指定
app.set('views', path.join(__dirname,'views'));
app.set('view engine','jade');

//ミドルウェアの追加
app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));

//ルーティングの追加
app.use('/', routes);
app.use('/PC', PC);
app.use('/smartphone', smartphone);

//Expressインスタンスをエクスポート
module.exports = app;

##www
・Socket.IOの記述はものによっては結構長くなるので、別ファイルに書いておいたほうがすっきりする。

・しかし、Socket.IOの記述ができるのは、createServerしているところと同じファイルでないといけない。

・なのでcreateServerはこのファイルでは行わず、socketIO処理を書いておくモジュール(SocketIO.js)に記載したのち、このページへ読み込む形にする

#!/usr/bin/env node

//appモジュールをrequireする(ここではhttpモジュールは読み込まず、代わりにroutesフォルダに作ったsocket.IOを読み込む)
var app = require('../app');
var debug = require('debug')('ReactServer:server');
var socketIO = require('../routes/socketIO');

//port番号の指定
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

//ソケットIOのモジュールを実行。(実はこの中でcreateServerしてlistenしている)
socketIO();

//以下はその他。変化なし

##SocketIO.js(routesファイル内に作成)
・ここでサーバーを立ち上げてlistenする処理も書く(createServerする)
・createServerをするにあたり、以下の三つが必要になることを覚えておくとやりやすい

・app.jsモジュール
・httpモジュール
・ポート番号
//appモジュールを読み込む(このappには、www内ですでにポート番号が登録されているので、ポート番号を取得したことにもなる)
var app = require('../app');

//httpモジュールを読み込んで、サーバーを立ち上げる(createServerと同じ扱い)
var http = require('http');

//必要な三要素を揃えて初めてサーバーを立ち上げられる
var server = http.createServer(app);

//サーバーをlistenしてsocketIOを設定
var io = require('socket.io')(server);

//socketIOモジュール
function socketIO(){
	//サーバーを立ち上げたら実行
    server.listen(app.get('port'), function() {
        console.log('listening!!!');
    });

	//socket処理を記載する
    io.on('connection', function(socket){
    
        //socket処理
        socket.on('socketName',function(data){
            console.log(data);
            io.sockets.emit('socketName2',data);
        })
        
    });
};

//export
module.exports = socketIO;

・おしまい

26
32
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?