ビルドツール
はじめの一歩(タスクランナー編)

宇野陽太@cancer6

坂巻 翔大郎@geckotang

小山田 晃浩@yomotsu

1. タスクランナー導入方法
2. Gruntを使ったプロジェクト
3. gulpを使ったプロジェクト

タスクランナーとは

photo by https://www.flickr.com/photos/ryanthescooterguy/8276354585

繰り返し発生する作業を自動化して開発効率を上げるツールこんなこと言われたことありませんか？

「JSの読み込みが遅いので、まとめたり圧縮したりして欲しいんですけど」

「画像書き出したので、そっちでスプライト作ってくれませんか？」

p
i
z
.
7
0
「納品物はZIPで固めて
2
0
2015

ファイル名は今日の日付で納品してください」

「ブラウザをいちいちリロードするのが面倒なんですけど！」手作業でやってたことを自動化しようphoto by https://www.flickr.com/photos/127066648@N08/15526064479

• JSファイルを結合・圧縮• 書きだした画像を組み合わせてスプライト画像作成• ファイルを集めて今日の日付でZIPファイル化• ファイルを編集したらブラウザをリロード

タスクランナーの世界

…

…

Gruntとgulpの特徴

•現在最もメジャーなタスクランナー•利用者が多い(プラグインの数が豊富)•Gruntﬁleにタスクの設定•タスクの実行が簡単(反面、複雑なタスクを作ろうとすると面倒)を記述

•後発のタスクランナー•gulpﬁleにタスクの処理 を記述•複雑なタスクを作りやすい(Node.jsのモジュールやcommonJSの知識が多少必要)•処理が高速•どっちを使うかは好み•はじめての人はGruntがオススメ•慣れてきたらgulpも使ってみるタスクランナーを導入する

…その前に、Node.js & npmのインストール

http://nodejs.org/

ここからダウンロード

http://nodejs.org/

基本的にはウィザードに従うだけ

Macへのインストール$ node -v↵
v0.10.36$ npm -v↵
1.4.28

Windowsへのインストール+ R

$ node -v↵
v0.10.36$ npm -v↵
1.4.28

コマンドラインから
インストールする場合• Homebrew(Macのみ)• nodebrew• ndenv

Node.jsのバージョン管理Node.js & npm
準備OK

Gruntのインストール

$ npm install -g grunt-cli
gruntの実行環境をインストール

53

$ npm install -g grunt-cli
おまじない

54

$ npm install -g grunt-cli$ npm init
(Enter…Enter…Enter…)
package.jsonを作成

55

package.json!

{}"name": "get-started-grunt","version": "0.0.0","devDependencies": {"grunt": "~0.4.5","grunt-contrib-concat": "~0.5.0","grunt-contrib-sass": "~0.8.1","grunt-contrib-uglify": "~0.7.0"}

package.json!

{"name": "get-started-grunt","version": "0.0.0","devDependencies": {}}$ npm install -g grunt-cli$ npm init
(Enter…Enter…Enter…)$ npm install grunt --save-dev
grunt本体をインストール

58

$ npm install -g grunt-cli$ npm init
(Enter…Enter…Enter…)$ npm install grunt --save-dev
package.jsonに保存

59

package.json!

{"name": "get-started-grunt","version": "0.0.0","devDependencies": {}}$ npm install -g grunt-cli$ npm init
(Enter…Enter…Enter…)$ npm install grunt --save-dev

61

package.json!

{"name": "get-started-grunt","version": "0.0.0","devDependencies": {"grunt": "~0.4.5"}}

$ npm install -g grunt-cli$ npm init
(Enter…Enter…Enter…)$ npm install grunt --save-dev$ grunt --version
grunt-cli v0.1.6
grunt v0.4.5

63gulpのインストール

$ npm install -g gulp
$ npm init
(Enter…Enter…Enter…)$ npm install gulp --save-dev

65

$ npm install -g gulp
$ npm init
(Enter…Enter…Enter…)$ npm install gulp --save-dev

66

