Stocks and Flows

やったこと、考えたことの記録

Yeomanで生成したAngularJSアプリをherokuでデプロイする

この投稿の目的は以下2つの記録。主に後者。

  1. Sass入れてYeoman使う場合に詰まったところ
  2. Yeomanで作ったAngularJSアプリをherokuにデプロイ

1. 前提+事前準備

$ gem update sass compass #=> これをしておかないとSass入れる場合につまづく
$ node -v #=> v0.10.30
$ yo -v #=> 1.2.1
$ bower cache clean #=> 一応念のため
$ npm cache clean

あとherokuアカウント+SDKも必要

2. Scaffolding

$ mkdir yo-angular-heroku && cd yo-angular-heroku
$ yo angular # 色々聞かれるのは全部YES/デフォルト

     _-----_
    |       |    .--------------------------.
    |--(o)--|    |    Welcome to Yeoman,    |
   `---------´   |   ladies and gentlemen!  |
    ( _´U`_ )    '--------------------------'
    /___A___\
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

Out of the box I include Bootstrap and some AngularJS recommended modules.

? Would you like to use Sass (with Compass)?: Yes
? Would you like to include Bootstrap?: Yes
? Would you like to use the Sass version of Bootstrap?: Yes
? Which modules would you like to include?: (Press <space> to select)
❯ⓧ angular-animate.js #=> デフォルトでEnter
 ⓧ angular-cookies.js
 ⓧ angular-resource.js
 ⓧ angular-route.js
 ⓧ angular-sanitize.js
 ⓧ angular-touch.js

3. ローカルで起動

$ npm install
$ grunt serve
Running "wiredep:app" (wiredep) task
Warning: ENOENT, no such file or directory '/Users/myname/Desktop/yo-angular-heroku/app/bower.json' Use --force to continue. #=> エラー

このエラーを解決するには、package.json内のgrunt-wiredepバージョン指定を"^1.7.0"から"1.8.0"に書き換え、再びnpm install。 終わったらサーバーを起動。

$ grunt serve #=> 開発中のファイルでサーバーを起動

または

$ grunt server:dist #=> コンパイルされたdist/以下でサーバーを起動

これでいつものこの画面が出てればとりあえずOK.

f:id:yusuke-nozoe:20140909082612p:plain

5. heroku deploy の準備(ビルド)

世の中はとても便利で、yeomanアプリをherokuにデプロイするためのnpm packageが既にある。

$ npm install -g generator-heroku
$ yo heroku 
[?] Do you want a separate git repository in dist/? No #=> 同じgitリポジトリのsubtreeとしてデプロイする
   create heroku/Procfile
   create heroku/server.js
   create heroku/distpackage.json
Please add this copy task rule to your Gruntfile:
    copy: {
        dist: {
            files: [{
                expand: true,
                dest: '<%= yeoman.dist %>',
                cwd: 'heroku',
                src: '*',
                rename: function (dest, src) {
                    var path = require('path');
                    if (src === 'distpackage.json') {
                        return path.join(dest, 'package.json');
                    }
                    return path.join(dest, src);
                }
            }]
        }
    }

You're all set! Now run
    heroku apps:create
and push your dist directory with
    git subtree push --prefix dist heroku master

基本的には出力された通りにやればいいが、Gruntfile.jsにはcopyタスクが既にあるので、ちゃんと合併させる必要がある。

// Gruntfile.js
...
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            '*.html',
            'views/{,*/}*.html',
            'images/{,*/}*.{webp}',
            'fonts/*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: '.',
          src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        }, {
          expand: true,
          dest: '<%= yeoman.dist %>',
          cwd: 'heroku',
          src: '*',
          rename: function (dest, src) {
          var path = require('path');
          if (src === 'distpackage.json') {
            return path.join(dest, 'package.json');
          }
            return path.join(dest, src);
          }
        }]
      },
...

そしてビルドする。ここでは確認のため、dist/に移動してnpm installし、node.jsを起動してみる。

$ grunt build
$ cd dist && npm install
$ node server.js #=> http://localhost:1203/

6. heroku deploy

herokuにデプロイする前に注意点が一つある。yeomanのデフォルトの.gitignoreではdist/とbower_componentsがignoreされている。yo herokuするとdist/のignoreが消されるが、bower_componentsはそのままになっており、dist/bower_componentsもignoreされてしまい、そのままpushするとbootstrapのアイコンが出ない。この辺はherokuがbowerに対応してくれれば解決するのかも。

そこで下記を追加。

# .gitignore
node_modules
.tmp
.sass-cache
bower_components
!dist/bower_components #=> これを追加!

これでcommit して、pushする。

$ heroku create <app name>
Creating <app name>... done, stack is cedar
http://<app name>.herokuapp.com/ | git@heroku.com:<app name>.git
Git remote heroku added
$ git subtree push --prefix dist heroku master
git push using:  heroku master
-n 1/       1 (0)
Initializing repository, done.
Counting objects: 30, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (22/22), done.
Writing objects: 100% (30/30), 214.86 KiB | 262.00 KiB/s, done.
Total 30 (delta 0), reused 0 (delta 0)

-----> Node.js app detected
...
-----> Launching... done, v3
       http://<app name>.herokuapp.com/ deployed to Heroku

To git@heroku.com:<app name>.git
 * [new branch]     jaogjraejgaeogjieaogjae -> master

$ heroku open #=> ブラウザが開かれる

DONE.