Socket.IO サーバーとして Heroku を使ってみよう。 実験中 https://shielded-caverns-4913.herokuapp.com/ Heroku 練習 以前作ったユーザーが生きていたので改めてチュートリアルを実践。
Getting Started with Node.js on Heroku
gulpでexpressなサーバを作る
普通にnpmなプロジェクトを作る。
> mkdir bvh_sio
> cd bvh_sio
> npm init
> mkdir src
> mkidr src/server
> mkdir src/client
> cd src
> tsd init
> tsd query node -rosa install
> tsd query express -rosa install
> tsd query serve-static -rosa install
> tsd query socket.io -rosa install
Herokuにデプロイする場合はでdevDependenciesじゃなくてdependenciesに書くらしいのでそのようにした。
package.json
{
"name": "bvh_sio",
"version": "1.0.0",
"description": "",
"main": "build/app.js",
"scripts": {
"start": "node build/app.js"
},
"author": "ousttrue",
"license": "ISC",
"dependencies": {
"express": "^4.13.3",
"gulp": "^3.9.0",
"gulp-if": "^2.0.0",
"gulp-load-plugins": "^1.1.0",
"gulp-run-sequence": "^0.3.2",
"gulp-typescript": "^2.10.0",
"serve-static": "^1.10.0",
"socket.io": "^1.3.7",
"tsd": "^0.6.5"
}
}
serve-staticで静的なファイルをホストするexpress。後でsocket.ioを追加する。
src/server/app.ts
/// <reference path="../typings/tsd.d.ts" />
import http = require('http');
import express = require('express');
const port = process.env.PORT || 3000; // <- Herokuで必要!
const app = express();
const server = http.createServer(app);
const servestatic = require('serve-static');
const serve_dir = __dirname + '/public';
console.log('serve %s', serve_dir);
app
.use(servestatic(serve_dir))
;
// start
server.listen(port);
console.log('start port: %d...', port);
こいつをtypescriptでコンパイルしてbuildディレクトリに展開したい。
gulpfile.js
'use strict';
const path = require('path');
const execSync = require('child_process').execSync;
const gulp = require('gulp');
const $ = require('gulp-load-plugins')();
const config = {
server_src: './src/server/**/*.*',
server_dst: './build',
client_src: './src/client/**/*.*',
client_dst: './build/public'
};
const tsconfig = require('./tsconfig.json');
function pushd(dst, callback) {
const cwd = process.cwd();
process.chdir(dst);
callback();
process.chdir(cwd);
}
gulp.task('tsd:install', () => {
pushd('./src', ()=>execSync('tsd install'));
});
gulp.task('server', () => {
gulp.src(config.server_src)
.pipe($.if((file) => path.extname(file.path).toLowerCase() === '.ts'
, $.typescript(tsconfig.compilerOptions)))
.pipe(gulp.dest(config.server_dst))
;
});
gulp.task('client', () => {
gulp.src(config.client_src)
.pipe($.if((file) => path.extname(file.path).toLowerCase() === '.ts'
, $.typescript(tsconfig.compilerOptions)))
.pipe(gulp.dest(config.client_dst))
;
});
gulp.task('build', ['server', 'client']);
gulp.task('install', (cb) => {
$.runSequence('tsd:install', 'build', cb);
});
gulp.task('default', ['build']);
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": true,
"outDir": ".",
"rootDir": ".",
"sourceMap": false,
"removeComments": true
},
"exclude": [
"node_modules"
]
}
jsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es6"
}
}
src/client/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h1>Hello</h1>
</body>
</html>
プロジェクトをHeroku化してデプロイ
Herokuでビルドしたりbuild結果だけをpushするなどの方式があるようだが、Heroku上でgulpする方式にしてみた(git苦手w)。
git push時に実行するコマンドをpackage.jsonに記述できる。
package.json
"scripts": {
"postinstall": "gulp install", // <- 追加する
"start": "node build/app.js"
},
サーバー実行コマンド。
Procfile
web: node build/app.js
herokuにデプロイ。
# 一回だけ実行する
> heroku create
# herokuを更新
> git push heroku master
# エラーが出たら直す。npm installなど
# herokuサイトをブラウザで開く
> heroku open
# エラーが出たら直す。npm installなど
heroku側でgulp-typescriptするように作ってみたけどうまくいった。
socket.ioを追加
websocketじゃなくてajax pollingらしいけどSocket.IOがよきに計らってくれる。
src/server/app.tsに追加
// socket.io
import socketio = require('socket.io');
const io = socketio(server);
io.on('connection', (socket) => {
var clientAddress = socket.client.conn.remoteAddress;
console.log('connected: %s from %s', socket.id, clientAddress);
function recTimer(interval: number, callback: Function)
{
setTimeout(()=>recTimer(interval, callback), interval);
callback();
}
recTimer(3000, ()=>socket.emit('time', Date.now()));
});
src/client/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="/socket.io/socket.io.js"></script>
<script src="index.js"></script>
</head>
<body>
<h1>Hello</h1>
<div id='content'></div>
</body>
</html>
src/client/index.ts
/// <reference path="../typings/tsd.d.ts" />
declare module io {
export function connect(): SocketIO.Socket;
}
window.onload = () => {
const socket = io.connect();
const content=document.getElementById('content');
socket.on('connect', ()=>{
content.innerHTML='connected!';
});
socket.on('time', (message: any)=>{
content.innerHTML+='<br>'+message;
});
}
bvh
準備が整ったので、node.js側でパースしたbvhを適当にjson化してsocket.ioにemitするサーバーを作る。