package.jsonをどう書けばいいのかよくわからない・・・。jade, coffee-script, stylusだけをgitで管理し、gruntでビルドしたjs, css, bower_componentsとかは、gitで管理する必要がない。流れ的には下記の通り。

  1. jade, stylus, coffee-scriptで開発。
  2. gruntで更新ファイルを監視し、jadeはcopy、stylusはcssへ、coffee-scriptはjsへ。
  3. gitで管理するのは、1.のファイルたち。
  4. Herokuへdeploy。
  5. gruntが実行して、1.のファイルたちが2.になってサーバーが動く。

この流れに行き着くまでに色々理由がある。

  1. coffeeファイルでNode.jsを動かしてもいいが、syntaxerrorが事前にわかりにくい。
    → grunt-coffeelintで文法チェックをする
    → 文法チェックしても動くかどうかはわからない。
    → やっぱりjsファイルにしてから動作確認したい。
  2. grunt-autoprefixerを使えば、-webkit, -mozなどを書かなくても保管してくれる。
    → stylusには効かない。
    → stylusからcssに変換してからautoprefixerを掛ける。
  3. Herokuへdeployするにはgitで管理しているファイルに限る。 → gruntで書きだしたファイルをgitで管理する?いやそれはない。
    → gruntで書きだす前のファイルをgitで管理しないと意味がない。
  4. Herokuへdeployする時にgruntを動かしたい。
    → 方法としては、package.jsonのscriptにpostinstallを追記する。
    → または、Herokuが提供しているbuildpackを使ってgruntを叩くようにheroku configで設定をする。

4.の項目に関して、具体的なpackage.jsonは下記の通り。

{
  "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に書いてあれば、ここの項目が実行されます。

さて、コレを実際にデプロイするとどうなるか。

       > 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にあります。

  "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が実行できない。ということです。そしたらここに書いてまえ!と、

  "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が出てました。

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に書いてみます。

  "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が出ていました。

       >> 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の中身はこうなります。

{
  "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完了しました!ワーイヽ(゚∀゚)メ(゚∀゚)メ(゚∀゚)ノワーイ

       > ./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はこちらです。

'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はこちら。

{
  "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に書いてあることが多いので、違和感があるだけなんやろうか・・・。実際にこれがベストプラクティスなんかはわからないので、どなたか賢くてエロい方、ご教授いただければ幸いです。

Node.jsをHerokuへdeployした時にGruntを実行させるとき
Pocket

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です