6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Jade+Stylus+CoffeeScriptなページを生成・アップロードするgruntタスク

Last updated at Posted at 2014-10-22

Jade、Stylus、CoffeeScriptで簡単にページを作ってアップロードするgruntタスクを紹介します。作ってある機能は以下の通りです。

  • 開発用
    • 各種ファイルの変更監視
    • サーバ起動
    • Jade、Stylus、CoffeeScript
    • CSSのvendor prefix拡張
    • 素のHTML、CSS、JavaScript、画像への対応
  • デプロイ用
    • HTML、CSS、JavaScript、画像の圧縮
    • FTPでの差分アップロード

普段は、これをベースに機能を削って使っています。

ディレクトリ構成

以下のようなディレクトリ構成で使います。

/
 .ftppass(FTP使わないなら不要)
 .gitignore(git使わないなら不要だけど、使うときに事故起こさないようにいつも入れてる)
 Gruntfile.coffee
 package.json
 src/ (アップロードしたいファイルを入れる。ディレクトリ構成は自由です!)
   index.jade
   sample/
     index.html
   css/
     styles.styl
     normalize.css
   js/
     scripts.coffee
     jquery.js
 dist/ (自動で作られる。圧縮済みのファイルが入る)

各ファイルの中身

package.json

{
  "name": "example-site",
  "version": "0.0.0",
  "description": "build example website.",
  "devDependencies": {
    "grunt": "*",
    "grunt-contrib-watch": "*",
    "grunt-contrib-connect": "*",
    "grunt-contrib-clean": "*",
    "grunt-contrib-copy": "*",
    "grunt-contrib-coffee": "*",
    "grunt-closurecompiler": "*",
    "grunt-contrib-jade": "*",
    "grunt-contrib-htmlmin": "*",
    "grunt-contrib-stylus": "*",
    "grunt-autoprefixer": "*",
    "grunt-contrib-cssmin": "*",
    "grunt-contrib-imagemin": "*",
    "grunt-ftpush": "*"
  }
}

Gruntfile.coffee