$ npm install -g gulp
$ npm init
(Enter…Enter…Enter…)$ npm install gulp --save-dev$ gulp --version[21:26:01] CLI version 3.8.8[21:26:01] Local version 3.8.10

67

タスクを実行する• プラグインのインストール• 設定ファイルの用意「JSの読み込みが遅いので、まとめたり圧縮したりして欲しいんですけど」

プラグインのインストール

ファイルを結合

grunt-contrib-concat
gulp-concat

ファイルを圧縮

grunt-contrib-uglify
gulp-uglify

$ npm install -g grunt-cli$ npm init
(Enter…Enter…Enter…)$ npm install grunt --save-dev$ npm install grunt-contrib-concat--save-dev$ npm install grunt-contrib-uglify--save-dev

76

$ npm install -g gulp
$ npm init
(Enter…Enter…Enter…)$ npm install gulp --save-dev$ npm install gulp-concat --savedev$ npm install gulp-uglify --savedev

77

設定ファイルの用意

Gruntﬁle.js• Gruntの設定ファイル• タスクの設定を記述する

1. module.exports = function(grunt){
おまじない
2.
3.
4. grunt.loadNpmTasks('grunt-contrib-concat');
5. grunt.loadNpmTasks('grunt-contrib-uglify');
6.
7.
8. grunt.initConfig({
プラグインを読み込む
9.
concat: {10.
options: {11.
separator: ';'
12.
},
13.
app: {
設定ここから14.
src: [
15.
'src/js/1.js',
16.
'src/js/2.js'
17.
],
18.
dest: 'dist/js/app.js'
19.
}

5. grunt.loadNpmTasks('grunt-contrib-uglify');
6.
7.
8. grunt.initConfig({
9.
concat: {concatタスクのオプション
10.
options: {11.
separator: ';'
12.
},
13.
app: {
結合対象のファイル名
14.
src: [
15.
'src/js/1.js',
16.
'src/js/2.js'
17.
],
18.
dest: 'dist/js/app.js'
19.
}
20.
},
結合後のファイル名21.
uglify: {22.
app: {
23.
files: {24.
'dist/js/app.min.js': ['dist/js/app.js']
25.
}
26.
}
27.
},

12.
},
13.
app: {
14.
src: [
15.
'src/js/1.js',
16.
'src/js/2.js'
17.
],
18.
dest: 'dist/js/app.js'
19.
}
20.
},
圧縮後のファイル名21.
uglify: {22.
app: {
23.
files: {24.
'dist/js/app.min.js': ['dist/js/app.js']
25.
}
26.
}
圧縮対象のファイル名
27.
}28. });!

30.
31. grunt.registerTask('default', ['concat', 'uglify','sass']);
!

33.}

24.
files: {25.
'dist/js/app.min.js': ['dist/js/app.js']
26.
}
27.
}
28.
}
29. });
30.
31.
32. grunt.registerTask(‘default',
33.
‘concat',34.
‘uglify’35. ]);
36.
defaultタスクに登録
37.}
38.
39.
40.

$ grunt
Running "concat:option" (concat) task!

Running "concat:app" (concat) task
File dist/js/app.js created.
!

Running "uglify:app" (uglify) task>> 1 file created.
!

Running "sass:option" (sass) task!

Running "sass:app" (sass) task!

Done, without errors.

Done, without errors.

85

gulpﬁle.js• gulpの設定ファイル• タスクの処理を記述する

1. gulp= require('gulp');
2. concat = require('gulp-concat');
3. uglify = require('gulp-uglify');
4.
5.
6. gulp.task('js', function(){
プラグインを読み込む
7. return gulp.src('src/js/**/*.js')
8.
.pipe(concat('app.js'))9.
.pipe(uglify())
10.
.pipe(gulp.dest('./dist/js')); 処理ここから11.});!

13.gulp.task('sass', function(){
14. return gulp.src('src/scss/**/*.scss')
15.
.pipe(sass({ bundleExec: true }))16.
.pipe(gulp.dest('./dist/css'));17.});!
!

