本文へジャンプ

Gruntで効率化! リリース前の面倒な作業をまとめる

Posted by MONSTER DIVE

納品時には、少しでもページを速く表示させるために、CSS・JS・画像の圧縮などファイルを最適化し、Webサイトを高速化することは必要不可欠です。
ファイルを圧縮するには、アプリを使ったりWebサービスを使ってもできますが、一つ一つ行うと時間がかかってしまいます。作業漏れの原因にもなります。

そこで、納品前の面倒な作業をGruntでまとめて行いたいと思います。Gruntを使うことによって、Sass(SCSS)のコンパイルHTMLの量産を簡単に出来たりするので、とても便利なツールです。事前にGruntのインストールと、SassとCompassのインストールを行ってから、ぜひ以下の手順でお試しください。

今回、Gruntでやることは下記の通りです。

  • HTMLファイルの圧縮
  • CSSファイルの圧縮
  • 画像ファイルの圧縮
  • JSファイル圧縮
  • 不要なファイル・フォルダの削除(Comassでスプライト画像を制作するためのフォルダ等)

※画像の圧縮にはImageOptim(Macのみ)を使用しますので、事前にアプリをダウンロードをしましょう。

構築環境について

Gruntを実行する上でのプロジェクトのフォルダ構成は、下記の通りです。

    project
    ├src              (Sass(SCSS)などのコンパイルして使うファイルのフォルダ)
    │└sass
    │ ├config.rb
    │ └style.scss
    │
    ├bin              (ローカルの作業フォルダ)
    │├index.html
    │├css
    │├js
    ││└sample.js
    │└images
    │ ├sprite.png
    │ └sprite           (Compassでスプライト画像を作るためのフォルダ。納品時は不要)
    │
    ├release          (サーバーにアップするフォルダ)
    │├index.html        (圧縮されたHTMLファイル)
    │├css               (圧縮されたCSSファイル)
    │├js
    ││└sample.js      (圧縮されたJSファイル)
    │└images
    │ └sprite.png       (スプライト画像のみ)
    ├package.json
    └Gruntfile.js
フォルダ分けをした理由
  • サーバーに不要なファイルをアップしないため
  • 圧縮前と圧縮後のファイルをローカル上に残しておくため
  • サーバーにアップするフォルダと作業ファイルを明確に分けるため

などのミスを防ぐためにフォルダを分けています。

Grunt - フォルダ分けをした理由

各フォルダの役割

srcフォルダ

コンパイルして使うファイル(Sass(SCSS)やCoffeeScriptなど)を置いています。

binフォルダ

ローカルでの作業フォルダになります。Compassを使ってスプライト画像を作るためのフォルダなども該当します。

releaseフォルダ

サーバーにアップするためのフォルダになります。このフォルダは、直接修正やファイルの追加などは行いません。

Gruntの設定

pakage.json

今回、使用するpackage.jsonになります。

    {
        "name": "Sample",
        "main": "Gruntfile.js",
        "dependencies": {
           "grunt": "~0.4.1"
         },
        "devDependencies": {
            "grunt-contrib-copy": "~0.4.1",
            "grunt-contrib-clean": "~0.5.0",
            "grunt-contrib-htmlmin": "~0.1.3",
            "grunt-contrib-cssmin": "~0.6.2",
            "grunt-contrib-uglify": "~0.2.4",
            "grunt-imageoptim": "~1.3.13",
            "grunt-contrib-livereload": "~0.1.2",
            "grunt-contrib-connect": "~0.5.0",
            "grunt-contrib-compass": "~0.6.0",
            "grunt-csscomb": "~0.5.0",
            "grunt-combine-media-queries": "~1.0.6",
            "grunt-contrib-watch": "~0.5.3"
        }
    }
納品ファイルを作成するためのモジュール
  • grunt-contrib-copy(ファイルのコピー)
  • grunt-contrib-clean(ファイルの削除)
  • grunt-contrib-htmlmin(HTMLファイルの圧縮)
  • grunt-contrib-cssmin(CSSファイルの圧縮)
  • grunt-contrib-uglify(JSファイルの圧縮)
  • grunt-imageoptim(イメージファイルの圧縮)
Sass(SCSS)をコンパイルするためのモジュール
  • grunt-contrib-livereload
  • grunt-contrib-connect
  • grunt-contrib-compass
  • grunt-csscomb
  • grunt-combine-media-queries
  • grunt-contrib-watch

上記の使い方はこちらの記事をご覧ください。

Gruntfile.js

