LoginSignup
28
28

More than 5 years have passed since last update.

Expressの最小構成(ES2015 + Browserify + Watchify + Stylus + Jade)

Last updated at Posted at 2016-04-26

Expressで簡単なプロダクトを作る時のオレオレ最小構成です。

要件

  • サーバーサイドもクライアントサイドもES2015(ES6)で書く
    • サーバーサイドはNode.jsがv4以上だとES2015で書けるはず
      importなどが使えないと知ったので、babel-nodeを使います
    • クライアントサイドJSはBrowserify + Babelifyでコンパイルする
    • 開発時はWatchifyする
    • ビルド時はUglifyする
  • CSSはStylusで書く
    • StylusはExpressのMiddlewareで都度コンパイルする
    • ライブラリはkouto-swissを使う
    • ベンダープレフィックスはautoprefixerでつける
  • ViewはJadeで書く
    • サーバーからJadeに変数を渡したりする
  • Gulpなどのタスクランナーは使わない
    • $ npm run xxxでやる
    • 画像のSprite化とかするならGulp使ったほうがいいでしょう

ディレクトリ構成

.
├── .gitignore
├── README.md
├── app.js
├── assets
│   ├── javascripts
│   │   ├── index.js
│   │   ├── index_dev.js
│   └── stylesheets
│       └── style.styl
├── package.json
└── views
    └── index.jade

ディレクトリ構成はこんな感じです。

npm install

$ npm initしてからインストールするNode package一覧です。
Browserifyとかは$ npm install -gしないと動かないかも。

$ npm install --save autoprefixer-stylus express jade jquery kouto-swiss path stylus
$ npm install --save-dev babel-cli babel-preset-es2015 babelify browserify uglifyjs watchify
$ npm install --global babel-cli babel-preset-es2015 babelify browserify uglifyjs watchify

ファイルのテンプレート

app.js

サーバーのJavaScrptです。
/へのアクセスでindexを返します。あとはres.render()の中でViewに値を渡しています。
他はStylusを使う設定とか。

app.js
'use strict';

import express from 'express';
const app = express();
import path from 'path';
import stylus from 'stylus';
import koutoSwiss from 'kouto-swiss';
import autoprefixer from 'autoprefixer-stylus';

app.set('port', 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(stylus.middleware({
  src: path.join(__dirname, 'assets'),
  compile: (str, path) => {
    return stylus(str)
      .set('filename', path)
      .set('compress', true)
      .use(koutoSwiss())
      .use(autoprefixer({ browsers: ['last 2 versions'] }))
    ;
  }
}));
app.use(express.static(path.join(__dirname, 'assets')));

app.get('/', (req, res) => {
  res.render('index', {
    title: 'App Title',
    description: 'App Description'
  });
});

app.listen(app.get('port'), (error) => {
  if (error) {
    console.error(error);
  } else {
    console.info('listen:', app.get('port'));
  }
});

assets/javascripts/index_dev.js

クライアントサイドのJavaScriptです。命名は自由だけど、コンパイル後のファイルがindex.jsなので、index_dev.jsにしました。同じファイル名でフォルダを分けたほうがいいかも。
jQueryを読みこんだり、ES2015の記法を使ったり。

assets/javascripts/index_dev.js
'use strict';

window.jQuery = window.$ = require('jquery');

(() => {
  const hello = () => {
    const _message = 'Hello World!';
    console.log(_message);
  };

  $(() => {
    hello();
  });
})();

views/index.jade

viewです。サーバーから送られたtitledescriptionを受け取り、表示しています。
テンプレートにOGPのmetaタグも入れておくと、後でラク。

views/index.jade
<!DOCTYPE html>
html(lang='ja', prefix='og: http://ogp.me/ns#')
  head
    meta(charset='UTF-8')
    title!= title

    meta(name='description', content='#{description}')
    meta(name='robots', content='index,follow')
    meta(name='viewport', content='width=device-width')
    meta(property='og:title', content='#{title}')
    meta(property='og:type', content='website')
    meta(property='og:url', content='#{url}')
    meta(property='og:description', content='#{description}')
    meta(property='og:site_name', content='#{title}')
    //- meta(property='og:image', content='#{url}/images/ogp.jpg')
    meta(property='og:locale', content='ja_JP')
    meta(name='twitter:card', content='summary')

    link(rel='stylesheet', href='stylesheets/style.css')
    script(src='javascripts/index.js')

  body
    h1 #{title}
    p #{description}

.babelrc

Babelifyの設定ファイルです。ES2015のモジュールを読み込みます。

.babelrc
{
  "presets": ["es2015"]
}

npm run-script

$ npm run xxxで実行するコマンドです。package.jsonに書きます。

package.json
{
  "scripts": {
    "build": "browserify -t babelify assets/javascripts/index_dev.js -o assets/javascripts/index.js",
    "watch": "npm run build && watchify -d -t babelify assets/javascripts/index_dev.js -o assets/javascripts/index.js -v",
    "build:prod": "npm run build && uglifyjs assets/javascripts/index.js --stats -o assets/javascripts/index.js",
    "start": "babel-node app.js"
  }
}
  • 開発時は$ npm startでサーバーを起動して、別プロセスで$ npm run watchをします。index_dev.jsの変更が監視され、都度index.jsが出力されます。
    • $ npm startではnode app.jsではなくbabel-node app.jsを実行します。babel-nodeだと、ES2015のimportなどが使えるようになります(Node.js v4以降でもletconst、アロー関数は使えますが)。
  • 本番用のビルドは$ npm run build:prodを実行します。BrowserifyとUglifyが実行されます。
  • Sourcemap忘れてた…。余力があれば書き出すようにする(CSS/JSどっちも)
    • JSだけSourcemap出力します(npm run watch時)
    • StylusのSourcemapがなぜか出力できない、謎
  • ESLintも忘れてるので、おいおい

まとめ

以下の最小構成のようにもっとコンパクトにできるけど、なにか作るかとなると結局こんな感じになるかな、と。JSをES5で書いてStylusを使わずに生CSSで書けばもっとコードは減らせますが、実際辛い。

ここから、ルーティングやエラー処理を加えたり、処理が増えたらJSを分割するなどをしていけばいいかなと思います。

参考

expressを最小構成で試す - Qiita

28
28
2

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
28
28