1. gulp= require('gulp');
2. concat = require('gulp-concat');
3. uglify = require('gulp-uglify');4.
対象のファイルたち
5.
6. gulp.task('js', function(){7. return gulp.src('src/js/**/*.js')
8.
.pipe(concat('app.js'))9.
.pipe(uglify())
10.
.pipe(gulp.dest('./dist/js'));11.});
12.
src/js/以下のすべての.jsファイルを読み込んで、
13.gulp.task('sass',
function(){
14. return gulp.src('src/scss/**/*.scss')「app.jsというファイルに結合」して、
15.
.pipe(sass({ bundleExec: true }))「そのファイルを圧縮」して、
16.
.pipe(gulp.dest('./dist/css'));「./dist/js/に保存」する17.});!
!

20.gulp.task('default', ['js', 'sass']);!

2. concat = require('gulp-concat');
3. uglify = require('gulp-uglify');
4. sass= require('gulp-sass');
5.
6.
7. gulp.task('js', function(){8. return gulp.src('src/js/**/*.js')
9.
.pipe(concat('app.js'))
10.
.pipe(uglify())
11.
.pipe(gulp.dest('./dist/js'));defaultタスクに登録12.});
13.
14.
15.gulp.task('default', ['js']);
16.
17.
18.

$ gulp[01:00:20] Using gulpfile ~/works/slide/getstarted-gulp/gulpfile.js[01:00:20] Starting 'js'...
[01:00:20] Starting 'sass'...
[01:00:20] Finished 'js' after 37 ms[01:00:20] Finished 'sass' after 37 ms[01:00:20] Starting 'default'...
[01:00:20] Finished 'default' after 6.39 μs

Finished 'default'91

http://goo.gl/EEPCqz

http://goo.gl/EEPCqz

https://github.com/cancer/get-started-gruntプロジェクトにGruntを使った例

photo by https://www.flickr.com/photos/quinnanya/2122300849

大規模サイトのリニューアル2013/08〜2015/02

• レスポンシブデザイン• JS制御によるUIも多数(カルーセル、検索絞り込み、ログインフォームなど)• 文字コードはUTF-8やShift̲JIS• 基本的には静的なHTML• サイトに応じたCSS/JSを作成

やったことHTMLテンプレート、コンポーネント集、

CSSファイルやJSファイルの結合・最適プレビュー
サーバー

自分

社内メンバー パートナー

ソース管理はGitを利用

納品は必要ファイルのみをZIP圧縮して送付

• HTMLテンプレート、コンポーネント集、
スタイルガイドの作成• CSSファイルやJSファイルの結合• ソース管理はGitを利用• 納品はZIPを送付

Gruntで行った内容

なぜGruntなのか1. Sass(scss)ビルド、結合
ベンダープリフィックスはCompassによって自grunt動で付与

combine-mq

2. メディアクエリをまとめる
3. CSSの圧縮

@media screen and (max-width: 959px) {/* Style1... */}@media screen and (max-width: 469px) {/* Style2... */}@media screen and (max-width: 959px) {/* Style3... */}@media screen and (max-width: 469px) {/* Style4... */}@media screen and (max-width: 959px) {/* Style1... */}@media screen and (max-width: 469px) {/* Style2... */}@media screen and (max-width: 959px) {/* Style3... */}@media screen and (max-width: 469px) {/* Style4... */}gruntcombine-mq@media screen and (max-width: 959px) {/* Style1... *//* Style3... */}@media screen and (max-width: 469px) {/* Style2... *//* Style4... */}gruntcombine-mq

