Socket.IOな実験環境
Socket.IO を実験する環境のメモ。
Expressは、serve-staticで静的なファイルのhostingが目的兼後で拡張できるように
coffee-scriptは無しでES6要素をなるべく入れる
Socket.IOを手早く展開するのが目的なのでtypescriptは抜きにしようと思ったが、無い方がつらいので矢張り入れる
https://github.com/ousttrue/sio_sample
Project生成
> mkdir sio_sample
> cd sio_sample
sio_sample> npm init -y
sio_sample> npm install gulp gulp-load-plugins gulp-nodemon browser-sync -D
sio_sample> npm install express socket.io body-parser method-override connect-logger errorhandler serve-static --save
vscodeでes6を使えるように
jsconifg.json
{
"compilerOptions": {
"target": "ES6"
}
}
後で拡張できるように以下のようなディレクトリ構成にする。
build <- srcから(加工して)コピーされる
src <- 加工前のファイル置き場
+ server
+ app.js
+ client
+ index.html
+ index.js
src/server/app.js
"use strict";
const http = require('http');
const express = require('express');
const port = process.env.port || 3000;
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))
;
// socket.io
const socketio = require('socket.io');
const io = socketio(server);
io.on('connection', (socket) => {
console.log('a client connected %s', socket);
socket.on('disconnect', () => {
console.log('a client disconnected');
});
});
// start
server.listen(port);
console.log('start port: %d...', port);
src/client/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="index.js"></script>
</head>
<body>
<div id="target"></div>
</body>
</html>
src/client/index.js
"use strict";
function setup(target) {
const div = document.createElement('div');
div.appendChild(document.createTextNode('onLoad'));
target.appendChild(div);
}
window.onload = () => {
setup(document.getElementById('target'));
};
srcからbuildに展開するgulp
gulpfile.js
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'
};
gulp.task('server', () => {
gulp.src(config.server_src)
.pipe(gulp.dest(config.server_dst));
});
gulp.task('client', () => {
gulp.src(config.client_src)
.pipe(gulp.dest(config.client_dst));
});
gulp.task('default', ['server', 'client']);
build
sio_sample> gulp
ブラウザで動いた。
browserSync導入
gulpfile.js。browserSync
const config = { // 追加分
app_entry: './build/app.js',
app_port: 5000,
};
const browserSync = require('browser-sync').create();
gulp.task('serve', ()=>{
$.nodemon({
script: config.app_entry,
exp: 'js',
ignore: [],
env: {
port: config.app_port
}
})
.on('readable', ()=>{
this.stdout.on('data', (chunk)=>{
if (/^start /.test(chunk)){
console.log('reloading...');
browserSync.reload();
}
process.stdout.write(chunk)
});
});
});
gulp.task('browser-sync', ['serve'], ()=>{
browserSync.init({
proxy: 'localhost:' + config.app_port,
port: 3000,
ws: true
})
});
gulpfile.js。watchタスク追加
gulp.task('server', () => {
gulp.src(config.server_src)
.pipe(gulp.dest(config.server_dst))
.pipe(browserSync.stream())
;
});
gulp.task('client', () => {
gulp.src(config.client_src)
.pipe(gulp.dest(config.client_dst))
.pipe(browserSync.stream())
;
});
gulp.task('build', ['server', 'client']);
gulp.task('watch', ['build', 'browser-sync'], ()=>{
gulp.watch(config.server_src, ['server']);
gulp.watch(config.client_src, ['client']);
});
gulp.task('default', ['watch']);
git
いったんgitに登録しよう。
.gitignore
/node_modules/
/build/
Socket.IOの疎通
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script src="index.js"></script>
</head>
<body>
<div id="target"></div>
</body>
</html>
"use strict";
function setup(target) {
const div = document.createElement('div');
div.appendChild(document.createTextNode('hello'));
target.appendChild(div);
this.socket = io.connect();
}
window.onload = () => {
setup(document.getElementById('target'));
};
typescript導入
sio_sample> tsc --init
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": true,
"outDir": ".",
"rootDir": ".",
"sourceMap": false
},
"exclude": [
"node_modules"
]
}
sio_sample> npm install gulp-typescript gulp-if gulp-plumber gulp-debug -D
sio_sample> cd src
sio_sample/src> tsd init
sio_sample/src> tsd query node express socket.io -rosa install
gulpfile.js。typescriptのコンパイルを追加
const path = require('path');
const tsconfig = require('./tsconfig.json');
const isTypescript = (file) => {
const ext = path.extname(file.path).toLowerCase();
return ext === '.ts';
}
gulp.task('server', () => {
gulp.src(config.server_src)
.pipe($.plumber())
.pipe($.if(isTypescript, $.typescript(tsconfig.compilerOptions)))
.pipe($.debug('server'))
.pipe(gulp.dest(config.server_dst))
.pipe(browserSync.stream())
;
});
gulp.task('client', () => {
gulp.src(config.client_src)
.pipe($.plumber())
.pipe($.if(isTypescript, $.typescript(tsconfig.compilerOptions)))
.pipe($.debug('client'))
.pipe(gulp.dest(config.client_dst))
.pipe(browserSync.stream())
;
});
src/server/app.jsをapp.tsにリネーム
/// <reference path="../typings/tsd.d.ts" />
"use strict";
import http = require('http');
import express = require('express');
const port = process.env.port || 3000;
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))
;
// 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', clientAddress);
socket.on('disconnect', () => {
console.log('disconnected: %s', clientAddress);
});
});
// start
server.listen(port);
console.log('start port: %d...', port);
src/client/index.jsをindex.tsにリネーム
/// <reference path="../typings/tsd.d.ts" />
"use strict";
declare module io {
export function connect(): SocketIO.Socket;
}
function setup(target: Element) {
const div = document.createElement('div');
div.appendChild(document.createTextNode('hello socket.io'));
target.appendChild(div);
this.socket = io.connect();
}
window.onload = () => {
setup(document.getElementById('target'));
};
メッセージをやり取り
src/server/app.ts サーバーサイド。client-messageを受けてserver-messageを発行
// 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', clientAddress);
socket.on('disconnect', () => {
console.log('disconnected: %s', clientAddress);
});
socket.on('client-message', (data: any) => {
socket.emit('server-message', 'server clicked message');
});
});
src/client/index.ts クライアントサイド。buttonを押したらclient-messageを発行。server-messageを受けてテキストを描画
/// <reference path="../typings/tsd.d.ts" />
"use strict";
declare module io {
export function connect(): SocketIO.Socket;
}
class Client {
socket: SocketIO.Socket;
constructor() {
this.socket = io.connect();
}
setup(target: Element) {
const div = document.createElement('div');
div.appendChild(document.createTextNode('hello socket.io'));
target.appendChild(div);
this.socket.on('server-message', (data: any)=>{
const div = document.createElement('div');
div.appendChild(document.createTextNode(data.toString()));
target.appendChild(div);
});
const button=document.createElement('button');
button.appendChild(document.createTextNode('send'));
button.onclick=(ev: MouseEvent)=>{
this.socket.emit('client-message', 'clicked');
};
target.appendChild(button);
}
}
var client=new Client();
window.onload = () => {
client.setup(document.getElementById('target'));
};