Pro Yearly is on sale from $80 to $50! »

我が家の web フロントエンド開発・ビルド環境の遍歴

82ed567f8497acfed7f7b464225dd536?s=47 wakamsha
June 05, 2017

我が家の web フロントエンド開発・ビルド環境の遍歴

2017年6月5日の『We Are JavaScripters! @8th』で発表した資料です。

私がこれまで使用してきた web フロントエンド開発におけるビルド環境の遍歴をご紹介しています。それぞれの概要やユースケースは勿論、なぜそれを使うのをやめたのかについても言及しています。

#WeJS

82ed567f8497acfed7f7b464225dd536?s=128

wakamsha

June 05, 2017
Tweet

Transcript

  1. զ͕Ոͷ XFCϑϩϯτΤϯυ։ൃɾϏϧυ؀ڥͷวྺ - The itinerant history of our web frontend

    dev & build environment -  /BPLJ:"."%" !XBLBNTIB 8F"SF+BWB4DSJQUFST!UI
  2. Introduction w XBLBNTIB͕͜Ε·Ͱ࢖༻͖ͯͨ͠XFCϑϩϯτΤϯυ։ൃʹ͓͚Δ Ϗϧυ؀ڥͷวྺΛ͝঺հ w ͦΕͧΕͷ֓ཁ΍Ϣʔεέʔε͸໪࿦ɺͳͥͦΕΛ࢖͏ͷΛ΍Ίͨͷ͔ ʹ͍ͭͯ΋ݴٴ

  3.     OPX 

  4. Build static websites with an easy-to-use framework - 2013.early ~

    2014.early - Middleman
  5. Middleman 3VCZ੡ͷʰ੩తXFCαΠτδΣωϨʔλʱ 4JOBUSBͱ͍͏3VCZ੡%4-ʹґଘ 3VCZ 4JOBUSB

  6. Middleman ֦ுϝλݴޠͱͯ͠)BNM4$44 4BTT $P⒎FF4DSJQU͕ ࠷ॳ͔Β࢖༻Մೳ

  7. Middleman 3VCZ(FNTʹͯ഑෍͞Ε͍ͯΔͨΊ ίϚϯυϥΠϯͻͱͭͰΠϯετʔϧ׬ྃ $ gem install middleman $ middleman init

    my-project $ middleman server $ middleman build
  8. $ gem install middleman $ middleman init my-project $ middleman

    server $ middleman build w ๛෋ͳϔϧύʔϝιου w 3BJMTͱಉ͡΋ͷ͕΄΅࢖༻Մೳ w ࠷ॳ͔ΒϏϧυ؀ڥ͕׬੒͍ͯ͠ΔͷͰ௒ઈ͓खܰ w ֤छϝλݴޠͷίϯύΠϧ w -JWF3FMPBE w "TTFU1JQFMJOF +4 $44ͷ݁߹ϛχϑΝΠԽ  w FUDʜ
  9. w ϓϩμΫτͷXFCϑϩϯτΤϯυ։ൃͱ͍͏ΑΓ͸ ϓϩτλΠϐϯά؀ڥͱͯ͠׆༻ w 6*ݕূͷͨΊͷϞοΫΞοϓ w σϞ༻ w ͜Ε͕͔͋ͬͨΒࠓ೔ͷࣗ෼͕͍Δͱݴͬͯ΋աݴͰ ͸ͳ͍

    w "MU+4 "MU$44ͰίʔσΟϯά͠ɺϩʔΧϧαʔόͰಈ࡞֬ೝ͢Δ ͱ͍͏։ൃϑϩʔΛҰ௨Γମײ͢Δ͜ͱ͕ग़དྷͨ 6TFDBTF
  10. w 5ZQF4DSJQUΛϝΠϯͰ࢖͍ͨ͘ͳͬͨ w .JEEMFNBOͷΤίγεςϜ಺Ͱ͸54ΛίϯύΠϧग़དྷͳ͍ w (SVOU্Ͱ54ίϯύΠϧ.JEEMFNBO࣮ߦ͢Δ؀ڥΛߏங w ྑ͘΋ѱ͘΋ग़དྷΔ͜ͱ͕ܾ·͍ͬͯΔͨΊɺ͔ͦ͜Β͸Έग़͠ ͨ͜ͱΛ͠Α͏ͱ͢Δͱ్୺ʹϋοΫ·͕͍ͷ͜ͱΛ͢Δඞཁ͕ ͋Δ

    ଔۀͷ͖͔͚ͬ
  11.     OPX 

  12. The JavaScript Task Runner - 2014.early ~ 2015.early - Grunt

  13. Grunt +BWB4DSJQU੡ͷλεΫϥϯφʔ /PEFKT্Ͱಈ͘  XFCϑϩϯτΤϯυք۾ͰλεΫϥϯφʔ͕ຊ֨తʹ࢖ΘΕ͸͡ΊΔ͖͔͚ͬͱͳͬͨ

  14. w ϓϥάΠϯ /PEFϞδϡʔϧ ͕๛෋ w ͦΕΒΛ૊Έ߹Θͤͯཁ݅ʹదͨ͠Ϗϧυ؀ڥΛߏங w ֤छϝλݴޠ 5ZQF4DSJQU4$44+BEFʜ ͷίϯύΠϧ

    w ϩʔΧϧαʔόͷىಈ w -JWF3FMPBE w +4 $44ͷ݁߹ϛχϑΝΠԽ w FUDʜ w gruntfile.jsʹϋογϡܗࣜͰλεΫΛఆٛ w ˞$P⒎FF4DSJQUͰ΋هड़Մೳ
  15. w খن໛ͳαʔόʔϨεΞϓϦέʔγϣϯͷ։ൃ؀ڥ w 8PSE1SFTTͷςʔϚ։ൃ w +BWB4DSJQU͸5ZQF4DSJQU $44͸4$44Ͱهड़ͨ͠ͷΛϏϧυ 6TFDBTF

  16. w λεΫͷॻ͖΍͢͞Մಡੑ͕ΠϚΠν w άάͬͯݟ͚ͭͨίʔυΛίϐϖ͚ͨͩ͠Ͱಈ͍ͨ͜ͱ͕Ұ౓΋ ͳ͘ɺԿ͔͠Βͷख௚͕͠ඞཁͩͬͨ w ಉ͡໨తͰ΋ఆٛͷهड़͕݁ߏόϥ͍͍ͭͯΔ w ࢖͍͜ͳ͢લʹ(VMQʹڵຯ͕Ҡͬͨ ଔۀͷ͖͔͚ͬ

  17.     OPX 

  18. Automate and enhance your workflow - 2015.early ~ 2016.mid -

    Gulp
  19. Gulp /PEFKTͷ4USFBN"1* ΠϕϯτετϦʔϜ Λ޼Έʹར༻ͨ͠λεΫϥϯφʔ ΤϯδχΞք۾͚ͩͰͳ͘ɺσβΠφʔք۾Ͱ΋࢖ΘΕΔ͘Β͍ʹ·Ͱීٴ͍ͯ͠Δ

  20. w νΣʔϯϝιου෩ʹλεΫΛఆٛ w <ίϯύΠϧ><݁߹><ϛχϑΝΠ>ͷΑ͏ͳಉظతॲཧΛՄಡ ੑߴ͘ఆٛͰ͖Δ w ॲཧͷྲྀΕ͕௥͍΍͍͢ w (SVOUΑΓ΋هड़ʹ౷Ұײ͕͋Δ w

    ฒྻॲཧ͕ݪଇ w λεΫͷ࣮ߦ଎౓͕଎͍ w ˞(SVOU͸Ұͭͣͭॱ൪ʹॲཧ͢Δ
  21. w େن໛41"։ൃҊ݅ͷϑϩϯτΤϯυ։ൃج൫ w 5ZQF4DSJQU4$44+BEF 1VH ͷίϯύΠϧ w ϓϩμΫγϣϯίʔυͱґଘϥΠϒϥϦͱͷ݁߹ w ϩʔΧϧαʔόͷىಈͱXBUDI

    -JWF3FMPBE  w Ϗϧυ؀ڥͷຊ֨తͳߏஙϊ΢ϋ΢ͷଟ͘Λ͜ͷஈ֊ Ͱशಘ w /PEFKTͷ֓ཁ΋͜ͷࠒʹֶΜͩ ˞ͦ͜·Ͱਂ͘͸ཧղͯ͠ͳ͍ 6TFDBTF
  22. Browserify lets you require ( ‘modules’ ) in the browser

    by bundling up all of your dependencies - 2016.mid ~ 2016.later - Use Browserify
  23. w +BWB4DSJQUϑϨʔϜϫʔΫΛ࡮৽ w "OHVMBS΍$ZDMFKTͱ͍ͬͨΑΓϞμϯͳ'8Λݕূ w ˞࠷ऴతʹ$ZDMFKTΛ࠾༻ w CSPXTFSJGZΛಋೖ w +4ͷϞδϡʔϧؒͷґଘղܾ΍ϑΝΠϧ݁߹ͷͨΊʹඞཁ

    w Ϗϧυ࣌ؒ୹ॖͷͨΊʹXBUDIJGZ΋ซͤͯಋೖ ࠩ෼ίϯύΠϧ
  24. w CSPXTFSJGZΛ(VMQͷ4USFBN"1*Ͱ࢖͏ϝϦοτ͕ খ͍͞ͱ൑அ w WJOZMTPVSDFTUSFBNͰϥοϓͯ͠ແཧ΍Γ4USFBN"1*্ʹ৐ͤ ͯ͋͛Δඞཁ͕͋Δ w ϏϧυͷͨΊʹґଘ͢Δ/PEFϞδϡʔϧΛݮΒ͍ͨ͠ w (VMQ্Ͱಈ͔͢Ҏ্ɺ֤छίϯύΠϥͷ(VMQϥούʔ͕ඞཁ

    w όʔδϣϯ61ͨ͠Βಈ͔ͳ͘ͳͬͨͱ͍͏ϦεΫ͕૿͑Δ w ˞࣮ࡍʹԿ౓͔ಈ͔ͳ͘ͳΔ͜ͱ͕͋ͬͨ ଔۀͷ͖͔͚ͬ
  25.     OPX 

  26. npm scripts the “scripts” property of the package.json script, for

    following scripts - 2017.early ~ Now - npm-scripts
  27. npm-scripts λεΫϥϯφʔͱ͍͏ΑΓ͸TIFMMTDSJQUͷΤΠϦΞείϚϯυ iTerm my-project > npm run build > my-project@1.0.0

    watch /path/to/your/project/my-project > node ./bin/build.js ⋮
  28. iTerm my-project > npm run build > my-project@1.0.0 watch /path/to/your/project/my-project

    > node ./bin/build.js ⋮ w λεΫࣗମ͸TIϑΝΠϧ΍KTϑΝΠϧʹఆٛ w OQNTDSJQUT͸ͦΕΒΛ࣮ߦ͢Δ͚ͩ w .shͳΒbash task.sh w jsͳΒnode task.js w $JSDMF$*ͷcircle.ymlΈ͍ͨͳΠϝʔδ w (VMQ΄ͲෳࡶͳλεΫͷఆٛʹ͸޲͔ͳ͍͕ɺ͋Δ ఔ౓͸͜Ε͚ͩͰॆ෼ΧόʔՄೳ
  29. iTerm my-project > npm run build > my-project@1.0.0 watch /path/to/your/project/my-project

    > node ./bin/build.js ⋮ w /PEFϞδϡʔϧؒͷґଘ͕ܹݮ w (VMQ༻ͷϥούʔϞδϡʔϧ͕ෆཁ w ΞοϓσʔτʹΑΔյ໓ͱ͍͏ϦεΫ͕ܹݮ w ࣮ߦ଎౓͕ܶతʹ޲্
  30. my-project > npm run build > my-project@1.0.0 watch /path/to/your/project/my-project >

    node ./bin/build.js ⋮ iTerm w ݱߦͷ41"։ൃͷͨΊͷج൫ w 5ZQF4DSJQU4UZMVT1VHͷίϯύΠϧ w CSPXTFSJGZͰ+4Ϟδϡʔϧͷґଘؔ܎ΛղܾϑΝΠϧ݁߹ w ϑϩϯτΤϯυɾΤίγεςϜͷਐԽʹ൐ͬͯλεΫ ఆ͕ٛ؆ུԽ w +4ϑϨʔϜϫʔΫ͕ద੾ʹϞδϡʔϧԽ͞Ε͍ͯΔ w #PXFSΛ࢖Θͣͱ΋ຆͲͷ+4ϥΠϒϥϦ͕OQNܦ༝ͰΠϯε τʔϧͰ͖ΔΑ͏ʹͳͬͨ 6TFDBTF
  31. { "name": “my-project", "version": "1.0.0", "main": "index.js", "scripts": { "build":

    “node ./bin/build.js” }, "dependencies": { "@cycle/dom": "^17.3.0", "@cycle/run": "^3.1.0", "@cycle/rxjs-run": “^7.0.0", "ramda": "^0.24.1", "rxjs": "^5.4.0", "xstream": "^10.8.0" }, "devDependencies": { "browser-sync": "^2.18.11", "browserify": "^14.3.0", "connect-modrewrite": "^0.10.1", "pug": "^2.0.0-rc.1", "pug-cli": "^1.0.0-alpha6", "stylus": "^0.54.5", "tsify": "^3.0.1", "typescript": "^2.3.2", "watchify": "^3.9.0" } } package.json
  32. { "name": “my-project", "version": "1.0.0", "main": "index.js", "scripts": { "build":

    “node ./bin/build.js” }, "dependencies": { "@cycle/dom": "^17.3.0", "@cycle/run": "^3.1.0", "@cycle/rxjs-run": “^7.0.0", "ramda": "^0.24.1", "rxjs": "^5.4.0", "xstream": "^10.8.0" }, "devDependencies": { "browser-sync": "^2.18.11", "browserify": "^14.3.0", "connect-modrewrite": "^0.10.1", "pug": "^2.0.0-rc.1", "pug-cli": "^1.0.0-alpha6", "stylus": "^0.54.5", "tsify": "^3.0.1", "typescript": "^2.3.2", "watchify": "^3.9.0" } } package.json // Compile Pug sources execSync(`pug src/templates -o public -w`); // Compile Stylus sources execSync(`stylus src/styles/style.styl -o public/assets/style.css`); // Compile TypeScript sources let b = browserify({ entries: ['./src/scripts/main.ts'], cache: {}, packageCache: {}, plugin: [watchify], debug: true }) .plugin(tsify); b.on('update', bundle) bundle(); function bundle() { b.bundle().on('error', (err) => { console.log(err.message); }).pipe(fs.createWriteStream('./public/assets/main.js')); } // Run Server browserSync.create().init({ files: ['public'], server: { baseDir: ['public'] }, startPath: '/', reloadDebounce: 500 }); build.js
  33. { "name": “my-project", "version": "1.0.0", "main": "index.js", "scripts": { "build":

    “node ./bin/build.sh” }, "dependencies": { "@cycle/dom": "^17.3.0", "@cycle/run": "^3.1.0", "@cycle/rxjs-run": “^7.0.0", "ramda": "^0.24.1", "rxjs": "^5.4.0", "xstream": "^10.8.0" }, "devDependencies": { "browser-sync": "^2.18.11", "browserify": "^14.3.0", "connect-modrewrite": "^0.10.1", "pug": "^2.0.0-rc.1", "pug-cli": "^1.0.0-alpha6", "stylus": "^0.54.5", "tsify": "^3.0.1", "typescript": "^2.3.2", "watchify": "^3.9.0" } } package.json #!/usr/bin/env bash # Compile Pug sources nohup pug src/templates -o public -w & pug_pid=$! trap "kill -15 $pug_pid &>/dev/null" 2 15 # Compile Stylus sources nohup stylus src/styles/app.styl -o public/assets -m -w & stylus_pid=$! trap "kill -15 $stylus_pid &>/dev/null" 2 15 # Compile TypeScript sources nohup watchify -d src/scripts/main.ts -p [ tsify ] -o public/assets/ app.js & watchify_pid=$! trap "kill -15 $watchify_pid $>/dev/null" 2 15 # Run Server nohup browser-sync start --config bs-config.js & browserSync_pid=$! trap "kill -15 $browserSync_pid &>/dev/null" 2 15 tail -f nohup.out build.sh
  34. OPX w 1SFQBDL w $44.0%6-&4 w FUDʜ ࠓޙ࢖ͬͯΈ͍ͨ΋ͷ

  35. *OUSPEVDFNZTFMG Զͷ໊લΛݴͬͯΈΖ ࣗݾ঺հ

  36. גࣜձࣾϦΫϧʔτϚʔέςΟϯάύʔτφʔζ XFCϑϩϯτΤϯυΤϯδχΞ ࢁా ௚थ /BPLJ:"."%" *OUSPEVDFNZTFMG !XBLBNTIB

  37. https://tech.recruit-mp.co.jp NET BIZ DIV. TECH BLOG

  38. None
  39. https://tech.recruit-mp.co.jp 3.1 ϒϩά

  40. 5IBOLZPV