module.exports = (grunt) ->
  pkg = grunt.file.readJSON('package.json')

  grunt.initConfig
    pkg: pkg
    watch:
      gruntfile:
        files: 'Gruntfile.coffee'
      html:
        files: 'src/**/*.html'
        tasks: 'copy:html'
      css:
        files: 'src/**/*.css'
        tasks: ['copy:css', 'autoprefixer:dist']
      js:
        files: 'src/**/*.js'
        tasks: 'copy:js'
      jade:
        files: 'src/**/*.jade'
        tasks: 'jade:dist'
      stylus:
        files: 'src/**/*.styl'
        tasks: ['stylus:dist', 'autoprefixer:dist']
      coffee:
        files: 'src/**/*.coffee'
        tasks: 'coffee:dist'
      options:
        livereload: true
    connect:
      server:
        options:
          base: '.tmp'
          useAvailablePort: true
      dist:
        options:
          keepalive: true
          useAvailablePort: true
          base: 'dist'
    clean:
      server: '.tmp'
      dist: 'dist'
    copy:
      image:
        expand: true
        cwd: 'src'
        src: '**/*.{png,jpg,gif}'
        dest: '.tmp'
        filter: 'isFile'
      html:
        expand: true
        cwd: 'src'
        src: '**/*.html'
        dest: '.tmp'
        filter: 'isFile'
      css:
        expand: true
        cwd: 'src'
        src: '**/*.css'
        dest: '.tmp'
        filter: 'isFile'
      js:
        expand: true
        cwd: 'src'
        src: '**/*.js'
        dest: '.tmp'
        filter: 'isFile'
    jade:
      options:
        client: false
      dist:
        expand: true
        cwd: 'src'
        src: '**/*.jade'
        dest: '.tmp'
        ext: '.html'
    stylus:
      dist:
        expand: true
        cwd: 'src'
        src: ['**/*.styl', '!**/_*.styl']
        dest: '.tmp'
        ext: '.css'
    autoprefixer:
      dist:
        expand: true
        cwd: '.tmp'
        src: '**/*.css'
        dest: '.tmp'
        ext: '.css'
    coffee:
      options:
        bare: true
      dist:
        expand: true
        cwd: 'src'
        src: '**/*.coffee'
        dest: '.tmp'
        ext: '.js'
    htmlmin:
      options:
        removeComments: true
        collapseWhitespace: true
      dist:
        expand: true
        cwd: '.tmp'
        src: '**/*.html'
        dest: 'dist'
    cssmin:
      dist:
        expand: true
        cwd: '.tmp',
        src: '**/*.css'
        dest: 'dist'
    closurecompiler:
      options:
        compilation_level: 'SIMPLE_OPTIMIZATIONS'
        max_processes: 5
      dist:
        expand: true
        cwd: '.tmp',
        src: '**/*.js'
        dest: 'dist'
    imagemin:
      options:
        optimizationLevel: 7
      dist:
        expand: true
        cwd: '.tmp'
        src: '**/*.{png,jpg,gif}'
        dest: 'dist'
    ftpush:
      dist:
        auth:
          host: 'server.domain.tld' # アップロード先サーバ
          port: 21
          authKey: pkg.name
        src: 'dist'
        dest: '/' # アップロード先のディレクトリなので環境によって変わる
        exclusions: 'dist/**/{.DS_Store,Thumbs.db}'
        simple: false
        useList: false

  grunt.loadNpmTasks task for task of pkg.devDependencies when /^grunt-/.test(task)

  grunt.registerTask 'generate', [
    'clean:server'
    'copy'
    'jade:dist'
    'stylus:dist'
    'autoprefixer:dist'
    'coffee:dist'
  ]

  grunt.registerTask 'compile', [
    'clean:dist'
    'htmlmin:dist'
    'cssmin:dist'
    'closurecompiler:dist'
    'imagemin:dist'
  ]

  grunt.registerTask 'build', [
    'generate'
    'compile'
  ]

  grunt.registerTask 'serve', [
    'generate'
    'connect:server'
    'watch'
  ]

  grunt.registerTask 'serve:dist', [
    'build'
    'connect:dist'
  ]

  grunt.registerTask 'deploy', [
    'build'
    'ftpush:dist'
  ]

  grunt.registerTask 'default', [
    'serve'
  ]

.ftppass

{
  "example-site": {
    "username": "USERNAME",
    "password": "PASSWORD"
  }
}

当たり前ですが、このファイルは.gitignoreの対象にしておきましょう。

.gitignore

/node_modules
/.ftppass
/.tmp
/dist

distをレポジトリの管理下に置きたいことはよくあるので、その時は取り除きます。

使い方

grunt # 開発用のサーバが起動します。圧縮しません。
grunt serve:dist # 圧縮した場合のデータが見れるサーバが起動します。
grunt build # 圧縮したデータを生成します。
grunt deploy # 圧縮したデータを生成し、FTPでアップロードします。

もちろん事前にnpm i --save-devしてからですが。

補足

割とオーソドックスな構成ですが、他に比べたら一般的ではないgrunt-closurecompilerとgrunt-ftpushについて。

grunt-closurecompilerは趣味的なものです。grunt-contrib-uglifyを使う場合は、package.jsonを置き換えて、Gruntfileのタスク名を置き換えれば良いでしょう。closurecompilerを使うgruntはいくつかありますが、これを使っているのは、何も考えずにnpm i --save-devするだけで他のセットアップが不要だからです。オススメです。

grunt-ftpushは差分アップロードに対応しているという理由で使っています。他に良いタスクがあれば教えていただきたいです。あと、多分、差分アップロードなので、他のところからFTPでアップロードすると消されたりするのではないかと思います(未検証)。そういう専用のディレクトリに対して適用しないといけない可能性が高いです。

問題点

  • デプロイするたびに変更していないものの圧縮、特に画像の圧縮が走るのが無駄
6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?