package.jsonをどう書けばいいのかよくわからない・・・。jade, coffee-script, stylusだけをgitで管理し、gruntでビルドしたjs, css, bower_componentsとかは、gitで管理する必要がない。流れ的には下記の通り。
jade, stylus, coffee-scriptで開発。 gruntで更新ファイルを監視し、jadeはcopy、stylusはcssへ、coffee-scriptはjsへ。 gitで管理するのは、1.のファイルたち。 Herokuへdeploy。 gruntが実行して、1.のファイルたちが2.になってサーバーが動く。 この流れに行き着くまでに色々理由がある。
coffeeファイルでNode.jsを動かしてもいいが、syntaxerrorが事前にわかりにくい。 → grunt-coffeelintで文法チェックをする → 文法チェックしても動くかどうかはわからない。 → やっぱりjsファイルにしてから動作確認したい。 grunt-autoprefixerを使えば、-webkit, -mozなどを書かなくても保管してくれる。 → stylusには効かない。 → stylusからcssに変換してからautoprefixerを掛ける。 Herokuへdeployするにはgitで管理しているファイルに限る。 → gruntで書きだしたファイルをgitで管理する?いやそれはない。 → gruntで書きだす前のファイルをgitで管理しないと意味がない。
Herokuへdeployする時にgruntを動かしたい。 → 方法としては、package.jsonのscriptにpostinstallを追記する。 → または、Herokuが提供しているbuildpackを使ってgruntを叩くようにheroku configで設定をする。
4.の項目に関して、具体的なpackage.jsonは下記の通り。
package.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 {
"name": "test",
"version": "0.0.1",
"engines": {
"node": "0.10.x"
},
"private": false,
"scripts": {
"start": "node ./dist/bin/www",
"postinstall": "./node_modules/grunt-cli/bin/grunt build"
},
"dependencies": {
"express": "~4.2.0",
"static-favicon": "~1.0.0",
"morgan": "~1.0.0",
"cookie-parser": "~1.0.1",
"body-parser": "~1.0.0",
"debug": "~0.7.4",
"jade": "~1.3.0",
"stylus": "0.42.3",
"grunt": "^0.4.5",
"grunt-cli": "^0.1.13"
},
"devDependencies": {
"grunt-autoprefixer": "^0.8.1",
"grunt-connect-proxy": "^0.1.10",
"grunt-contrib-clean": "^0.5.0",
"grunt-contrib-coffee": "^0.10.1",
"grunt-contrib-connect": "^0.8.0",
"grunt-contrib-copy": "^0.5.0",
"grunt-contrib-imagemin": "^0.7.1",
"grunt-contrib-stylus": "^0.18.0",
"grunt-contrib-watch": "^0.6.1",
"grunt-express-server": "^0.4.17",
"grunt-newer": "^0.7.0",
"grunt-bower-task": "^0.3.4",
"load-grunt-tasks": "^0.6.0"
}
}
9,10行目に書かれている項目がいつもと少し違います。express v3からwwwというファイルをstartの項目に書いて、Node.jsを起動する方法になりました。そのパスの最初にdistを指定しているのは、gruntがビルドしたディレクトリを指していますので、distというディレクトリにしています。ここは任意になりますね。
10行目は、Herokuにdeployした時に実行するgruntコマンドが書いてあります。deploy時に実行したいコマンドをGruntfileに書いてあれば、ここの項目が実行されます。
さて、コレを実際にデプロイするとどうなるか。
command 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 > test@0.0.1 postinstall /tmp/build_63e5029d-35ad-4574-8b0b-60718f56b4c8
> ./node_modules/grunt-cli/bin/grunt build
sh: ./node_modules/grunt-cli/bin/grunt: not found
npm ERR! test@0.0.1 postinstall: `./node_modules/grunt-cli/bin/grunt build`
npm ERR! Exit status 127
npm ERR!
npm ERR! Failed at the test@0.0.1 postinstall script.
npm ERR! This is most likely a problem with the grunt-express-coffee package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! ./node_modules/grunt-cli/bin/grunt build
npm ERR! You can get their info via:
npm ERR! npm owner ls grunt-express-coffee
npm ERR! There is likely additional logging output above.
npm ERR! System Linux 3.8.11-ec2
npm ERR! command "/tmp/build_63e5029d-35ad-4574-8b0b-60718f56b4c8/vendor/node/bin/node" "/tmp/build_63e5029d-35ad-4574-8b0b-60718f56b4c8/vendor/node/bin/npm" "install" "--userconfig" "/tmp/build_63e5029d-35ad-4574-8b0b-60718f56b4c8/.npmrc"
npm ERR! cwd /tmp/build_63e5029d-35ad-4574-8b0b-60718f56b4c8
npm ERR! node -v v0.10.30
npm ERR! npm -v 1.4.21
npm ERR! code ELIFECYCLE
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /tmp/build_63e5029d-35ad-4574-8b0b-60718f56b4c8/npm-debug.log
npm ERR! not ok code 0
こんな感じでエラーになっちゃうんですよね。要はgruntが実行できないですよと怒られているわけです。これの原因は、packega.jsonにあります。
package.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "dependencies": {
"express": "~4.2.0",
"static-favicon": "~1.0.0",
"morgan": "~1.0.0",
"cookie-parser": "~1.0.1",
"body-parser": "~1.0.0",
"debug": "~0.7.4",
"jade": "~1.3.0",
"stylus": "0.42.3"
},
"devDependencies": {
"grunt": "^0.4.5",
"grunt-cli": "^0.1.13",
....
}
dependenciesがdeploy時に必要なmoduleをインストールする項目なので、ここにgruntを書いてないので、gruntが実行できない。ということです。そしたらここに書いてまえ!と、
package.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "dependencies": {
"express": "~4.2.0",
"static-favicon": "~1.0.0",
"morgan": "~1.0.0",
"cookie-parser": "~1.0.1",
"body-parser": "~1.0.0",
"debug": "~0.7.4",
"jade": "~1.3.0",
"stylus": "0.42.3",
"grunt": "^0.4.5",
"grunt-cli": "^0.1.13"
},
"devDependencies": {
....
}
devDependenciesの中にあるgrunt, grunt-cliをdependenciesに移しました。これでHerokuへdeployすると、激しくログが出て、結果こけます。そのログの途中でERRORが出てました。
command 1 2 3 Loading "Gruntfile.coffee" tasks...ERROR
>> Error: Cannot find module 'load-grunt-tasks'
Warning: Task "build" not found. Use --force to continue.
gruntタスクを読み込むためのload-grunt-tasksがないですよーと怒られました。んではまた、dependenciesに書いてみます。
package.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 "dependencies": {
"express": "~4.2.0",
"static-favicon": "~1.0.0",
"morgan": "~1.0.0",
"cookie-parser": "~1.0.1",
"body-parser": "~1.0.0",
"debug": "~0.7.4",
"jade": "~1.3.0",
"stylus": "0.42.3",
"grunt": "^0.4.5",
"grunt-cli": "^0.1.13",
"load-grunt-tasks": "^0.6.0"
},
"devDependencies": {
....
}
さて、これでdeployしてどうなるかな・・・ってまた激しくログが出て、途中でERRORが出ていました。
command 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 >> Local Npm module "grunt-autoprefixer" not found. Is it installed?
>> Local Npm module "grunt-connect-proxy" not found. Is it installed?
>> Local Npm module "grunt-contrib-clean" not found. Is it installed?
>> Local Npm module "grunt-contrib-coffee" not found. Is it installed?
>> Local Npm module "grunt-contrib-connect" not found. Is it installed?
>> Local Npm module "grunt-contrib-copy" not found. Is it installed?
>> Local Npm module "grunt-contrib-imagemin" not found. Is it installed?
>> Local Npm module "grunt-contrib-stylus" not found. Is it installed?
>> Local Npm module "grunt-contrib-watch" not found. Is it installed?
>> Local Npm module "grunt-express-server" not found. Is it installed?
>> Local Npm module "grunt-newer" not found. Is it installed?
>> Local Npm module "grunt-bower-task" not found. Is it installed?
Warning: Task "clean" not found. Use --force to continue.
Aborted due to warnings.
もう全然moduleが足りないってことね笑。ってことは、どうなるかというと、package.jsonの中身はこうなります。
package.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 {
"name": "test",
"version": "0.0.1",
"engines": {
"node": "0.10.x"
},
"private": false,
"scripts": {
"start": "node ./dist/bin/www",
"postinstall": "./node_modules/grunt-cli/bin/grunt build"
},
"dependencies": {
"express": "~4.2.0",
"static-favicon": "~1.0.0",
"morgan": "~1.0.0",
"cookie-parser": "~1.0.1",
"body-parser": "~1.0.0",
"debug": "~0.7.4",
"jade": "~1.3.0",
"stylus": "0.42.3",
"grunt": "^0.4.5",
"grunt-cli": "^0.1.13",
"grunt-autoprefixer": "^0.8.1",
"grunt-connect-proxy": "^0.1.10",
"grunt-contrib-clean": "^0.5.0",
"grunt-contrib-coffee": "^0.10.1",
"grunt-contrib-connect": "^0.8.0",
"grunt-contrib-copy": "^0.5.0",
"grunt-contrib-imagemin": "^0.7.1",
"grunt-contrib-stylus": "^0.18.0",
"grunt-contrib-watch": "^0.6.1",
"grunt-express-server": "^0.4.17",
"grunt-newer": "^0.7.0",
"grunt-bower-task": "^0.3.4",
"load-grunt-tasks": "^0.6.0"
}
}
devDependenciesの項目が全然なくなってしまうんですよね!これでdeployすると、無事にdeploy完了しました!ワーイヽ(゚∀゚)メ(゚∀゚)メ(゚∀゚)ノワーイ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 > ./node_modules/grunt-cli/bin/grunt build
Running "clean:dist" (clean) task
Running "bower:install" (bower) task
>> Installed bower packages
>> Copied packages to /tmp/build_dbb97ba9-1171-42e5-aa62-d7acea76c359/lib
Running "stylus:dist" (stylus) task
File dist/public/stylesheets/style.css created.
Running "autoprefixer:dist" (autoprefixer) task
File dist/public/stylesheets/style.css created.
Running "coffee:dist" (coffee) task
Running "copy:jade" (copy) task
Copied 3 files
Running "copy:img" (copy) task
Running "copy:bin" (copy) task
Created 1 directories, copied 1 files
Running "copy:vendors" (copy) task
Running "copy:bower_components" (copy) task
Running "imagemin:dist" (imagemin) task
Minified 0 images (saved 0 B)
Done, without errors.
deployログの途中にも、ちゃんとgruntのログがでて、Welcome to Express画面も確認できました。
まとめますと、今回しようしたGruntfileはこちらです。
Gruntfile.coffee 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 'use strict'
mountFolder = folderMount = (connect, base) ->
connect['static'] require('path').resolve(base)
listen = 8000
server = 3000
module.exports = (grunt) ->
require('load-grunt-tasks')(grunt)
grunt.initConfig
pkg: grunt.file.readJSON('package.json')
# Metadata.
banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today(\'yyyy-mm-dd\') %>\n' + '<%= pkg.homepage ? \'* \' + pkg.homepage + \'\\n\' : \'\' %>' + '* Copyright (c) <%= grunt.template.today(\'yyyy\') %> <%= pkg.author.name %>;' + ' Licensed <%= _.pluck(pkg.licenses, \'type\').join(\', \') %> */\n'
dir:
src: 'app'
styl: 'stylesheets'
coffee: 'javascripts'
images: 'images'
js: 'javascripts'
css: 'stylesheets'
img: 'images'
vendors: 'vendors'
dist: 'dist'
build: 'build'
docs: 'docs'
test: 'test'
bower:
install:
options:
install: true
cleanTargetDir: false
cleanBowerDir: false
stylus:
dist:
options:
compress: false
expand: true
cwd: '<%= dir.src %>'
src: '**/*.styl'
dest: '<%= dir.dist %>'
ext: '.css'
coffee:
dist:
option:
pretty: true
expand: true
cwd: '<%= dir.src %>'
src: '**/*.coffee'
dest: '<%= dir.dist %>'
ext: '.js'
# coffeeの文法チェック
coffeelint:
app: '<%= dir.src %>/**/*.coffee'
# CSSのprefiexを補完
autoprefixer:
options:
browsers: ['last 2 version', 'ie 8', 'ie 7', 'ie 6']
dist:
expand: true
cwd: '<%= dir.dist %>'
src: '**/*.css'
dest: '<%= dir.dist %>'
ext: '.css'
# 画像の圧縮
imagemin:
options:
optimizationLevel: 7
pngquant: false
dist:
expand: true
cwd: '<%= dir.dist %>/<%= dir.images %>'
src: '**/*.{jpg,jpeg,gif}'
dest: '<%= dir.dist %>/<%= dir.img %>'
copy:
jade:
expand: true
dot: true
cwd: '<%= dir.src %>'
dest: '<%= dir.dist %>'
src: '**/*.jade'
bin:
expand: true
cwd: '<%= dir.src %>/bin'
dest: '<%= dir.dist %>/bin'
src: '**'
img:
expand: true
dot: true
cwd: '<%= dir.src %>'
dest: '<%= dir.dist %>'
src: [
'**/*.{gif,jpeg,jpg,png,svg,webp}',
]
vendors:
expand: true
dot: true
cwd: '<%= dir.src %>/public/vendors'
dest: '<%= dir.dist %>/public/vendors'
src: '**'
bower_components:
expand: true
dot: true
cwd: '<%= dir.src %>/bower_components'
dest: '<%= dir.dist %>/bower_components'
src: ['**']
connect:
front:
options:
host: 'localhost'
port: listen
middleware: (connect) ->
[
mountFolder(connect, '.')
proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest
]
open:
target: 'http://localhost:' + listen
livereload: true
proxies: [
context: '/'
host: 'localhost'
port: server + ''
https: false
changeOrigin: false
]
express:
dev:
options:
background: true
port: server
cmd: 'supervisor'
args: []
script: '<%= dir.dist %>/bin/www'
delay: 0
watch:
options:
livereload: true
jade:
files: '<%= dir.src %>/**/*.jade',
tasks: 'newer:copy:jade'
stylus:
files: '<%= dir.src %>/**/*.styl'
tasks: [
'newer:stylus:dist',
'newer:autoprefixer:dist',
]
coffee:
files: '<%= dir.src %>/**/*.coffee'
tasks: 'newer:coffee:dist'
images:
files: ['<%= dir.src %>/**/*.{gif,jpeg,jpg,png,svg,webp}']
tasks: ['newer:imagemin:dist', 'copy', 'imagemin']
vendors:
files: ['<%= dir.src %>/public/vendors']
tasks: ['copy:vendors']
bower_components:
files: ['<%= dir.src %>/bower_components']
tasks: ['copy:bower_components']
express:
files: [
'<%= dir.dist %>/app.js'
'<%= dir.dist %>/routes/**/*.js'
'<%= dir.dist %>/views/**/*.jade'
]
tasks: ['express:dev']
options:
livereload: true
veiw:
files: ['<%= dir.dist %>/public/**/*.{js,css}']
clean:
dist:
src: [
'<%= dir.dist %>'
]
grunt.registerTask 'server', [
'configureProxies'
'express:dev'
'connect:front'
'watch'
]
grunt.registerTask 'default', [
'clean'
'bower:install'
'stylus:dist'
'autoprefixer'
'coffee:dist'
'copy:jade'
'copy:img'
'copy:bin'
'copy:vendors'
'copy:bower_components'
'imagemin'
]
grunt.registerTask 'dev', [
'default'
'configureProxies'
'express:dev'
'connect:front'
'watch'
]
grunt.registerTask 'build', [
'default'
]
package.jsonはこちら。
package.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 {
"name": "grunt-express-coffee",
"version": "0.0.1",
"engines": {
"node": "0.10.x"
},
"private": false,
"scripts": {
"start": "node ./dist/bin/www",
"postinstall": "./node_modules/grunt-cli/bin/grunt build"
},
"dependencies": {
"express": "~4.2.0",
"static-favicon": "~1.0.0",
"morgan": "~1.0.0",
"cookie-parser": "~1.0.1",
"body-parser": "~1.0.0",
"debug": "~0.7.4",
"jade": "~1.3.0",
"stylus": "0.42.3",
"grunt": "^0.4.5",
"grunt-cli": "^0.1.13",
"grunt-autoprefixer": "^0.8.1",
"grunt-connect-proxy": "^0.1.10",
"grunt-contrib-clean": "^0.5.0",
"grunt-contrib-coffee": "^0.10.1",
"grunt-contrib-connect": "^0.8.0",
"grunt-contrib-copy": "^0.5.0",
"grunt-contrib-imagemin": "^0.7.1",
"grunt-contrib-stylus": "^0.18.0",
"grunt-contrib-watch": "^0.6.1",
"grunt-express-server": "^0.4.17",
"grunt-newer": "^0.7.0",
"grunt-bower-task": "^0.3.4",
"load-grunt-tasks": "^0.6.0"
}
}
ちょっと待てよ・・・。ホンマにこのpackage.jsonでええんやろか・・・。gruntは基本、devDependenciesに書いてあることが多いので、違和感があるだけなんやろうか・・・。実際にこれがベストプラクティスなんかはわからないので、どなたか賢くてエロい方、ご教授いただければ幸いです。