Node.js で小規模なアプリケーションを開発する方法 その1

3日坊主にならないように頑張ります。

Node.js を使って小規模なアプリケーションをいくつか開発して、こうすると綺麗にまとまるなあ、というパターンをいくつか発見しました。

これらのパターンを紹介していけたら良いなあ、と思います。

# プロジェクトの作成

日報を管理するアプリケーションを例にとろうと思います。まずはプロジェクトのディレクトリを作ります。使用するコマンドはもちろん```mkdir```です。

```
mkdir nippo
```

nippoディレクトリを作成したらサーバ側のソースコードを配置する```app```ディレクトリとクライアント側のソースコードを配置する```static```を作成します。

```
cd nippo
mkdir app
mkdir static
```

```app```ディレクトリと```static```ディレクトリのそれぞれで```npm init```をします。

```
cd app
npm init -f
```

```
cd ../static
npm init -f
```

```-f``` をつけると、エンターキー連打しなくてもいいんですね、今、初めて知りしました。

上記のコマンドを全部入力すると下記のようなディレクトリ構造が出来上がります。

```
nippo
├ app
│ └ package.json
└ static
  └ package.json
```

# クライアント側のセットアップ

まずは、クライアント側のセットアップを終わらせていこうと思います。

```webpack-dev-server``` と ```nodemon``` をインストールします。

```
npm install --save-dev webpack-dev-server nodemon
```

```webpack-dev-server``` と ```nodemon``` をインストールしている間に```webpack.config.js```を作成します。

```
touch webpack.config.js
```

```webpack.config.js``` の内容は下記の通りです。

````webpack.config.js
'use strict';

var path = require('path')

module.exports = {
  entry: './src/entry.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'js/bundle.js',
  },
}

```

```src``` ディレクトリを作成します。

```
mkdir src
```

```entry.js``` を作成します。

```
touch src/entry.js
```

```entry.js``` にはとりあえず、下記の内容を記載します。

```entry.js
'use strict';

console.log('entry.js')
```

```public``` フォルダを作成します。

```
mkdir public
```

http://www.initializr.com/ から Bootstrap のボイラープレートをダウンロードします。いつも下記のように設定しています。

- Twitter Bootstrap
- Modernizr
- Respond チェックはずす
- jQuery minified
- H5BP Optional 全部チェックはずす

zipファイルをダウンロードして解凍したら ```public``` にコピーします。下記のファイルは不要なので削除します。

- img
- js/vendor/bootstrap.js
- js/vendor/npm.js
- js/main.js
- index.html

現時点のディレクトリ構造は下記のようになります。

```

nippo
├ app
│ └ package.json
└ static
  ├ public
  │ ├ css
  │ │ ├ bootstrap-theme.css
  │ │ ├ bootstrap-theme.css.map
  │ │ ├ bootstrap-theme.min.css
  │ │ ├ bootstrap.css
  │ │ ├ bootstrap.css.map
  │ │ ├ bootstrap.min.css
  │ │ └ main.css
  │ ├ fonts
  │ │ ├ glyphicons-halflings-regular.eot
  │ │ ├ glyphicons-halflings-regular.svg
  │ │ ├ glyphicons-halflings-regular.ttf
  │ │ └ glyphicons-halflings-regular.woff
  │ └ js
  │   └ vendor
  │     └ vendor
  │       ├ bootstrap.min.js
  │       ├ jquery-1.11.2.min.js
  │       └ modernizr-2.8.3.min.js
  ├ src
  │ └ entry.js
  ├ entry.js
  └ package.json
```

```package.json``` の ```script``` に 新しく ```start``` の行を追加します。

```package.json(変更前)
{
  "name": "static",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^1.12.2",
    "webpack-dev-server": "^1.12.0"
  }
}
```


```package.json(変更後)
{
  "name": "static",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node_modules/.bin/nodemon -w webpack.config.js node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --port=8080 --content-base=public",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^1.12.2",
    "webpack-dev-server": "^1.12.0"
  }
}
```

```npm start``` で ```webpack-dev-server``` を起動します。

```
npm start
```

成功すると http://localhost:8080/js/bundle.js にアクセスしたときに ```webpack-dev-server``` が生成したJavaScriptファイルが表示されます。念のため、http://localhost:8080/css/bootstrap.min.css などにもアクセスし、Bootstrap の CSSファイルが表示されることも確かめましょう。

# サーバ側のセットアップ

まずは```cd```で```app```ディレクトリに移動します。

```
cd ../app
```

```express```, ```serve-static```, ```proxy-middleware```, ```morgan```, ```jade``` を ```--save``` でインストールします。

```
npm install --save express serve-static proxy-middleware morgan jade
```

```nodemon``` を ```--save-dev``` でインストールします。

```
npm install --save-dev nodemon
```

ルータを格納する ```routes``` ディレクトリを作成します。

```
mkdir routes
```

```routes``` ディレクトリ内に静的ページを表示するためのルータを```pages.js```という名前で作成します。

```
touch routes/pages.js
```

```pages.js``` の内容は次のようにします。

```pages.js
'use strict';