今回使用したGruntfile.jsになります。

    'use strict';
    // livereload用の処理
    var
        path = require('path'),
        lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet,
        folderMount = function folderMount(connect, point) {
            return connect.static(path.resolve(point));
        };

    module.exports = function(grunt) {
        var pkg, taskName;
        pkg = grunt.file.readJSON('package.json');

        grunt.initConfig({
            pkg: pkg,
            dir: {
                src:'src',
                bin:'bin',
                release:'release',
                js: 'js',
                css: 'css',
                img:'images',
                sass:'sass'
            },
            // ファイルをコピーする
            copy: {
                html: {
                    expand: true,
                    // コピー元のディレクトリ
                    cwd: '<%= dir.bin %>/',
                    src: ['**/*.html'],
                    // コピー先のディレクトリ
                    dest: '<%= dir.release %>/'
                },
                css: {
                    expand: true,
                    cwd: '<%= dir.bin %>/',
                    src: ['css/**'],
                    dest: '<%= dir.release %>/'
                },
                images: {
                    expand: true,
                    cwd: '<%= dir.bin %>/',
                    src: ['images/**'],
                    dest: '<%= dir.release %>/'
                },
                js: {
                    expand: true,
                    cwd: '<%= dir.bin %>/',
                    src: ['js/**'],
                    dest: '<%= dir.release %>/'
                }
            },
            // HTMLを圧縮する
            htmlmin: {
                all: {
                    options: {
                        removeComments: true,
                        removeCommentsFromCDATA: true,
                        removeCDATASectionsFromCDATA: true,
                        collapseWhitespace: true,
                        removeRedundantAttributes: true,
                        removeOptionalTags: true
                    },
                    expand: true,
                    cwd: '<%= dir.bin %>/',
                    src: ['**/*.html'],
                    dest: '<%= dir.release %>/'
                }
            },
            // JSを圧縮する
            uglify: {
                min: {
                    expand: true,
                    cwd: '<%= dir.release %>/<%= dir.js %>/',
                    src: ['sample.js'],
                    dest: '<%= dir.release %>/<%= dir.js %>/'
                }
            },
            // CSSを圧縮する
            cssmin: {
                all: {
                    expand: true,
                    cwd: '<%= dir.bin %>/<%= dir.css %>/',
                    src: ['*.css'],
                    dest: '<%= dir.release %>/<%= dir.css %>/'
                }
            },
            // 画像を圧縮する
            imageoptim: {
                files: ['bin/'],
                options: {
                    jpegMini: true,
                    quitAfter: true
                }
            },
            // 不要なファイルを削除する
            clean: {
                // releaseフォルダ内を削除する
                deleteReleaseFolder: {
                    src: '<%= dir.release %>/'
                },
                // releaseから不要なファイルを削除する
                deleteReleaseFile: {
                    src: [
                        '<%= dir.release %>/<%= dir.img %>/sprite'
                    ],
                }
            },
            // localhostの設定
            // http://localhost:9001/で内容を確認することができます。
            connect: {
                livereload: {
                    options: {
                        port: 9001,
                        middleware: function(connect, options) {
                            return [lrSnippet, folderMount(connect, 'bin')];
                        }
                    }
                }
            },
            // Compassの設定
            compass: {
                dist: {
                    options: {
                        config: '<%= dir.src %>/<%= dir.sass %>/config.rb'
                    }
                }
            },
            // ファイルを監視する
            watch: {
                html: {
                    files: '<%= dir.bin %>/**/*.html',
                    tasks: [],
                    options: {
                        livereload: true,
                        nospawn: true
                    }
                },
                sass: {
                    files: ['<%= dir.src %>/<%= dir.sass %>/**'],
                    tasks: ['compass', 'cmq', 'csscomb'],
                    options: {
                        livereload: true,
                        nospawn: true
                    }
                }
            },
            // メディアクエリをまとめる
            cmq:{
                options: {
                    log: false
                },
                dev: {
                    files: {
                        '<%= dir.bin %>/<%= dir.css %>/': ['<%= dir.bin %>/<%= dir.css %>/style.css']
                    }
                }
            },
            // CSSのプロパティを揃える
            csscomb:{
                dev:{
                    expand: true,
                    cwd: '<%= dir.bin %>/<%= dir.css %>/',
                    src: ['*.css'],
                    dest: '<%= dir.bin %>/<%= dir.css %>/'
                }
            }
        });




        // pakage.jsonに記載されているパッケージを自動読み込み
        for(taskName in pkg.devDependencies) {
            if(taskName.substring(0, 6) == 'grunt-') {
                grunt.loadNpmTasks(taskName);
            }
        }

        // sassをコンパイルするgruntコマンド
        grunt.registerTask('default', ['connect', 'watch']);

        // 画像を圧縮するためのgruntコマンド
        grunt.registerTask('imgmin', ['imageoptim']);

        // 社内確認用のファイルを作るためのgruntコマンド
        grunt.registerTask('check', ['clean:deleteReleaseFolder', 'copy:html', 'copy:css', 'copy:images', 'copy:js', 'clean:deleteReleaseFile']);

        // 納品用のファイルを作るためのgruntコマンド
        grunt.registerTask('release', ['clean:deleteReleaseFolder', 'copy:images', 'copy:js', 'htmlmin', 'cssmin', 'uglify', 'clean:deleteReleaseFile']);

        grunt.registerTask('eatwarnings', function() {
            grunt.warn = grunt.fail.warn = function(warning) {
                grunt.log.error(warning);
            };
        });
    };

