Middlemanで快適フロントエンド開発環境構築

Kazuhito Hokamura

2013/11/22

Tokyo Middleman Meetup #1

自己紹介

  • 外村 和仁
  • @hokaccha
  • 株式会社 ピクセルグリッド
  • JavaScript, Node.js, Ruby

昨今のフロントエンド開発事情

アプリケーションの複雑化

CoffeeScriptやSassなどの普及

開発環境の自動化の必要性

Gruntなどのツールの登場

Grunt

  • Node.js製のタスクランナー
  • Rake + Guardみたいな感じ
  • 最近フロントエンド界隈でブーム

DEMO

Gruntは柔軟だけど設定がめんどう

BUILD_DIR = 'build/2013'
DEPLOY_DIR = 'deploy'
DEPLOY_BRANCH = 'master'
DEPLOY_REPOSITORY = 'git@github.com:nodefest/nodefest.github.com.git'

module.exports = (grunt) ->
  
  grunt.task.loadNpmTasks 'assemble'
  grunt.task.loadNpmTasks 'grunt-contrib-sass'
  grunt.task.loadNpmTasks 'grunt-contrib-copy'
  grunt.task.loadNpmTasks 'grunt-contrib-clean'
  grunt.task.loadNpmTasks 'grunt-contrib-connect'
  grunt.task.loadNpmTasks 'grunt-contrib-watch'
  grunt.loadTasks 'tasks'

  grunt.initConfig

    assemble:
      options:
        socketServer: process.env['SOCKET_HOST'] || 'nodefest2013.c.node-ninja.com:80'
        partials: 'src/partials/*.hbs'
        data: 'data/*.yml'
      dist:
        expand: true
        cwd: 'src/tmpls'
        src: '*.hbs'
        dest: BUILD_DIR

    sass:
      options:
        bundleExec: true
      dist:
        files: [
          src: 'src/scss/style.scss'
          dest: "#{BUILD_DIR}/assets/css/style.css"
        ]

    copy:
      static:
        expand: true
        cwd: 'src/static'
        src: '**/*'
        dest: BUILD_DIR
      deploy:
        expand: true
        cwd: BUILD_DIR
        src: ['**/*', '!**/_**/*', '!**/_*'] # ignore files start with underscore.
        dest: "#{DEPLOY_DIR}/2013"

    clean: [BUILD_DIR]

    connect:
      server:
        options:
          port: process.env.PORT || 3000
          base: './build'

    watch:
      assemble:
        files: ['data/*', 'src/tmpls/*', 'src/partials/*']
        tasks: 'assemble'
      sass:
        files: 'src/scss/*'
        tasks: 'sass'
      copy:
        files: 'src/static/**/*'
        tasks: 'copy:static'

    setup:
      repository: DEPLOY_REPOSITORY
      branch: DEPLOY_BRANCH
      dir: DEPLOY_DIR

    deploy:
      #dryrun: true
      branch: DEPLOY_BRANCH
      dir: DEPLOY_DIR
      message: 'Update 2013 with <%= sha1 %>'

  grunt.registerTask 'build', ['clean', 'sass', 'assemble', 'copy:static']
  grunt.registerTask 'server', ['build', 'connect', 'watch']
  grunt.registerTask 'publish', ['setup', 'build', 'copy:deploy', 'deploy']
  grunt.registerTask 'default', ['build']

そこでMiddleman

configure :development do
  set :debug_assets, true
end

configure :build do
  activate :minify_javascript
end

ここがいいよねMiddleman

  • 設定がほとんどいらない
  • Asset Pipeline
  • Rackの資産を利用できる
  • 開発時に動的サーバー、デプロイ時に静的ファイル出力という理想的な動作

Asset Pipeline

  • コンパイル、concat、minifyが一発でできる
  • require による依存関係の解決
  • 開発時にファイルを分割して読み込める

外部APIを使った開発

よくあるパターン(当社比)

  • サーバーサイドはAPIのみ
  • APIとフロントエンドの開発が完全に分離している
  • 本番ではAPIとアセットは同一オリジンで配信

事例紹介

<問題点>
開発時のクロスオリジンXHRの壁

解決案

  • JSONP
  • XHR2 (CORS)
  • 静的なダミーデータ
  • Proxy

JSONP、XHR2

  • 開発環境のためにAPIのヘッダや形式を変えたくない
  • そもそもAPIの都合上できないことも多い

※ただし本番でもAPIとJSのオリジンが異なるならこれでもよい

静的なダミーデータ

  • 複雑なAPIに対応するのが難しい
  • オフラインでも開発できるという利点はある

そこで
Middleman + rack-reverse-proxy

config.rb

require 'rack/reverse_proxy'

use Rack::ReverseProxy do 
  reverse_proxy '/api', 'http://api-server.com/'
end

api proxy

DEMO

まとめ

Middlemanをフロントエンドの開発構築に使うと

  • Asset Pipelineで快適アセットコンパイル
  • Rackの資産が利用できる
  • フロントエンド開発環境が超快適!

ありがとうございました