納品時には、少しでもページを速く表示させるために、CSS・JS・画像の圧縮などファイルを最適化し、Webサイトを高速化することは必要不可欠です。
ファイルを圧縮するには、アプリを使ったりWebサービスを使ってもできますが、一つ一つ行うと時間がかかってしまいます。作業漏れの原因にもなります。
そこで、納品前の面倒な作業をGruntでまとめて行いたいと思います。Gruntを使うことによって、Sass(SCSS)のコンパイルやHTMLの量産を簡単に出来たりするので、とても便利なツールです。事前にGruntのインストールと、SassとCompassのインストールを行ってから、ぜひ以下の手順でお試しください。
今回、Gruntでやることは下記の通りです。
※画像の圧縮には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
などのミスを防ぐためにフォルダを分けています。
コンパイルして使うファイル(Sass(SCSS)やCoffeeScriptなど)を置いています。
ローカルでの作業フォルダになります。Compassを使ってスプライト画像を作るためのフォルダなども該当します。
サーバーにアップするためのフォルダになります。このフォルダは、直接修正やファイルの追加などは行いません。
今回、使用する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" } }
上記の使い方はこちらの記事をご覧ください。
今回使用した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 // サーバーアップ用のファイルを作成する
ImageOptimとJPEGminiを使用して、画像を圧縮します。コマンドを実行すると、ImageOptimとJPEGminiが立ち上がり画像が圧縮されます。処理が重いので、他のreleaseコマンドは別にしています。
grunt imgmin
filesで画像を圧縮するフォルダを指定します。jpegMiniがインストールされてない環境では、Gruntfile.jsのjpegMini: falseと設定します。
imageoptim: { files: ['bin/'], options: { jpegMini: true, quitAfter: true } }
実行すると下記のタスクが実行されます。
社内でソースコードをチェックすることも有ると思うので、各種ファイルの圧縮を行いません。
grunt check
削除ファイルの設定は、Gruntfile.jsのcleanタスク内のdeleteReleaseFileに不要なファイルやフォルダを追加していきます。
clean: { // releaseフォルダ内を削除する deleteReleaseFolder: { src: '<%= dir.release %>/' }, // releaseから不要なファイルを削除する deleteReleaseFile: { src: [ '<%= dir.release %>/<%= dir.img %>/sprite', '削除するファイルやフォルダを指定してください' ], } }
実行すると下記のタスクが実行されます。納品用のファイルなので、HTML, CSS, JSファイルの圧縮も行います。
grunt release
Gruntを使うと、納品時に必要な面倒な作業をまとめて行うことができます。自動化することによって、ファイルのアップミスやファイル最適化のし忘れなど、うっかりありがちなヒューマンエラーが減ります。
また、Gruntfile.jsとpackage.jsonだけを用意して、モジュールをインストール後に初期設定のコマンドを用意しておくと便利です。作業フォルダの作成や自分が使うSass(SCSS)ファイルのコピーなど、Gruntのコマンドだけで簡単に作業環境を作ることができます。gitやBowerなどのGruntのモジュールも出てるので、それらと連携した作業環境も構築することできます。
使いまわしを想定してベースとなるGruntfile.jsを作り、案件によって必要なタスクやモジュールを追加していくと良いと思います。