compass: {SCSSからCSSを作成している部分
siteA: {options: {bundleExec: true,
config: 'config_siteA.rb',
environment: 'production'}},
siteB: {options: {bundleExec: true,
config: 'config_siteB.rb',
environment: 'production'}}},
cmq: {
siteA: {files: {'htdocs_siteA/common2/css/': ['htdocs_siteA/common2/css/*.css']}},
siteB: {environment: 'production'}}},
メディアクエリをまとめるCSSを作成している部分
cmq: {
siteA: {files: {'htdocs_siteA/common2/css/': ['htdocs_siteA/common2/css/*.css']}},
siteB: {files: {'htdocs_siteB/common2/css/': ['htdocs_siteB/common2/css/*.css']}}},
cssmin: {siteA: {expand: true,
cwd: 'siteA/common2/css/',
src: ['*.css'],
dest: 'siteA/common2/css/',
ext: '.css'},
siteB: {expand: true,
cwd: 'siteB/common2/css/',

'htdocs_siteB/common2/css/': ['htdocs_siteB/common2/css/*.css']}}},
cssmin: {siteA: {expand: true,
cwd: 'siteA/common2/css/',
src: ['*.css'],
dest: 'siteA/common2/css/',
ext: '.css'},
siteB: {expand: true,
cwd: 'siteB/common2/css/',
src: ['*.css'],
dest: 'siteB/common2/css/',
ext: '.css'}},

圧縮したCSSを作成している部分

},
!
!
!
!
!
!

grunt.registerTask('build_mincss_siteA', ['compass:siteA','cmq:siteA','cssmin:siteA']);!

grunt.registerTask('build_mincss_siteB', ['compass:siteB','cmq:siteB','cssmin:siteB']);!

1. JSファイルの結合
2. JSファイルの圧縮

ライブラリを結合している部分
concat: {minlib_siteA: {src: ['htdocs_siteA/common2/js/vendor/jquery-1.10.2.min.js','htdocs_siteA/common2/js/vendor/underscore-min.js','htdocs_siteA/common2/js/vendor/backbone-min.js'],
dest: 'htdocs_siteA/common2/js/lib_for_siteA.min.js'},
minlib_siteB: {src: ['htdocs_siteA/common2/js/modernizr.custom.js','htdocs_siteA/common2/js/vendor/jquery.cookie.min.js','htdocs_siteA/common2/js/vendor/underscore-min.js','htdocs_siteA/common2/js/vendor/backbone-min.js',],
dest: 'htdocs_B/common2/js/lib-for-old.min.js'},
script_siteA: {src: ['htdocs_siteA/common2/js/src/js-lineup.js','htdocs_siteA/common2/js/src/mod-unprintable.js','htdocs_siteA/common2/js/src/mod-togglableTable.js',

'htdocs_siteA/common2/js/vendor/backbone-min.js',],
dest: 'htdocs_B/common2/js/lib-for-old.min.js'},
プロジェクト用に書いたJSを結合している部分
script_siteA: {src: ['htdocs_siteA/common2/js/src/js-lineup.js','htdocs_siteA/common2/js/src/mod-unprintable.js','htdocs_siteA/common2/js/src/mod-togglableTable.js','htdocs_siteA/common2/js/src/mod-tab.js'],
dest: 'htdocs_siteA/common2/js/script.js'},
script_siteB: {src: ['htdocs_siteA/common2/js/src/js-lineup.js','htdocs_siteA/common2/js/src/mod-tab.js'],
dest: 'htdocs_siteB/common2/js/script-for-old.js'}},
uglify: {script_siteA: {options: {preserveComments: 'some',banner: '/*! <%= grunt.template.today("yyyy-mm-dd") %> */\n'},dest: 'htdocs_siteB/common2/js/script-for-old.js'}},
JSを圧縮している部分
uglify: {script_siteA: {options: {preserveComments: 'some',banner: '/*! <%= grunt.template.today("yyyy-mm-dd") %> */\n'},src: ['<%= concat.script_siteA.dest%>'],
dest: 'htdocs_siteA/common2/js/script-for-siteA.min.js'},
script_siteB: {options: {preserveComments: 'some',banner: '/*! <%= grunt.template.today("yyyy-mm-dd") %> */\n'},src: ['<%= concat.script_siteB.dest%>'],
dest: 'htdocs_siteB/common2/js/script-for-siteB.min.js'
}
}
!
!
!
!
!

}
}
!
!
!
!
!

圧縮して、結合したJSを作成するタスク

grunt.registerTask('build_minjs_siteA', ['concat:minlib_siteA','concat:script_siteA','uglify:script_siteA']);!
!

