Edited at

node.jsとRubyで作るWindows向けフロントエンド開発環境

More than 3 years have passed since last update.

自身はMacを使っているのだけど、Windows向けの開発環境を作る必要があったため作ってみた。つらかった。


やりたいこと


  • Jadeのコンパイル

  • Sassのコンパイル


    • node-sass/libsass + compass



  • 画像の最適化

  • ローカルにHTTPサーバを立てて確認できる

  • LiveReload


node.js/npm

node.jsとnpmを以下から持ってきた。node.jsは最新安定版の0.10.36を、npmは2.0系を使いたかったのだけど1.4.12までしかなかったので、これを入れてupdateすることに。


使ったモジュール

シェルスクリプトは当然動かない(Bashを入れれば別かもしれないけど)し、たまにはGruntでなくてgulpを使ってみるか、ということでgulpを使った。


  • coffee-script


    • gulpfile.coffeeで書くため



  • gulp


    • 本体、npm-scriptsから実行できるようにするため



  • gulp-cached


    • 変更のあったファイルだけを対象にフィルターしてくれる



  • gulp-imagemin


    • 画像の最適化



  • gulp-jade


    • Jadeのコンパイル



  • gulp-notify


    • 通知してくれる



  • gulp-plumber


    • watchでコンパイルエラーが出てもwatchが続くようにしてくれる



  • gulp-sass


    • Sassのコンパイル



  • gulp-util


    • ユーティリティ



  • gulp-watch


    • ファイル監視



  • gulp-webserver


    • HTTPサーバ + LiveReload



  • serve-static


    • ファイルをいい感じに返してくれるミドルウェア




package.json

npm 2.0でnpm startから引数を渡して使いたいのでstartにgulpのコマンドを書いてる。


package.json

{

"private": true,
"scripts": {
"start": "gulp --require coffee-script/register"
},
"devDependencies": {
"coffee-script": "^1.8.0",
"gulp": "^3.8.10",
"gulp-cached": "^1.0.2",
"gulp-imagemin": "^2.1.0",
"gulp-jade": "^0.11.0",
"gulp-notify": "^2.2.0",
"gulp-plumber": "^0.6.6",
"gulp-sass": "^1.3.2",
"gulp-util": "^3.0.2",
"gulp-watch": "^4.1.0",
"gulp-webserver": "^0.9.0",
"serve-static": "^1.8.1"
}
}


gulpfile.coffee

なんかこんな感じ。serve-staticを使ったのは、ディレクトリが2つあって片方のディレクトリにファイルがなかったらもう片方を見に行って欲しかったため。


gulpfile.coffee

# serve directories

viewDirectory = '../views'
webrootDirectory = '../webroot'

# 出力先
jadeOutput = '../views'
sassOutput = '../webroot/css'
imageOutput = '../webroot/image'

# 先頭が_で始まるファイル(インクルードされるファイルを想定)は無視
# 一方で、インクルードファイルを更新してもwatchでコンパイルされないというデメリットがある
# ぐぬぬ
jadeTarget = './jade/**/!(_)*.jade'
sassTarget = './scss/**/!(_)*.scss'

# gif, jpg, jpeg, pngを最適化
imageTarget = './image/**/*.{gif,jpg,jpeg,png}'

exec = require('child_process').exec

gulp = require 'gulp'
util = require 'gulp-util'
jade = require 'gulp-jade'
sass = require 'gulp-sass'
image = require 'gulp-imagemin'
watch = require 'gulp-watch'
server = require 'gulp-webserver'
cached = require 'gulp-cached'
notify = require 'gulp-notify'
plumber = require 'gulp-plumber'

serve = require 'serve-static'

if util.env.production
jadeOption =
debug: false
pretty: true
sassOption =
outputStyle: 'compressed'
sourceComments: false
else
jadeOption =
debug: true
pretty: true
sassOption =
outputStyle: 'nested'
sourceComments: true

gulp.task 'jade', ->
gulp
.src(jadeTarget)
.pipe(plumber(errorHandler: notify.onError('<%= error.message %>')))
.pipe(cached('jade'))
.pipe(jade(jadeOption))
.pipe(gulp.dest(jadeOutput))

