å幎ããããªããã¡ã«ãããããæç§æžã®ç¬¬2ç« ãæžãããšãã§ããŸããã ãŸããè¡å人ã®åžæãèæ
®ã«å
¥ããŠãæåã®ç« ãå°ãäœãçŽããŸããããã®ãã
ãnode.jsãšexpressã§ã®WebéçºãããäžåºŠèŠãããšãã§ããŸã
ã å®éã«node.jsãåŠç¿ãã第2ç« ãã¢ã¢ããªã±ãŒã·ã§ã³ãšæåã®ãã¹ã
ãã®ç« ã§ã¯ããã¥ãŒããªã¢ã«å
šäœãéããŠäŸãšããŠäœ¿çšããã¢ããªã±ãŒã·ã§ã³ã®éçºãéå§ããæãåçŽãªéçããŒãžããå§ããŸãã ãŸããnode.jsäžã®ã¢ããªã±ãŒã·ã§ã³ã®ãã¹ããšãããã«äœ¿çšãããããŒã«ã«ã€ããŠãçè§£ããŸãã
2.1ã¢ãã«ãã¥ãŒã³ã³ãããŒã©ãŒïŒMVCïŒ
ã¢ããªã±ãŒã·ã§ã³ã®å®éã®éçºãéå§ããåã«ãå
žåçãªWebã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£ãæœè±¡åã®æé«ã¬ãã«ã«ãããã®ã«ã€ããŠè©±ãããšã¯æçšã§ãã çŸåšæãäžè¬çãªã¢ãŒããã¯ãã£ãã¿ãŒã³ã¯
ã¢ãã«ãã¥ãŒã³ã³ãããŒã©ãŒ ïŒMVCïŒã§ãããã¿ãŒã³ã®äžè¬çãªæå³ã¯ãã¢ããªã±ãŒã·ã§ã³ã®ããžãã¹ããžãã¯ïŒã¢ãã«ã«é¢é£ä»ããããŠããïŒãšãã¥ãŒãåé¢ããããšã§ãã ããã«ãã¢ãã«ã¯ããŒã¿ããŒã¹ãžã®ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããŸãã ã³ã³ãããŒã©ãŒã¯ãã¢ãã«ãšãã¥ãŒã®éã®ä»²ä»åœ¹ãšããŠæ©èœããŸãã Webã¢ããªã±ãŒã·ã§ã³ã®å Žåãããã¯æ¬¡ã®ããã«ãªããŸãããŠãŒã¶ãŒã®ãã©ãŠã¶ãŒããµãŒããŒã«ãªã¯ãšã¹ããéä¿¡ããã³ã³ãããŒã©ãŒããªã¯ãšã¹ããåŠçããã¢ãã«ããå¿
èŠãªããŒã¿ãåä¿¡ãããã¥ãŒã«éä¿¡ããŸãã Viewã¯ãã³ã³ãããŒã©ãŒããããŒã¿ãåä¿¡ãããããçŸããHTMLããŒãžã«å€æããæçµçã«ã³ã³ãããŒã©ãŒããŠãŒã¶ãŒã«éä¿¡ããŸãã