grunt.registerTask('build_minjs_siteB', ['concat:minlib_siteB','concat:script_siteB','uglify:script_siteB']);サイトごとに必要な
CSS/JSを生成する

サイトA

サイトA

サイトB

サイトA

サイトB

SCSSからCSSを作成している部分
compass: {siteA: {options: {bundleExec: true,
config: 'config_siteA.rb',
environment: 'production'}},
siteB: {options: {bundleExec: true,
config: 'config_siteB.rb',
environment: 'production'}}},
cmq: {
siteA: {files: {'htdocs_siteA/common2/css/': ['htdocs_siteA/common2/css/*.css']}},
siteB: {SCSSからCSSを作成している部分
compass: {siteA: {サイトA用のCSSを作成する部分
options: {bundleExec: true,
config: 'config_siteA.rb',
environment: 'production'}},
siteB: {サイトB用のCSSを作成する部分
options: {bundleExec: true,
config: 'config_siteB.rb',
environment: 'production'}}},
cmq: {
siteA: {files: {'htdocs_siteA/common2/css/': ['htdocs_siteA/common2/css/*.css']}},
siteB: {'htdocs_siteA/common2/js/modernizr.custom.js','htdocs_siteA/common2/js/vendor/jquery.cookie.min.js','htdocs_siteA/common2/js/vendor/underscore-min.js','htdocs_siteA/common2/js/vendor/backbone-min.js',],
dest: 'htdocs_B/common2/js/lib-for-old.min.js'

結合されたJSを作成している部分},
script_siteA: {src: ['htdocs_siteA/common2/js/src/js-lineup.js','htdocs_siteA/common2/js/src/mod-unprintable.js','htdocs_siteA/common2/js/src/mod-togglableTable.js','htdocs_siteA/common2/js/src/mod-tab.js'],
dest: 'htdocs_siteA/common2/js/script_siteA.js'},
script_siteB: {src: ['htdocs_siteA/common2/js/src/js-lineup.js','htdocs_siteA/common2/js/src/mod-tab.js'],
dest: 'htdocs_siteB/common2/js/script-siteB.js'
}

}
!
!
!

'htdocs_siteA/common2/js/modernizr.custom.js','htdocs_siteA/common2/js/vendor/jquery.cookie.min.js','htdocs_siteA/common2/js/vendor/underscore-min.js','htdocs_siteA/common2/js/vendor/backbone-min.js',],
dest: 'htdocs_B/common2/js/lib-for-old.min.js'

結合されたJSを作成している部分},
script_siteA: {サイトA用のJSを作成する部分
src: ['htdocs_siteA/common2/js/src/js-lineup.js','htdocs_siteA/common2/js/src/mod-unprintable.js','htdocs_siteA/common2/js/src/mod-togglableTable.js','htdocs_siteA/common2/js/src/mod-tab.js'],
dest: 'htdocs_siteA/common2/js/script_siteA.js'},
script_siteB: {サイトB用のJSを作成する部分
src: ['htdocs_siteA/common2/js/src/js-lineup.js','htdocs_siteA/common2/js/src/mod-tab.js'],
dest: 'htdocs_siteB/common2/js/script-siteB.js'
}

}
!
!
!

'htdocs_siteA/common2/js/modernizr.custom.js','htdocs_siteA/common2/js/vendor/jquery.cookie.min.js','htdocs_siteA/common2/js/vendor/underscore-min.js','htdocs_siteA/common2/js/vendor/backbone-min.js',],
dest: 'htdocs_B/common2/js/lib-for-old.min.js'

結合されたJSを作成している部分},
script_siteA: {サイトA用のJSを作成する部分
src: ['htdocs_siteA/common2/js/src/js-lineup.js','htdocs_siteA/common2/js/src/mod-unprintable.js','htdocs_siteA/common2/js/src/mod-togglableTable.js','htdocs_siteA/common2/js/src/mod-tab.js'],
dest: 'htdocs_siteA/common2/js/script_siteA.js'},
script_siteB: {サイトB用のJSを作成する部分
src: ['htdocs_siteA/common2/js/src/js-lineup.js','htdocs_siteA/common2/js/src/mod-tab.js'],
dest: サイトB用のJSを使う'htdocs_siteB/common2/js/script-siteB.js'
}

}
!
!
!

