Help us understand the problem. What is going on with this article?

jadeとstylusとcoffeeのgruntを作ってみた

More than 5 years have passed since last update.

はじめに

タイトルの通りですが、jadeとstylusとcoffeeを監視、コンパイルして、圧縮してビルドするGruntfileを作りました。その他にも色々機能がありますので紹介します。

ファイル構成

Gruntfile.coffee
package.json
src/
  jade/sample.jade
  stylus/sample.styl
  coffee/sample.coffee
  images/sample.jpg

Getting Started

package.jsonを任意の場所に置いて、npm installします。
必要なnode_modulesがインストールされます。
grunt-contribで足りないものも含まれています。

package.json
{
  "name": "grunt-jade-stylus-coffee",
  "version": "0.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": "",
  "author": "",
  "license": "BSD",
  "devDependencies": {
    "grunt-contrib-concat": "~0.3.0",
    "grunt-contrib-copy": "~0.4.1",
    "grunt-contrib-compass": "~0.6.0",
    "grunt-contrib-clean": "~0.5.0",
    "grunt-contrib-sass": "~0.5.1",
    "grunt-contrib-htmlmin": "~0.1.3",
    "grunt-contrib-csslint": "~0.1.2",
    "grunt-contrib-cssmin": "~0.6.2",
    "grunt-contrib-jst": "~0.5.1",
    "grunt-contrib-coffee": "~0.7.0",
    "grunt-contrib-qunit": "~0.3.0",
    "grunt-contrib-connect": "~0.5.0",
    "grunt-contrib-requirejs": "~0.4.1",
    "grunt-contrib-jshint": "~0.6.5",
    "grunt-contrib-jasmine": "~0.5.2",
    "grunt-contrib-uglify": "~0.2.7",
    "grunt-contrib-handlebars": "~0.5.12",
    "grunt": "~0.4.2",
    "grunt-contrib-compress": "~0.5.3",
    "grunt-contrib-watch": "~0.5.3",
    "grunt-contrib-stylus": "~0.8.0",
    "grunt-contrib-jade": "~0.8.0",
    "grunt-contrib-imagemin": "~0.3.0",
    "grunt-contrib-less": "~0.7.0",
    "grunt-contrib-nodeunit": "~0.2.2",
    "grunt-contrib-yuidoc": "~0.5.0",
    "grunt-contrib": "~0.8.0",
    "matchdep": "~0.3.0",
    "grunt-coffeelint": "0.0.7",
    "grunt-simple-mocha": "~0.4.0",
    "grunt-autoprefixer": "~0.4.1",
    "grunt-styleguide": "~0.2.12"
  }
}
npm install
Gruntfile.coffee
module.exports = (grunt) ->

  # load all grunt tasks
  (require 'matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks)

  _ = grunt.util._
  path = require 'path'

  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: 'src'
      jade: 'jade'
      styl: 'stylus'
      coffee: 'coffee'
      images: 'images'
      js: 'js'
      css: 'css'
      img: 'images'
      vendors: 'vendors'
      dist: 'dist'
      build: 'build'
      docs: 'docs'
      test: 'test'

    jade:
      dist:
        options:
          pretty: true, #htmlをインデント表記させる
        expand: true
        cwd: '<%= dir.src %>/<%= dir.jade %>'
        src: '**/*.jade'
        dest: '<%= dir.dist %>/'
        ext: '.html'

    stylus:
      dist:
        options:
          compress: false
        expand: true
        cwd: '<%= dir.src %>/<%= dir.styl %>/'
        src: '**/*.styl'
        dest: '<%= dir.dist %>/<%= dir.css %>/'
        ext: '.css'

    coffee:
      dist:
        expand: true
        cwd: '<%= dir.src %>/<%= dir.coffee %>'
        src: '**/*.coffee'
        dest: '<%= dir.dist %>/<%= dir.js %>'
        ext: '.js'

    htmlmin:
      build:
        options:
          removeComments: true
          collapseWhitespace: true
        expand: true
        cwd: '<%= dir.dist %>'
        src: '**/*.html'
        dest: '<%= dir.build %>'
        ext: '.html'

    cssmin:
      build:
        expand: true
        cwd: '<%= dir.dist %>/<%= dir.css %>'
        src: '**/*.css'
        dest: '<%= dir.build %>/<%= dir.css %>'
        ext: '.css'

    uglify:
      options:
        banner: '<%= banner %>'
        sourceMap: (path) ->
          path + '.map'
      build:
        expand : true
        src: '<%= dir.build %>/**/*.js'

    # 画像の圧縮
    imagemin:
      options:
        optimizationLevel: 7
        pngquant: false
      dist:
        expand: true
        cwd: '<%= dir.dist %>/<%= dir.images %>'
        src: '**/*.{jpg,jpeg,gif}'
        dest: '<%= dir.dist %>/<%= dir.img %>'

    # coffeeの文法チェック
    coffeelint:
      app: '**/<%= dir.coffee %>/*.coffee'

    # CSSのprefiexを補完
    autoprefixer:
      options:
        browsers: ['last 2 version', 'ie 8', 'ie 7', 'ie 6']
      dist:
        expand: true
        cwd: '<%= dir.dist %>/<%= dir.css %>'
        src: '**/*.css'
        dest: '<%= dir.dist %>/<%= dir.css %>/'
        ext: '.css'

    simplemocha:
      dist:
        src: '<%= dir.test %>/<%= dir.coffee %>/*.coffee'
      options:
        globals: ['should']
        timeout: 3000
        ignoreLeaks: false
        grep: '*-test'
        ui: 'bdd'
        reporter: 'tap'

    watch:
      jade:
        files: '<%= dir.src %>/**/*.jade',
        tasks: 'jade:dist'
      stylus:
        files: '<%= dir.src %>/**/*.styl'
        tasks: ['stylus:dist', 'autoprefixer:dist', 'styleguide:dist']
      coffee:
        files: '<%= dir.src %>/**/*.coffee'
        tasks: 'coffee:dist'
      images:
        files: ['<%= dir.src %>/**/*.{gif,jpeg,jpg,png,svg,webp}']
        tasks: ['clean:images', 'copy', 'imagemin']
      vendors:
        files: ['<%= dir.src %>/<%= dir.vendors %>/']
        tasks: ['copy:vendors']
      livereload:
        options:
          livereload: '<%= connect.options.livereload %>'
        files: [
          '<%= dir.dist %>/*.html',
          '<%= dir.dist %>/**/*.css',
          '<%= dir.dist %>/**/*.js',
          '<%= dir.dist %>/**/*.{gif,jpeg,jpg,png,svg,webp}'
        ]

    connect:
      options:
        port: 9000
        livereload: 35729
        hostname: 'localhost'
      livereload:
        options:
          open: true
          base: ['<%= dir.dist %>']

    copy:
      img:
        expand: true
        dot: true
        cwd: '<%= dir.src %>/<%= dir.images %>'
        dest: '<%= dir.dist %>/<%= dir.img %>'
        src: [
          '**/*.{gif,jpeg,jpg,png,svg,webp}',
        ]
      vendors:
        expand: true
        dot: true
        cwd: '<%= dir.src %>/<%= dir.vendors %>'
        dest: '<%= dir.dist %>/<%= dir.vendors %>'
        src: ['**']
      build:
        expand: true
        dot: false
        cwd: '<%= dir.dist %>/'
        dest: '<%= dir.build %>/'
        src: ['**']

    yuidoc:
      dist:
        name: '<%= pkg.name %>'
        description: '<%= pkg.description %>'
        version: '<%= pkg.version %>'
      options:
        paths: '<%= dir.src %>/<%= dir.coffee %>/'
        outdir: '<%= dir.docs %>/<%= dir.js %>'
        syntaxtype: 'coffee'
        extension: '.coffee'

    styleguide:
      dist:
        files:
          #'<%= dir.docs %>/<%= dir.css %>': '<%= dir.src %>/<%= dir.styl %>/**/*.styl'
          '<%= dir.docs %>/<%= dir.css %>': '<%= dir.dist %>/<%= dir.css %>/**/*.css'
          #'<%= dir.docs %>/<%= dir.css %>': '<%= dir.src %>/<%= dir.styl %>/**/*.sass'

    clean:
      dist:
        src: [
          '<%= dir.dist %>/**/*.html',
          '<%= dir.dist %>/<%= dir.js %>/**/*.js',
          '<%= dir.dist %>/<%= dir.css %>/**/*.css',
          '<%= dir.build %>',
          '<%= dir.docs %>'
        ]
      docs:
        src: '<%= dir.docs %>'
      images:
        src: ['<%= dir.dist %>/<%= dir.img %>']

  grunt.registerTask 'default', [
    'clean',
    'coffeelint',
    'simplemocha',
    'yuidoc'
    'jade:dist',
    'stylus:dist',
    'autoprefixer',
    'styleguide',
    'coffee:dist',
    'copy:img',
    'copy:vendors',
    'imagemin'
  ]
  grunt.registerTask 'w', [
    'default',
    'connect',
    'watch',
    'jshint',
  ]
  grunt.registerTask 'compile', [
    'clean',
    'coffee:dist',
    'jade:dist',
    'stylus:dist'
  ]
  grunt.registerTask 'build', [
    'default',
    'copy:build'
    'htmlmin:build',
    'cssmin:build',
    'uglify'
  ]
  grunt.registerTask 'c', ['compile']
  grunt.registerTask 'docs', ['clean:docs', 'yuidoc', 'styleguide']

使い方

デフォルトのコマンドで、jade,stylus,coffeeがコンパイルされ、distディレクトリの中に配置されます。

grunt
Gruntfile.coffee
package.json
dist/
  sample.html
  js/
    sample.js
  css/
    sample.css
  img/
    sample.jpg
src/
  jade/sample.jade
  stylus/sample.styl
  coffee/sample.coffee
  images/sample.jpg

grunt wで監視します。ブラウザが立ち上がり、jade,stylus,coffee,imagesディレクトリの中身に変更があれば自動でリロードします。

grunt w

grunt buildでリリースビルドします。buildディレクトリの中に配置され、各ファイルはminifyされます。画像も圧縮されます。

grunt build

coffeelint

coffee-scriptの文法チェックです。デフォルトと監視時にチェックが入ります。

simplemocha

simplemochaで簡単なJSテストをします。

autoprefixer

CSSでベンダープレフィックスを自動でつけてくれる機能です。

selector {
  transition: transform 1s;
}

と書けば、grunt後に、

selector {
  -webkit-transition: -webkit-transform 1s;
  transition: transform 1s;
}

と書きだされます。

imagemin

画像のファイル容量を圧縮します。設定は、optimizationLevelでデフォルトは7です。
細かい設定は、下記のURLから。
grunt-contrib-imagemin

uglify

JSファイルの難読化、圧縮をします。ビルド時にSourceMapというファイルが出ます。
Introduction to JavaScript Source Maps

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away