Slide 1

Slide 1 text

Introduction to Grunt Shuhei Kagawa

Slide 2

Slide 2 text

I was surprised to find that 80-90% of the time spent by users waiting for pages to load is spent on the frontend, all the work that needs to be done after the HTML document has arrived. ! —Steve Souders (2007). High Performance Web Sites

Slide 3

Slide 3 text

+4 $44ך 穠さ٥剑㼭⻉ 歗⫷ 47(ך ؟؎ؤ⵴幾 4BTT $PFF4DSJQUך ؝ٝػ؎ٕ +4 $44 )5.- ךثؑحؙ Ꟛ涪欽؟٦غ٦ ך饯⹛ +BWB4DSJQUך 荈⹛ذأز أة؎ٕؖ؎س ך⡲䧭 זוזו ؿٗٝزؒٝسדװ׶׋ְֿהכ 㟓ִ׷♧倯٥٥٥

Slide 4

Slide 4 text

$ python -m SimpleHTTPServer $ uglify foo.js bar.js -o out.js $ cssmin foo.css > foo.min.css $ imagemin foo.png > foo.min.png $ svgmin foo.svg > foo.min.svg $ jshint foo.js $ jscs foo.js $ csslint foo.css $ compass …

Slide 5

Slide 5 text

$ grunt

Slide 6

Slide 6 text