Hologramを使ってSCSSからスタイルガイドを生成Hologram結合されたJSを作成している部分

shell: {hologram_siteA: {options: {stdout: true,stderr: true},command: 'bundle exec hologram hologram/config_siteA.yml'},
hologram_siteB: {options: {stdout: true,stderr: true},command: 'bundle exec hologram hologram/config_siteB.yml'}},

結合されたJSを作成している部分

shell: {hologram_siteA: {サイトA用のスタイルガイドを作成する部分
options: {stdout: true,stderr: true},command: 'bundle exec hologram hologram/config_siteA.yml'},
hologram_siteB: {サイトB用のスタイルガイドを作成する部分
options: {stdout: true,stderr: true},command: 'bundle exec hologram hologram/config_siteB.yml'}},

納品に必要なファイル
だけZIPにする

サイトA用のZIPを作成している部分
compress: {siteA: {options: {archive: 'dist/siteA-<%= grunt.template.today("yyyy-mm-dd-HHMM") %>.zip'},
files: [ZIPを作成した日付{
expand: true,
cwd: 'siteA/',src: ['**','!common/**/vendor/**','!common/**/src/**'],dest: 'siteA/'}]},
siteB: {options: {archive: 'dist/siteB-<%= grunt.template.today("yyyy-mm-dd-HHMM") %>.zip'},
files: [{expand: true,サイトA用のZIPを作成している部分
compress: {siteA: {options: {archive: 'dist/siteA-<%= grunt.template.today("yyyy-mm-dd-HHMM") %>.zip'},
files: [{expand: true,
cwd: 'siteA/',src: ['**','!common/**/vendor/**',
ZIPに含めるファイル'!common/**/src/**'],dest: 'siteA/'}]},
siteB: {options: {archive: 'dist/siteB-<%= grunt.template.today("yyyy-mm-dd-HHMM") %>.zip'},
files: [{expand: true,サイトA用のZIPを作成している部分
compress: {siteA: {options: {archive: 'dist/siteA-<%= grunt.template.today("yyyy-mm-dd-HHMM") %>.zip'},
files: [{expand: true,
cwd: 'siteA/',src: ['**','!common/**/vendor/**',
ZIPに含めないファイル'!common/**/src/**'],dest: 'siteA/'}]},
siteB: {options: {archive: 'dist/siteB-<%= grunt.template.today("yyyy-mm-dd-HHMM") %>.zip'},
files: [{expand: true,Gruntファイルを共有し同じタスクを使う

Gruntのいいところ

複数の作業の自動化ができる状況に合わせた
タスクを作れる作業者間でGruntの設定を共有できるGruntの気になるところ

非エンジニアの導入コスト

Gruntファイルの肥大化

肥大化に伴うタスク実行時間実際にあった話

Shift_JISにしてほしいUTF-8

UTF-8

Shift_JIS

iconvLitemodule.exports = function(grunt){
var iconvLite = require('iconv-lite');!
!

/* ...

*/

copy:{
UTF-8からShift_JISに変換
script_siteB:{
options:{
encoding:'utf8',
process:function( content ){return iconvLite.encode(new Buffer(content),'shift_jis');}},files:{'<%= concat.script_siteB.dest%>': '<%= concat.script_siteB.des'<%= uglify.script_siteB.dest%>': '<%= uglify.script_siteB.des}}},圧縮されたJSから
一部別ファイルにしてほしいscript1.js

script2.js

script3.js

script4.js<script src="common2/js/script-for-siteA.min.js"></script>

uglify: {script_siteA: {options: {preserveComments: 'some',banner: '/*! <%= grunt.template.today("yyyy-mm-dd") %> */\n'},src: ['<%= concat.script_siteA.dest%>'],
dest: 'htdocs_siteA/common2/js/script-for-siteA.min.js'}},
concat: {結合したJSを作成している部分
script_siteA: {src: ['htdocs_siteA/common2/js/src/script1.js','htdocs_siteA/common2/js/src/script2.js',
別にしてほしい'htdocs_siteA/common2/js/src/script3.js','htdocs_siteA/common2/js/src/script4.js'],
dest: 'htdocs_siteA/common2/js/script-for-siteA.js'}}!

uglify: {script_siteA: {options: {preserveComments: 'some',banner: '/*! <%= grunt.template.today("yyyy-mm-dd") %> */\n'},src: ['<%= concat.script_siteA.dest%>'],
dest: 'htdocs_siteA/common2/js/script-for-siteA.min.js'}},
concat: {script_siteA: {src: ['htdocs_siteA/common2/js/src/script1.js','htdocs_siteA/common2/js/src/script2.js', 結合対象から削除'htdocs_siteA/common2/js/src/script4.js'],
dest: 'htdocs_siteA/common2/js/script-for-siteA.js'}}!

script1.js

script2.js

script4.js

script3.js<script src="common2/js/script-for-siteA.min.js"></script><script src="common2/js/script3.js"></script>

今回紹介したGruntファイル

http://goo.gl/Uhwyh3

プロジェクトに
gulpを使った例

photo by https://www.flickr.com/photos/pantlesscrab/2322046043

大規模サイトのリニューアル2014/07〜• レスポンシブデザイン• JS制御によるUIも多数(カルーセル、追従、検索絞り込みなど)• 文字コードはShift̲JIS(過去の資産がある)• phpで動いているやったことHTMLテンプレートとコンポーネント集の作成
約200個

独自の
アイコンフォントセット

CSSファイルやJSファイルの結合

プレビュー
サーバー

自分

メンバー

クライアントソース管理はGitを利用• HTMLテンプレート、コンポーネント集の作成• 独自のアイコンフォントセット作成• CSSファイルやJSファイルの結合• ソース管理はGitを利用gulpで行った内容

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.

'use strict';var es = require( 'event-stream' );var browserSync = require( 'browser-sync' );var reload = browserSync.reload;
var runSequence = require( 'run-sequence' );var exec = require( 'child_process' ).exec;
var gulp = require( 'gulp' );var autoprefixer = require( 'gulp-autoprefixer' );var concat = require( 'gulp-concat' );var csscomb = require( 'gulp-csscomb' );var plumber = require( 'gulp-plumber' );var rename = require( 'gulp-rename' );var sass = require( 'gulp-ruby-sass' );var uglify = require( 'gulp-uglify' );var watch = require( 'gulp-watch' );var autoprefixerBrowsers = [

18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.

var autoprefixerBrowsers = ['ie >= 8','ios >= 6','android >= 3.0'];
gulp.task( 'sass', function () {return gulp.src( '../XXX/css/src/**/*.scss' ).pipe( plumber() ).pipe( sass() ).pipe( autoprefixer( autoprefixerBrowsers ) ).pipe( gulp.dest( '../XXX/css/' ) ).pipe( csscomb() ).pipe( rename( { extname: '.min.css' } ) ).pipe( gulp.dest( '../XXX/css/' ) );} );1. Sass(scss)ビルド、結合2. ベンダープリフィックス自動付与
3. CSSの圧縮

36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.

} );
gulp.task( 'scripts:X', function () {return gulp.src( ['../XXX/js/src/X.js','../XXX/js/src/X.jsonpRequester.js','../XXX/js/src/SlideToggle.js','../XXX/js/src/X-returnToTop.js'] ).pipe( plumber() ).pipe( concat( 'X.js' ) ).pipe( gulp.dest( '../XXX/js/') ).pipe( uglify() ).pipe( rename( { extname: '.min.js' } ) ).pipe( gulp.dest( '../XXX/js/') );} );gulp.task( 'scripts:run', function () {

53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.

} );
gulp.task( 'scripts:run', function () {return gulp.src( ['../XXX/js/src/X-XXX1.js','../XXX/js/src/X-XXX2.js','../XXX/js/src/X-modules.js',] ).pipe( plumber() ).pipe( concat( 'X-run.js' ) ).pipe( gulp.dest( '../XXX/js/') ).pipe( uglify() ).pipe( rename( { extname: '.min.js' } ) ).pipe( gulp.dest( '../XXX/js/') );} );gulp.task( 'scripts:lib', function () {

70.
71. gulp.task( 'scripts:lib', function () {72.
73. return gulp.src( [74.
'../share5/js/libs/modernizr/modernizr.custom.js',
75.
'../XXX/js/libs/jquery/jquery.min.js',
76.
'../XXX/js/libs/underscore/underscore-min.js',
77.
'../XXX/js/libs/backbone/backbone-min.js',
78.
'../XXX/js/libs/EveEve/eveeve.min.js',
79.
'../XXX/js/libs/jquery.easing/jquery.easing.min.js',
80.
'../XXX/js/libs/EaseStepper/easestepper.min.js',
81.
'../XXX/js/libs/jQuery.EaseScroller/
82.
83.
84.
85.
86.

jquery.easescroller.min.js','../XXX/js/libs/jQuery.jsonp/
jquery.jsonp-2.4.0.min.js','../XXX/js/libs/imagesloaded/
imagesloaded.pkgd.min.js','../XXX/js/libs/Lineups/lineups.js','../XXX/js/libs/FitVids.js/jquery.fitvids.js','../XXX/js/libs/jQuery.socialthings/

101.
102.
103.
104.
105.

jquery.viewportwatcher.min.js','../XXX/js/libs/transit/jquery.transit.min.js','../XXX/js/libs/jQuery.touchdragh/jquery.touchdragh.min.js','../XXX/js/libs/jQuery.imgUtil/
jquery.imgutil.min.js','../XXX/js/libs/jQuery.DeferredPipeline/
jquery.DeferredPipeline.min.js','../XXX/js/libs/jQuery.WinEnterWatcher/jquery.winenterwatcher.min.js'// slideshow ---

106.
107.
108. ] )109. .pipe( plumber() )110. .pipe( concat( 'libs.js' ) )111. .pipe( gulp.dest( '../XXX/js/') );112.
113. } );114.
115. gulp.task( 'phpserver', function ( cb ) {1. JSファイルの結合
2. JSファイルの圧縮

113. } );114.
115. gulp.task( 'phpserver', function ( cb ) {116.
117. exec( 'php -S 0.0.0.0:8080 -t ../ router.php' );118. exec( 'open -a "/Applications/Google Chrome.app"

http://0.0.0.0:8080/' );119. cb();
120.
121. } );122.
123.
124. gulp.task( 'watch', function() {125.
126. gulp.watch( [ '../XXX/css/src/**/*.scss' ], [ 'sass',

reload ] );127. gulp.watch( [ '../XXX/js/src/**/*.js' ],[ 'scripts:s5', reload ] );128. gulp.watch( [ '../XXX/js/src/**/*.js' ],[ 'scripts:run', reload ] );• gulp起動時にexecでローカルサーバを起動gulpﬁle.js• gulpファイルを共有し、同じタスクを使う

• CSSの作成（Sass、ベンダープリフィクス自動付与、ファイル圧縮）• JSの作成（ファイル圧縮、ファイル結合）• execで独自ローカルサーバを起動• 設定を共有https://www.youtube.com/watch?v=fBWu8y7h7UM

gulpのいいところgulpはGrunt同様に作業を自動化できるgulp環境構築はGruntの経験を活かせる

個々のプロジェクトに適したタスクを作れる

作業者やクライアントとgulp設定を共有できるgulpの気になるところ

環境によって動かない
プラグインがあったあとは、gulp云々より構築の考え方まとめ1. Node.jsのインストール
2. Grunt/gulpのインストール
プロジェクトごとに設定を npm installタスクランナーは、
プロジェクトに関わる人全体の効率を上げる• Gruntとgulp、どちらかはやっておこう• 他人の設定をつかってはじめよう(フォローアップメールで配布します)www.codegrid.net

ありがとうございました@cancer6@geckotang@yomotsu