gulp.task 'sass', ->
if util.env.compass
command =
if util.env.production
then 'compass compile --config config.rb --environment production --force'
else 'compass compile --config config.rb'
p = exec(command, (err, stdout, stderr) ->
util.log(err) if err
util.log(stdout)
util.log(stderr)
)
p.on('error', (err) -> util.log(err))
else
gulp
.src(sassTarget)
.pipe(plumber(errorHandler: notify.onError('<%= error.message %>')))
.pipe(cached('sass'))
.pipe(sass(sassOption))
.pipe(gulp.dest(sassOutput))

gulp.task 'image', ->
gulp
.src(imageTarget)
.pipe(plumber(errorHandler: notify.onError('<%= error.message %>')))
.pipe(cached('image'))
.pipe(image(progressive: false))
.pipe(gulp.dest(imageOutput))

gulp.task 'watch', ->
if util.env.compass
p = exec('compass watch --config config.rb', (err, stdout, stderr) ->
util.log(err) if err
util.log(stdout)
util.log(stderr)
)
p.on('error', (err) -> util.log(err))
process.on('exit', (code) -> p.kill('SIGINT'))
else
watch(sassTarget, -> gulp.start('sass'))

watch(jadeTarget, -> gulp.start('jade'))
watch(imageTarget, -> gulp.start('image'))

return

gulp.task 'server', ->
gulp
.src('.')
.pipe(server(
livereload: true
middleware: [
serve(webrootDirectory)
serve(viewDirectory)
]
))

gulp.task 'compile', ['jade', 'sass', 'image']
gulp.task 'develop', ['server', 'watch']
gulp.task 'default', ['server', 'watch']



Ruby/RubyGems

Ruby 2.1.5を以下から持ってきた。7zじゃなくてzipだったらもっと楽だったんだけどな……

それとpemを入れてあげないとrubygemsからgemがインストールできないので入れておく。


バッチファイル

手順書なんて書いても誰も実行してくれないのは目に見えているので、ダブルクリックで全て済むようにバッチファイルをいくらか書いた。


env.bat

@echo off

set PATH="%~dp0\bin\node";%PATH%
set NODE_PATH="%~dp0\bin\node\node_modules\npm\node_modules;%~dp0\bin\node\node_modules\npm";%NODE_PATH%

set PATH="%~dp0\bin\ruby\bin";"%~dp0\bin\ruby\gem\bin";%PATH%
set FULLPATH=%~dp0
set GEM_HOME=%FULLPATH:\=/%/bin/ruby/gem
set GEM_PATH=%FULLPATH:\=/%/bin/ruby/gem

rem vim:ff=dos:


環境変数を設定するバッチファイル。ポータブルな感じにしたかったので、%~dp0祭りをしている。GEM_HOMEなどはバックスラッシュだと駄目みたいなのでスラッシュに変えてある。

ん、ダブルクォートで囲んでいたのが駄目だっただけで、スラッシュでなくバックスラッシュでも行けるのかもしれない。面倒なので試さない。


setup.bat

call env.bat

call npm.cmd install -g npm
call npm.cmd install

call gem.bat update --no-document --system
call gem.bat install compass --no-document --version 1.0.3

rem vim:ff=dos:


アップデートしたりgemを入れたりとか。


develop.bat

call env.bat

call npm.cmd start -- develop

rem vim:ff=dos:


watchするやつ。


develop-compass.bat

call env.bat

call npm.cmd start -- develop --compass

rem vim:ff=dos:


上のcompass版。


環境構築

setup.batをダブルクリックするだけ。


一応、動くっぽいということは確認できた。ただ、LiveReloadは動作しなかったと思う。


というのをbuild-envに作って置いておいた。

バッチファイルはほとんど忘れていた。あとMacを使って欲しいと思った。

WindowsでRubyものすごいつらそう、と思ったけどこの程度の用途なら普通に使えるっぽいことがわかってよかった。

Bundlerをいつも使うのでGEM_HOMEを切り替えればRubyGemsだけでもGemのインストール先を切り替えられるのを知れてよかった(?)


作ったのはいいけど使ってくれるんだろうか。