+BWB4DSJQUד剅ַ׸׋ةأؙٓٝش٦կ ! 鞢㺡זفؚٓ؎ٝ ⦐⟃♳ָ䲿⣘ׅ׷ة أؙ׾㹋遤ׅ׷خ٦ٕկ ! ؿٗٝزؒٝسꟚ涪ךرؿ؋ؙزأةٝت٦سկ (PPHMF 5XJUUFS "EPCF K2VFSZ .P[JMMBזודⵃ欽կ

Slide 7

Slide 7 text

Gruntfile.js grunt-contrib-less grunt-contrib- requirejs grunt-contrib-sass ぐ珏خ٦ٕ ぐ珏فؚٓ؎ٝ 鏣㹀ؿ؋؎ٕ (SVOU

Slide 8

Slide 8 text

Ⱅ䒭فؚٓ؎ٝgrunt-contrib-* ؿ؋؎ٕ乼⡲ DMFBO DPQZ DPODBU TZNMJOL ؝٦سثؑحؙ KTIJOU DTTMJOU Ꟛ涪佄䴂 XBUDI DPOOFDU MJWFSFMPBE 㖇簭 VHMJGZ DTTNJO JNBHFNJO IUNMNJO SFRVJSFKT DPNQSFTT "MU999 MFTT DPFF DPNQBTT TBTT TUZMVT ذٝفٖ٦ز KBEF IBOEMFCBST KTU +4⽃⡤ذأز RVOJU OPEFVOJU KBTNJOF سًُؗٝز欰䧭 ZVJEPD

Slide 9

Slide 9 text

ְְהֿ׹ ˖ ةأؙ׾荈⹛⻉דֹ׷կ ˖ ةأؙך僇俑⻉ח״׶ث٦يדꟚ涪׃װׅ ֻז׷կ ˖ ♧אךخ٦ٕד圫ղזةأؙ׾㹋遤דֹ ׷կ ˖ فؚٓ؎ٝةأؙָ鞢㺡կ ˖ ِ٦ؠ٦٥䞔㜠ָ㢳ְկ ˖ 8JOEPXTד׮ⵃ欽׃װְׅկ

Slide 10

Slide 10 text

⢪ְ倯

Slide 11

Slide 11 text

欽䠐ׅ׷׮ך ! ⴱ㔐׌ֽ /PEF OQN HSVOUDMJ ! فٗآؙؑز׀ה QBDLBHFKTPO (SVOUMFKT

Slide 12

Slide 12 text

˖ +BWB4DSJQUך㹋遤橆㞮կـٓؐؠך㢩ד+BWB4DSJQU׾⹛ ַֿׅהָדֹ׷կ ˖ (SVOU׾⹛ַׅךח䗳銲կ ˖ (SVOU劤⡤װぐ珏(SVOUفؚٓ؎ٝ׮/PEFKTךفؚٗٓ يկ

Slide 13

Slide 13 text

˖ /PEFךٌآُ٦ٕ盖椚ءأذيկ ˖ /PEFד⢪ֲفؚٗٓيך鿇ㅷٌآُ٦ٕ׾؎ٝأز٦ ٕׅ׷ֿהָדֹ׷կ ˖ (SVOU劤⡤׮ぐ珏(SVOUفؚٓ؎ٝ׮OQNٌآُ٦ٕה׃ ג盖椚ׁ׸גְ׷կ ˖ (SVOUفؚٓ؎ָٝⵃ欽ׅ׷خ٦ٕ荈⡤׮OQNךٌآُ٦ ٕד֮׷ֿהָ㢳ְկKTIJOUװDTTMJOUזוկ ˖ ֿך㜥さכծخ٦ٕ荈⡤׮(SVOUفؚٓ؎ٝה♧筰ח؎ ٝأز٦ٕדֹ׷կ ˖ $PNQBTTכ3VCZ醡זךדծOQNٌآُ٦ٕדכזְկ

Slide 14

Slide 14 text

Installation on Windows ˖ ✲⵸ח؎ٝأز٦ٕ ˖ /PEFY ˖ ِ٦ؠ橆㞮㢌侧ך1"5)ח %USERPROFILE%\AppData\Roaming\npm׾鷄 ⸇ׅ׷ֿה ˖ 3VCZY $PNQBTT⢪ֲ㜥さ ˖ ؎ٝأز٦ٕ儗ח1"5)鷄⸇ׅ׷ؔفءّٝ׾ ثؑحؙׅ׷ֿה

Slide 15

Slide 15 text

Installation on Mac • $ brew update • $ brew install node ˖ ⡭酔ָ֮׸לOWNֶָׅׅ׭ $ curl https://raw.githubusercontent.com/creationix/nvm/ v0.12.2/install.sh | bash $ nvm install v0.10.29 $ nvm alias default 0.10.29 • $ brew install ruby ˖ ⡭酔ָ֮׸לSCFOWֶָׅׅ׭ $ brew install rbenv ruby-build $ rbenv install 2.1.2 $ rbenv global 2.1.2 $ rbenv rehash

Slide 16

Slide 16 text

grunt ίϚϯυͷΠϯετʔϧ $ npm install -g grunt-cli ! ⟃♴ך״ֲחז׸ל䧭⸆կ ! $ grunt grunt-cli: The grunt command line interface. (v0.1.13) ! Fatal error: Unable to find local grunt.

Slide 17

Slide 17 text

package.json ˖ OQNٌآُ٦ٕך㹀纏ؿ؋؎ٕկ ˖ فٗآؙؑز嫣ח⡲䧭ׅ׷կ荈ⴓ׋׍ךفٗ آؙؑز׮OQNٌآُ٦ٕהְֲ罋ִ倯կ ˖ ׉ךفٗآؙؑزח䗳銲זOQNػح؛٦آ ׾鎸鶢׃גֶֻ(SVOU劤⡤ծ(SVOUךぐ珏 فؚٓ؎ٝזוկׅ׷הծוֿד׮OQN ׾⢪׏ג䗳銲זػح؛٦آ׾؎ٝأز٦ٕד ֹ׷կ

Slide 18

Slide 18 text

package.json ͷ࡞੒ ת׆QBDLBHFKTPO׾⡲䧭կ $ npm init ! ٌآُ٦ٕ׾؎ٝأز٦ٕ׃אאծQBDLBHFKTPOך EFW%FQFOEFODJFTח鎸ꐮׅ׷կ荈ⴓד剅ֻ״׶嚂կ $ npm install -save-dev grunt $ npm install -D grunt-contrib-connect ! فٗآؙؑزח鷿⚥ַ׵⿫⸇ׅ׷זוծQBDLBHFKTPOָׅדח דֹגְ׷㜥さכծ剅ַ׸גְ׷ٌآُ٦ٕ׾؎ٝأز٦ٕկ $ npm install

Slide 19

Slide 19 text

(SVOUMFKT ˖ (SVOUך鏣㹀ؿ؋؎ٕկ ˖ +BWB4DSJQUד鎸鶢ׅ׷$PFF4DSJQUד׮〳կ ˖ فٗآؙؑز嫣ח⡲䧭կ׉ךفٗآؙؑزד䗳銲ז ةأؙה׉ך鏣㹀׾鎸鶢ׅ׷կ ˖ ֿ׸ָ剅ֽ׸לծ֮הכ㹋遤ׅ׷׌ֽ ˖ ؟ٝفٕIUUQHSVOUKTDPNTBNQMFHSVOUMF

Slide 20

Slide 20 text

module.exports = function(grunt) { // Task, Target ͷઃఆ grunt.initConfig({ // Config Object }); ! // ϓϥάΠϯͷಡΈࠐΈʢϓϥάΠϯʹ͸ Task ͕ೖ͍ͬͯΔʣ grunt.loadNpmTasks(‘plugin1’); grunt.loadNpmTasks(‘plugin2’); ! // ಠࣗλεΫͷొ࿥ʢϓϥάΠϯʹೖ͍ͬͯΔλεΫΛ૊Έ߹Θͤ Δʣ grunt.registerTask(‘sometask’, [‘task1:target1’, task2:target2’]); grunt.registerTask(‘default’, [‘sometask’]); };

Slide 21

Slide 21 text

珏겲ך5BTL "MJBT5BTL 醱侧ך5BTL׾♧אחתה׭׷ךח⢪ֲկ HSVOUSFHJTUFS5BTL ˎCVJMEˏ <ˎDPODBUˏ ˎVHMJGZˏ ˎDTTNJOˏ> HSVOUCVJMECVJME5BTL׾㹋遤 ! .VMUJ5BTL 醱侧ך5BSHFU׾䭯אկ 㣐⼱ךفؚٓ؎ָٝ欽䠐ׅ׷5BTLכֿ׸կ HSVOUGPPCBSGPP5BTLךCBS5BSHFU׾㹋遤 HSVOUGPPGPP5BTLךⰋ5BSHFU׾㹋遤 ! #BTJD5BTL #BTJDזךחծ֮ת׶⢪׻׸זְկ 荈ⴓד⟣䠐ךةأؙ׾鷄⸇ׅ׷ꥷח⢪ֲה葺ְַ׮կ

Slide 22

Slide 22 text

Config Multi Task Target options options files Target options files Multi Task Target options options files Target options files Target ڞ௨ Target ݻ༗

Slide 23

Slide 23 text

grunt.initConfig({ concat: { options: { separator: ';' }, js: { src: ['src/**/*.js'], dest: ‘dist/grunt-helloworld.js’ } } }); Task Target

Slide 24

Slide 24 text

ؿ؋؎ٕػأ 5BSHFUחכⳢ椚׃׋ְؿ؋؎ٕךؿ؋؎ٕػأ׾䭷㹀կ TSD EFTU MFT MUFS瘝ծ剅ֹ倯כְ׹ְ׹֮׷կ ת׆כTSD EFTUך剅ֹ倯ָ׻ַ׶װְׅךדֶׅׅ׭կ ؿ؋؎ٕ׾⳿⸂׃זְ5BTLחכEFTUכ䗳銲זְկ KTIJOUזוկ ! PQUJPOT ؿ؋؎ٕػأך➭ծPQUJPOTח׉ך5BTL㔿剣ךؔفءّ ٝ׾䭷㹀կ 5BSHFUח䭷㹀ׅ׷הծ׉ך5BSHFU׌ֽկ 5BTLח䭷㹀ׅ׷הծ5BSHFUⰟ鸐ד黝欽ׁ׸׷կ ⚕倯דずׄ갪湡ָ䭷㹀ׁ׸גְ׋׵5BSHFUך倯ָ⮚⯓կ

Slide 25

Slide 25 text

grunt.initConfig({ concat: { options: { separator: ';' }, js: { src: ['src/**/*.js'], dest: ‘dist/grunt-helloworld.js’ } } }); Options Files

Slide 26

Slide 26 text

$ grunt connect:server:keepalive task target flag

Slide 27

Slide 27 text

$ grunt task:target:flag1:flag2

Slide 28

Slide 28 text

فؚٓ؎ٝ稱➜

Slide 29

Slide 29 text

grunt-contrib-jshint +BWB4DSJQU׾ثؑحؙ׃ג㉏겗ָ֮׸ל陨デ׾邌爙կ 鏣㹀כKTIJOUSDהְֲؿ؋؎ٕח鎸鶢׃גֶֻהծؒر؍ةד KTIJOU׾ⵃ欽ׅ׷ꥷח׮⢪ִג葺ְկٓ؎ـٓٔזוثؑحؙ׃ז ְؿ؋؎ٕכKTIJOUJHOPSFח剅ְגֶֻկ ! jshint: { all: { src: [’Gruntfile.js’, ‘src/js/**/*’], options: { jshintrc: true } } }

Slide 30

Slide 30 text

grunt-contrib-uglify +BWB4DSJQU׾穠さ٥㖇簭٥ꨇ铣⻉կ ! uglify: { all: { src: [‘src/js/foo.js’, ‘src/js/bar.js’], dest: ‘public/js/bundle.js’ } }

Slide 31

Slide 31 text

grunt-contrib-imagemin 歗⫷׾㖇簭կ(*' +1&( 1/( 47(ח㼎䘔կ PQUJPOTכؿ؋؎ٕך珏겲׀החⴽזךדծؿ؋؎ٕך珏겲ד5BSHFU׾ⴓֽ׷䗳銲 כזְկ TSDחؿ؋؎ٕػة٦ٝ׌הֲתֻ⹛ַזַ׏׋ךדծMFTד鎸鶢׃גְתׅկ ! imagemin: { all: { files: { expand: true, cwd: ‘src/img/‘, src: [‘*.{jpg,svg,png,gif}’], dest: ‘dist/img/’, } } }

Slide 32

Slide 32 text

grunt-contrib-compass DPNQBTTד4BTT׾ؽٕسկ DPOHSC׾䭷㹀ׅ׷׌ֽד0,կDPOHSCח䭷㹀ׅ׷ ״ֲזⰻ㺁׾(SVOUMFKTⰻד䭷㹀ׅ׷倯岀׮֮׷կ ! compass: { all: { options: { config: ‘config.rb’ } }

Slide 33

Slide 33 text

grunt-contrib-watch ؿ؋؎ٕ׾湊鋔׃ծ㢌刿ָ֮׸ל5BTL׾㹋遤ׅ׷կ 鏣㹀ָ暴婊דMFT UBTLTהPQUJPOTկMFTח㢌刿ָ֮׸ לծUBTLT׾㹋遤ׅ׷կ➭ך5BTLה♧筰ח㹋遤ׅ׷ꥷכ ♧殢剑䖓חׅ׷ֿהկ ! watch: { js: { files: [‘src/js/**/*.js’], tasks: [‘jshint’, ‘uglify’] } }

Slide 34

Slide 34 text

grunt-contrib-connect Ꟛ涪欽ך؟٦غ׾饯⹛ׅ׷կ (SVOUך㹋遤ָ穄׻׷ה؟٦غ׮穄✪ׅ׷ךד岣䠐կ穄׻׵זְ״ ֲחׅ׷חכHSVOUDPOOFDUTFSWFSLFFQBMJWFהׅ׷կXBUDIה♧ 筰ח⢪ִלLFFQBMJWFכ♶銲կ ! connect: { server: { options: { port: 8000, base: ‘dist’ } } }

Slide 35

Slide 35 text

grunt-spritesmith 歗⫷ַ׵$444QSJUF欽$44׾欰䧭կ鏣㹀ָ暴婊דPQUJPOT׾ ⢪׻זְկ$PNQBTTה嫰ץג歗⫷ך⚛ץ倯׾厫鮾ח寸׭׵׸ ׷׵׃ְկ ! spritesmith: { all: { src: ‘src/img/sprites/*.png’, destImg: ‘dist/img/spritesheet.png’, destCSS: ‘dist/css/sprites.css’, algorithm: ‘alt-diagonal’ } }

Slide 36

Slide 36 text

鑫稢כծぐفؚٓ؎ٝךسًُؗٝز׾⿫撑 ! 鏣㹀חכفؚٓ؎ٝ׀הח䊴殯ָ֮׷ךדծسًُؗ ٝزח⛦׏גְ׷⢽׾⿫罋חׅ׷ךָ搀ꨇկ

Slide 37

Slide 37 text

Slide 38

Slide 38 text

23BJMTזוך؟٦غ؟؎سؿٖ٦يٙ٦ؙד׮ずֿׄ הָדֹ׷ךדכ ! "׋׃ַח"TTFUT1JQFMJOFד׮֮׷鿇ⴓ$PFF4DSJQU 4BTT .JOJGZזוחאְגכծ知⽃חדֹ׷կ׃ַ׃ծ ׉׸⟃♳ךֿה׾װ׹ֲהׅ׷ה㣐㢌կ (SVOUכفؚٓ؎ִׁ֮ٝ׸ל⡦ד׮דֹ׷կ ת׋ծ؟٦غ٦؟؎سךؿٖ٦يٙ٦ؙꟼ⤘זֻ⢪ִ׷ ךָ剑㣐ךًٔحزկ

Slide 39

Slide 39 text

2HVMQזו겲⡂خ٦ٕהך麩ְכ ! "(SVOUכةأؙ嫣ח穠卓׾ؿ؋؎ٕח剅ֹ鴥׬ךד 鹼ְկ鏣㹀ؿ؋؎ٕ׮ꞿֻז׶ָ׍կ ׃ַ׃ծ⯓涪זךדفؚٓ؎ٝװ䞔㜠ָ⯍㹋׃גְ ׷կת׋(SVOUכ/PEF׏שֻזְךדծ/PEF䢪׸׃ גְזְ➂ח׮⢪ְװְַׅ׮ ! HVMQכծ4USFBNזו/PEFך濼陎ָ⵸䲿חז׏גְ׷ ָծ鏣㹀ؿ؋؎ٕ׾ꬊ䌢חءٝفٕח剅ֽ׷׃ծⳢ椚 ׮鸞ְկفؚٓ؎ٝ׮׉׸ז׶ח⯍㹋կ♧䏝鋅ג׫גծ 孡חⰅ׏׋倯׾⢪ֲה葺ְַ׮կ ! #SPDDPMJזוחאְגכծ״ֻ濼׵זְկ