package.jsonとGruntfile.jsを準備して、モジュールをダウンロードします。

    sudo npm install

使用するコマンド

設定が完了したら、ターミナルからGruntfile.jsで設定したGruntのコマンドを実行します。今回使用するコマンドは下記の通りです。

    grunt imgmin    // 画像の圧縮
    grunt check     // 社内確認用のファイルを作成する
    grunt release   // サーバーアップ用のファイルを作成する

画像を圧縮するためのgruntコマンド

ImageOptimとJPEGminiを使用して、画像を圧縮します。コマンドを実行すると、ImageOptimとJPEGminiが立ち上がり画像が圧縮されます。処理が重いので、他のreleaseコマンドは別にしています。

コマンド
    grunt imgmin

filesで画像を圧縮するフォルダを指定します。jpegMiniがインストールされてない環境では、Gruntfile.jsのjpegMini: falseと設定します。

imageoptimタスクの設定
    imageoptim: {
        files: ['bin/'],
        options: {
            jpegMini: true,
            quitAfter: true
        }
    }

Grunt - imgmin

社内確認用のファイルを作るためのGruntコマンド

実行すると下記のタスクが実行されます。
社内でソースコードをチェックすることも有ると思うので、各種ファイルの圧縮を行いません。

  1. releaseフォルダを削除
  2. binフォルダからHTML, CSS, JS, Imageファイルをreleaseフォルダにコピー
  3. 不要なファイルをreleaseフォルダから削除
コマンド
    grunt check
削除するファイルの設定

削除ファイルの設定は、Gruntfile.jsのcleanタスク内のdeleteReleaseFileに不要なファイルやフォルダを追加していきます。

    clean: {
        // releaseフォルダ内を削除する
        deleteReleaseFolder: {
            src: '<%= dir.release %>/'
        },
        // releaseから不要なファイルを削除する
        deleteReleaseFile: {
            src: [
                '<%= dir.release %>/<%= dir.img %>/sprite',
                '削除するファイルやフォルダを指定してください'
            ],
        }
    }

Grunt - 削除対象の確認

納品用のファイルを作るためのgruntコマンド

実行すると下記のタスクが実行されます。納品用のファイルなので、HTML, CSS, JSファイルの圧縮も行います。

  1. releaseフォルダ中を削除
  2. binフォルダからJS, Imageファイルをコピー
  3. 圧縮したHTMLとCSSをreleaseフォルダに出力
  4. release/jsフォルダ内のJSファイルを圧縮
  5. 不要なファイルをreleaseフォルダから削除
コマンド
    grunt release

Grunt - 納品用のファイルを作る

まとめ

Gruntを使うと、納品時に必要な面倒な作業をまとめて行うことができます。自動化することによって、ファイルのアップミスやファイル最適化のし忘れなど、うっかりありがちなヒューマンエラーが減ります。

また、Gruntfile.jspackage.jsonだけを用意して、モジュールをインストール後に初期設定のコマンドを用意しておくと便利です。作業フォルダの作成や自分が使うSass(SCSS)ファイルのコピーなど、Gruntのコマンドだけで簡単に作業環境を作ることができます。gitやBowerなどのGruntのモジュールも出てるので、それらと連携した作業環境も構築することできます。

使いまわしを想定してベースとなるGruntfile.jsを作り、案件によって必要なタスクやモジュールを追加していくと良いと思います。

Recent Entries
MD EVENT REPORT
What's Hot?