2.2ãã¢ã¢ããªã±ãŒã·ã§ã³
ãã¢ã¢ããªã±ãŒã·ã§ã³ã®éçºãéå§ããŸãã æåã®ç« ã§ã¯ããã¹ãã¢ããªã±ãŒã·ã§ã³ãæ¢ã«ãããã€ããŸãããããšã¯ã¹ãã¬ã¹ãžã§ãã¬ãŒã¿ãŒã䜿çšãã1è¡ã®ã³ãŒããèšè¿°ããŸããã§ããã ããã§ãã¢ããªã±ãŒã·ã§ã³ãèªåã§äœæãããHelloãWorldãããå§ããŸãã
$ cd ~/projects/node-tutorial $ mkdir node-demo-app $ cd node-demo-app
2.2.1 npmããã±ãŒãž
npmãšã¯äœã§ããïŒ ç°¡åã§ããããã¯ããŒãããã±ãŒãžãããŒãžã£ãŒã§ãïŒèè
ã¯ããã«
ç°è°ãå±ããŠããŸããïŒã äžè¬çã«ãnpmããã±ãŒãžã¯ããã°ã©ã ãšãã®ããã°ã©ã ã説æããpackage.jsonãã¡ã€ã«ãå«ããã£ã¬ã¯ããªã§ãããã®ãã¡ã€ã«ã«ã¯ãããã°ã©ã ãäŸåããä»ã®ããã±ãŒãžãæå®ãããã
package.jsonã®
説æãèªãã ãã§ããŸãã
npmãæäŸã§ãããã¹ãŠã®ãã£ãŒã ãæŽ»çšããããã«ããããžã§ã¯ãã®ã«ãŒããã£ã¬ã¯ããªã«ãã¡ã€ã«ãäœæããŸãã
$ touch package.json
package.jsonïŒ
{ "name": "node-demo-app" , "version": "0.0.1" , "scripts": { "start": "node server.js" } , "dependencies": { "express": "3.0.x" } }
å®è¡ã§ããããã«ãªããŸãã
$ npm install
ãã®çµæãnpmã¯node_modulesãã£ã¬ã¯ããªãäœæããŸãããã®ãã£ã¬ã¯ããªã«ã¯ããããžã§ã¯ããäŸåãããã¹ãŠã®ã¢ãžã¥ãŒã«ãé
眮ãããŸãã
2.2.2ããã«ã¡ã¯ãäžçïŒ
ã¡ã€ã³ãã¡ã€ã«ã¯server.jsãšåŒã°ããŸãã
$ touch server.js
server.jsïŒ
var express = require('express') , app = express() , port = process.env.PORT || 3000 app.get('/', function (req, res) { res.send('Hello, World!') }) app.listen(port, function () { console.log('Listening on port ', port) })
ããã«çšèªã決å®ãããã®ã³ãŒããåæããŸãã
ã¢ããªã±ãŒã·ã§ã³ã¯
app
ãªããžã§ã¯ãã«ãªãã
app.get
颿°ã®åŒã³åºã
㯠ã¢ã¯ã·ã§ã³ ïŒã¢ã¯ã·ã§ã³ïŒã
ããŠã³ãããŸãããã®å Žåããã®åœ¹å²ã¯å¿å颿°ã«ãã£ãŠå®è¡ããã
ãã¹ ïŒã«ãŒãïŒ '/'ã«ãªããŸãã å®éãããã¯ãhttp GET /ãªã¯ãšã¹ããåä¿¡ãããã³ã«ãã¢ããªã±ãŒã·ã§ã³ãæå®ãããã¢ã¯ã·ã§ã³ãå®è¡ããããšãæå³ããŸãã ãã®äŸã®
port
倿°ã¯ãååšããå Žåã¯
PORT
ç°å¢å€æ°ã«ãã£ãŠåæåããããã®ãããªå€æ°ããªãå Žåã¯å€3000ã
app.listen
ãŸã
app.listen
ã¯æå®ãããããŒãã§httpãµãŒããŒãèµ·åããçä¿¡èŠæ±ã®ãªãã¹ã³ãéå§ããŸãã
ç§ãã¡ã®ä»äºã®çµæãè³è³ããããã«ã2ã€ã®æ¹æ³ããããŸãïŒ
$ node server.js
ã©ã¡ãã
$ npm start
ãscriptsãã»ã¯ã·ã§ã³ã§package.jsonæ§æãã¡ã€ã«ã«å¯Ÿå¿ããè¡ã远å ããããã2çªç®ã®æ¹æ³ã䜿çšå¯èœã§ãã
httpïŒ// localhostïŒ3000 /ã§ ããHelloãWorldïŒããšããè¡ãååŸã§ããŸãã
GitHubã«äœããã¢ããããŒãããŸãã node-demo-appãšããååã§GitHubã«æ°ãããªããžããªãäœæãããããžã§ã¯ããã£ã¬ã¯ããªã§æ¬¡ã®äžé£ã®ã³ãã³ããå®è¡ããæåã«README.mdãã¡ã€ã«ãäœæããŸãïŒé©åãªããŒã³ã«ãŒã«ïŒ
$ echo '# Node.js demo app' > README.md
gitã§äœåãªãã¡ã€ã«ãã€ãŸãnode_modulesãã£ã¬ã¯ããªãã³ãããããªãããã«ã.gitignoreãã¡ã€ã«ãäœæããŸãããã
$ echo 'node_modules' > .gitignore
誰ããMikeal Rogersã®
èšäºãèªãã§ãnode_modulesã.gitignoreã«è¿œå ããããšã«å察ããããããããŸããã èªãã®ãé¢åãªäººã«ã¯ãnode.jsã®ãããžã§ã¯ãã§ãã®ã¢ãããŒããæšå¥šãããŸãïŒ
- Webã¢ããªã±ãŒã·ã§ã³ãªã©ã ãããã€ããŠãããããžã§ã¯ãã®å Žåãnode_modulesã¯ãªããžããªã«é
眮ãããŸãã
- ã©ã€ãã©ãªããã³ãã®ä»ã®åå©çšå¯èœãªã³ãŒãã®å Žåãnode_modulesã¯ãªããžããªã«è¿œå ãããŸããã
- æ¬çªç°å¢ãžã®å±éã«ã¯ãnpmã¯äœ¿çšãããŸããã
ãããïŒ Herokuããã¹ãã£ã³ã°ãšããŠäœ¿çšãããããã€æ¹æ³ãéžæããââãnode.jsãããžã§ã¯ãã¯npmã䜿çšããŠãããã€ãããããããªããžããªãæ£ããããŸããã
ãªããžããªãäœæããã³ãããããŠGitHubã«ãã¹ãŠãã¢ããããŒãããŸãã
$ git init $ git add . $ git commit -m 'Hello, World' $ git remote add origin git@github.com:<username>/node-demo-app.git $ git push -u origin master
2.2.3ã¢ããªã±ãŒã·ã§ã³æ§é
Expressã§ã¯ãã¢ããªã±ãŒã·ã§ã³ãã¡ã€ã«ã®å³å¯ãªæ§é ã¯ãŸã èŠå®ãããŠããªããããç¬èªã®ãã¡ã€ã«ãäœæããŸãã ãã®ãªãã·ã§ã³ããå§ãããŸãïŒ
/node-demo-app |- /app | |- /controllers - | |- /models - | |- /views - html | |- config.js - | |- main.js - |- /public - - , , .. |- /tests - |- app.js - |- server.js - http
ãã®ãããªãã¡ã€ã«ã®ã¬ã€ã¢ãŠãã«åŸãããšã匷å¶ãã人ã¯ããŸããããç§ã«ãšã£ãŠã¯äŸ¿å©ãªããã§ãããã®ããããã®å³ãèŠããŠãããŠããã¥ãŒããªã¢ã«ãé²ããªããå¿
èŠãªãã¡ã€ã«ãšãã£ã¬ã¯ããªãäœæããŸãã
2.3ã¢ããªã±ãŒã·ã§ã³ã®ãã¹ã
ãããããTDDãšã¯äœãããã¹ããæžãå¿
èŠãããçç±ã«ã€ããŠã¯æ¢ã«èããããšãããã§ããããããã§ãªãå Žåã¯ã
ãã¡ãã§èªãããšãã§ã
ãŸã ã ãã®ãã¥ãŒããªã¢ã«ã§ã¯ã
BDD ïŒããã€ãã¢é§åéçºïŒãšåŒã°ããã¢ãããŒãã䜿çšããŠãã¢ããªã±ãŒã·ã§ã³ããã¹ãããŸãã ãã¹ãã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã®äºæ³ãããåäœã«ã€ããŠèª¬æããŸãã ãã¹ãèªäœã¯ãçµ±åãã¹ãïŒãŠãŒã¶ãŒã®åäœãã·ãã¥ã¬ãŒãããŠã·ã¹ãã å
šäœããã¹ãããïŒãšåäœãã¹ãïŒåã
ã®ã¢ããªã±ãŒã·ã§ã³ã¢ãžã¥ãŒã«ããã¹ãããïŒã®2ã€ã®ã«ããŽãªã«åé¡ãããŸãã
2.3.1èªåãã¹ã
ãã¹ããèšè¿°ããããã®ãã¬ãŒã ã¯ãŒã¯ãšããŠã
mochaã©ã€ãã©ãªïŒmochaãcoffee-mokaã®ããã«èªã¿ãŸã:)ïŒã
should.js ãããã³
supertestã䜿çšããŸãã Mochaã¯ãã¹ãã±ãŒã¹ã®èª¬æãæŽçããããã«äœ¿çšãããshould.jsã¯ããŸããŸãªãã§ãã¯ãå®è¡ããããã®æ§æãæäŸããsupertestã¯httpèŠæ±ã®çµæã確èªã§ããåçŽãªhttpã¯ã©ã€ã¢ã³ãã®ã¢ããªã³ã§ãã ã©ã€ãã©ãªãæ¥ç¶ããã«ã¯ãpackage.jsonã«å¿
èŠãªå€æŽãå ããŸã
{ "name": "node-demo-app" , "version": "0.0.1" , "scripts": { "start": "node server.js" } , "dependencies": { "express": "3.0.x" } , "devDependencies": { "mocha": "1.7.0" , "should": "1.2.1" , "supertest": "0.4.0" } }
ãããã®ã©ã€ãã©ãªãéçšãµãŒããŒã«ãã©ãã°ããå¿
èŠããªããããäŸåé¢ä¿ããdevDependenciesãã»ã¯ã·ã§ã³ã«é
眮ããŸããã ã©ã€ãã©ãªãã€ã³ã¹ããŒã«ããã«ã¯ãå®è¡ããŸã
$ npm install
ãããã©ã®ããã«æ©èœããããçè§£ããããã«ãæåã®ãã¹ããäœæãããã¬ãŒã ã¯ãŒã¯ã§å®è¡ããŠã¿ãŸããã
$ mkdir tests $ touch tests/test.js
test.jsã«ãã®ãããªãã¹ããå
¥ããŸã
describe('Truth', function () { it('should be true', function () { true.should.be.true }) it('should not be false', function () { true.should.not.be.false }) })
ãããŠãããå®è¡ãã
$ ./node_modules/.bin/mocha --require should --reporter spec tests/test.js
åœç¶ããã®ãããªãã¹ãã¯ãã¹ããã®ã§ãå£ãããã®ã«çœ®ãæããŠãã ãã
describe('foo variable', function () { it('should equal bar', function () { foo.should.equal('bar') }) })
æã¡äžãã
$ ./node_modules/.bin/mocha --require should --reporter spec tests
ãã¹ãããã¹ããªãã£ãããšã確èªããã«ã¯ãã³ãŒãã修埩ãã倿°å®£èšã远å ããå¿
èŠããããŸã
var foo = 'bar' describe('foo variable', function () { it('should equal bar', function () { foo.should.equal('bar') }) })
æã¡äžãã
$ ./node_modules/.bin/mocha --require should --reporter spec tests/test.js
ã³ãŒããæ©èœããŠããããšãããããŸãã
TDDã®åºæ¬ååã¯ãã³ãŒããèšè¿°ããåã«ãã¹ããäœæããããšã§ãããã®ãããå®è¡æã«ã³ãŒããå®è¡ããŠtrue.should.beã®ã¹ã¿ã€ã«ã§ãã§ãã¯ãè¡ãã ãã§ãªãããã¹ããå®éã«äœãããã¹ãããŠããããšã確èªã§ããŸããæ¬åœ ã€ãŸããéçºããã»ã¹ã¯æ¬¡ã®ãšããã§ãã
- ãã¹ããæžã
- ãã¹ããå®è¡ãããããèœã¡ãããšã確èªããŸã
- ã³ãŒããæžã
- ãã¹ããå®è¡ãããã¹ããããšã確èªããŸãããã¹ããªãå Žåã¯ãã¹ããã3ã«æ»ããŸãã
ãããŠäœåºŠãã
ãã¹ãã®èµ·åãç°¡çŽ åããã«ã¯ãã¿ã¹ã¯å®è¡ãã¹ããMakefileã«è¿œå ããŸã
$ touch Makefile
ã¡ã€ã¯ãã¡ã€ã«ã®å
容ïŒ
REPORTER=spec TESTS=$(shell find ./tests -type f -name "*.js") test: @NODE_ENV=test ./node_modules/.bin/mocha \ --require should \ --reporter $(REPORTER) \ $(TESTS) .PHONY: test
äŒçµ±çã«ããããžã§ã¯ãã®ãã«ãã«ã¯makeã䜿çšãããŠããŸããããã«ãŒãã³ã¿ã¹ã¯ãèªååããããã«makeãå
šäœãšããŠäœ¿çšãããšäŸ¿å©ã§ãã
ããã§ Makefileã®äœ¿çšã«ã€ããŠèªãã§
ãã ãã ã ã¿ã¹ã¯ã®ååã®åŸã®ã€ã³ãã³ãã¯ã¹ããŒã¹ã§ã¯ãªãã¿ãã«ããå¿
èŠãããããšã«æ³šæããŠãã ããã
次ã®ã³ãã³ãã§ãã¹ãã¹ã€ãŒããå®è¡ã§ããŸãïŒ
$ make test
httpãªã¯ãšã¹ãããã¹ãããŠã¿ãŸãããã ãã¹ãããã䟿å©ã«ããããã«ãå°ããªã³ãŒãã®ãªãã¡ã¯ã¿ãªã³ã°ãè¡ãããšã¯ã¹ãã¬ã¹ã¢ããªã±ãŒã·ã§ã³ãserver.jsãã¡ã€ã«ããå¥ã®app / main.jsã¢ãžã¥ãŒã«ã«è»¢éãããã®ã¢ãžã¥ãŒã«ããšã¯ã¹ããŒãããapp.jsãã¡ã€ã«ãäœæããŸãã ããã¯å®çšçã§ã¯ãªãããã«æãããããããŸããããã³ãŒãã®ç¯å²ããã¹ãã§ç¢ºèªãããšãã«ããã®ã³ãŒãã®ç·šææ¹æ³ã圹ç«ã¡ãŸãã
$ mkdir app $ touch app/main.js
app / main.jsïŒ
var express = require('express') , app = express() app.get('/', function (req, res) { res.send('Hello, World!') }) module.exports = app
$ touch app.js
app.jsïŒ
module.exports = require(__dirname + '/app/main')
server.jsã¯
var app = require(__dirname + '/app') , port = process.env.PORT || 3000 app.listen(port, function () { console.log('Listening on port ', port) })
node.jsã¢ãžã¥ãŒã«ãã©ã®ããã«æ©èœãããã
require
ããã³
module.exports
ãçè§£ããããã«ã
ããã¥ã¡ã³ããèªã¿
ãŸãhttpãªã¯ãšã¹ãã®æ£ç¢ºãã確èªããã«ã¯ãtest.jsã«æ¬¡ã®ã³ãŒããèšè¿°ããŸã
var request = require('supertest') , app = require(__dirname + '/../app') describe('GET /', function () { it('should contain text "Hello, Express!"', function (done) { request(app) .get('/') .expect(/Hello, Express!/, done) }) })
ãã®ãã¹ãã§ã¯ããµãŒããŒããHelloãExpressïŒããšããè¡ã§å¿çããããšã確èªããŸãã ãµãŒããŒã¯ãHelloãWorldïŒããšå¿çããããã代ããã«ãã¹ãã¯å€±æããŸãã æ³šæãã¹ãéèŠãªç¹ã¯ãhttpãµãŒããŒãžã®ãªã¯ãšã¹ããéåæçã«çºçããããšã§ãããã®ããããã¹ããå®äºããããã«ã³ãŒã«ããã¯ãå²ãåœãŠãå¿
èŠããããŸãã Mochaã¯ãdone颿°ã䜿çšããŠãã®ãããªæ©äŒãæäŸããŸããdone颿°ã¯ããªãã·ã§ã³ã§ãã¹ãã±ãŒã¹ãšãšãã«é¢æ°ã«æž¡ãããšãã§ããŸãã ãã¹ãã«åæ Œããã«ã¯ãapp / main.jsãã¡ã€ã«ã§ãHelloãWorldïŒãã®è¡ããHelloãExpressïŒãã«çœ®ãæããŠ
make test
ãå®è¡ãã
make test
ã
2.3.2ãã¹ãã«ããã³ãŒãã«ãã¬ããž
ååãšããŠããã®æ®µèœã¯ãã¹ãã¢ããªã±ãŒã·ã§ã³ã®äœæããã»ã¹ã«åœ±é¿ãäžããªããããã¹ãããã§ããŸããããã¹ãã®ã³ãŒãã«ãã¬ããžã«é¢ããã¬ããŒãã¯ããã¹ãã¹ã€ãŒãã«è¿œå ããã®ã«é©ããŠããŸãã
ã³ãŒã
ããã¹ãã§ã©ã®çšåºŠå®å
šã«
ã«ããŒãããŠãããã調ã¹ãã«ã¯ã
jscoverageãšåŒã°ããå¥ã®ããŒã«ãå¿
èŠã§ãã ã³ã³ãã€ã«ããå¿
èŠããããŸãã ãããã£ãŠãã³ã³ãã€ã©ããŸã ã€ã³ã¹ããŒã«ããŠããªãå Žåã¯ãã€ã³ã¹ããŒã«ããå¿
èŠããããŸãã
$ sudo apt-get install g++
次ã«ãjscoverageãã€ã³ã¹ããŒã«ããŸãã
$ cd /tmp $ git clone git://github.com/visionmedia/node-jscoverage.git $ cd node-jscoverage $ ./configure && make $ sudo make install
ãããžã§ã¯ããã£ã¬ã¯ããªã«æ»ããŸãããã
$ cd ~/projects/node-tutorial/node-demo-app/
ã«ãã¬ããžã¬ããŒããçæããã«ã¯ãMakefileãšapp.jsã«ããã€ãã®å€æŽãå ããå¿
èŠããããŸãã
ã¡ã€ã¯ãã¡ã€ã«ïŒ
REPORTER=spec TESTS=$(shell find ./tests -type f -name "*.js") test: @NODE_ENV=test ./node_modules/.bin/mocha \ --require should \ --reporter $(REPORTER) \ $(TESTS) test-cov: app-cov @APP_COV=1 $(MAKE) --quiet test REPORTER=html-cov > coverage.html app-cov: @jscoverage app app-cov .PHONY: test
app.jsïŒ
module.exports = process.env.APP_COV ? require(__dirname + '/app-cov/main') : require(__dirname + '/app/main')
test-covã¿ã¹ã¯ãMakefileã«è¿œå ããã®ã§ã
make test-cov
ãå®è¡ã
make test-cov
coverage.jsã¬ããŒããçæ
make test-cov
ã ãã§ååã§ãã app.jsã®å€æŽã¯ãjscoverageãçæããã¢ããªã±ãŒã·ã§ã³ã®ã€ã³ã¹ãã«ã¡ã³ãåãããã³ããŒãã¬ããŒãã«å«ãŸããŠãããšããäºå®ã«é¢é£ããŠããŸãã ã€ãŸããç°å¢å€æ°
APP_COV
ã確èªããã€ã³ã¹ããŒã«ãããŠããå Žåã¯/ app-covãã£ã¬ã¯ããªããã¢ããªã±ãŒã·ã§ã³ãããŒãããã€ã³ã¹ããŒã«ãããŠããªãå Žåã¯/ appããéåžžã®ããŒãžã§ã³ãååŸããŸãã
ã¬ããŒããçæããŸãã
$ make test-cov
ãã©ãŠã¶ãŒã§éãããšãã§ããcoverage.htmlãã¡ã€ã«ã衚瀺ãããŸãã
.gitignore app-covããã³coverage.htmlã«è¿œå ããå¿
èŠããããŸãã
$ echo 'app-cov' >> .gitignore $ echo 'coverage.html' >> .gitignore
ãã¹ããçè§£ããã®ã§ããã¹ãtestãåé€ããŸã
$ rm tests/test.js
ãããŠã³ããã
$ git add . $ git ci -m "Added testing framework" $ git push
ãã¢ã¢ããªã±ãŒã·ã§ã³ã®ãœãŒã¹ã³ãŒãã¯ã
github.com /
DavidKlassen /
node-demo-appããå
¥æã§ããŸãã
ã¢ãããŒãã¯3çªç®ã®ç« ã§ããµã€ãã®ããŒãžçšã®æ¬æ Œçãªã³ã³ãããŒã©ãŒãäœæããExpressã§ã®ãã³ãã¬ãŒãã®åäœãçè§£ããŸãã