module.exports = {
  anonymous: {
    home: anonymousHome,
  },
}

function anonymousHome() {
  return function (req, res) {
    res.render('pages/anonymous-home.jade')
  }
}

```

```app``` ディレクトリ内に ```index.js``` を作成します。内容は下記の通り。

```index.js
'use strict';

var env = process.env.NODE_ENV || 'development'

var url = require('url')
var path = require('path')
var morgan = require('morgan')
var express = require('express')
var serveStatic = require('serve-static')
var proxyMiddleware = require('proxy-middleware')
var pages = require('./routes/pages')

module.exports = factory

function factory(options) {
  options = options || {}

  var staticPath = options.staticPath
  var app = express()

  app.set('strict routing', true)
  app.set('views', path.join(__dirname, 'views'))
  app.set('view engine', 'jade')

  app.locals.baseUrl = ''

  app.use(morgan())
  app.get('/', pages.anonymous.home())

  if (env === 'development') {
    app.use('/static', proxyMiddleware(url.parse('http://127.0.0.1:8080')))
  } else {
    app.use('/static', serveStatic(staticPath))
  }

  return app
}

```

```views``` ディレクトリと ```bin``` ディレクトリを作成します。

```
mkdir views bin
```

```views``` ディレクトリ内に ```pages``` ディレクトリを作成します。

```
mkdir views/pages
```

```views/pages``` ディレクトリ内に ```anonymous-home.jade``` を作成します。内容は下記の通り。

```anonymous-home.jade
doctype
html(lang='ja')
  head
    meta(charset='UTF-8')
    meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
    title Nippo
    meta(name='description', content='')
    meta(name='viewport', content='width=device-width, initial-scale=1')
    link(rel='stylesheet', href='#{baseUrl}/static/css/bootstrap.min.css')
    link(rel='stylesheet', href='#{baseUrl}/static/css/bootstrap-theme.min.css')
    script(src='#{baseUrl}/static/js/vendor/modernizr-2.8.3.min.js')
  body
    p Nippo
    script(src='#{baseUrl}/static/js/vendor/jquery-1.11.2.min.js')
    script(src='#{baseUrl}/static/js/vendor/bootstrap.min.js')
    script(src='#{baseUrl}/static/js/bundle.js')
```

```bin``` ディレクトリ内に ```www``` を作成します。内容は次の通り。

```www
#!/usr/bin/env node

'use strict';

var port = Number.parseInt(process.env.PORT || '3000', 10)

var http = require('http')
var factory = require('../index')

var app = factory()
var server = http.createServer(app)

server.listen(port, function () {
  console.log('Listening on ' + port)
})

```

```package.json``` を次のように編集します。

```package.json(変更前)
{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "nodemon": "^1.7.1"
  },
  "dependencies": {
    "express": "^4.13.3",
    "jade": "^1.11.0",
    "morgan": "^1.6.1",
    "proxy-middleware": "^0.14.0",
    "serve-static": "^1.10.0"
  }
}

```

```package.json(変更後)
{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node_modules/.bin/nodemon bin/www",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "nodemon": "^1.7.1"
  },
  "dependencies": {
    "express": "^4.13.3",
    "jade": "^1.11.0",
    "morgan": "^1.6.1",
    "proxy-middleware": "^0.14.0",
    "serve-static": "^1.10.0"
  }
}

```

```npm start``` でWebサーバを起動します。

```
npm start
```

http://localhost:3000/ にアクセスして ```Nippo``` というコンテンツが表示され、コンソールに ```entry.js``` と表示されたらセットアップは完了です、お疲れさまでした。

# おわりに
Qiitaのエディタに自動保存機能がなかったらこの記事が公表されることはありませんでした。Qiitaの開発者さん、ありがとう。