Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Webpackで作る
Vueコンポーネント開発環境 / Creating the Vue component development with Webpack.

022fe97731555344992c588527848cb7?s=47 hypermkt
March 16, 2018

Webpackで作る
Vueコンポーネント開発環境 / Creating the Vue component development with Webpack.

バーチー / GMO Pepabo, Inc.
2018.03.16 フロントエンドテックミーティング#1
https://tech.pepabo.com/2018/04/02/frontend-tech-meeting-1-report/

022fe97731555344992c588527848cb7?s=128

hypermkt

March 16, 2018
Tweet

Transcript

  1. όʔνʔ(.01FQBCP *OD ϑϩϯτΤϯυςοΫϛʔςΟϯά 8FCQBDLͰ࡞Δ
 7VFίϯϙʔωϯτ։ൃ؀ڥ

  2. ιϑτ΢ΣΞΤϯδχΞ
 1)1FS IUUQCMPHIZQFSNLUKQ όʔνʔ !IZQFSNLU

  3. ͸͡Ίʹ̏ͭ

  4. ର৅ऀ w7VFKTͷجૅจ๏͕෼͔Δ w7VFKTͰ࣍ͷϨϕϧʹߦ͖͍ͨ 

  5. ΰʔϧ w7VFKTͰίϯϙʔωϯτ։ൃ͕࢝ΊΒΕΔΑ͏ʹͳΔ 

  6. ࠓ೔͓࿩͢Δ͜ͱ w ݱঢ়ͷ՝୊ w ՝୊ղܾ w 8FCQBDLͱ஥ྑ͘ͳΖ͏ w 7VFKTͷίϯϙʔωϯτ։ൃ؀ڥΛ࡞Δ w

    ·ͱΊ 
  7. ࿩͞ͳ͍͜ͱ w ίϯϙʔωϯτͷઃܭ 

  8. ݱঢ়ͷ՝୊

  9. ՝୊ 7VFKTͷจ๏ͷجૅ͸෼͔ͬͨ
 ࣍ͷϨϕϧʹߦͨ͘ΊʹԿΛ͢΂͖͔

  10. 7VFKT෦Ͱ্͕Δ੠ !Ͳ͏΍ͬͨΒ7VFKTͷٕज़͕޲্Ͱ͖Δͷ͔ !جૅจ๏ͷ࣍ʹԿΛ͢΂͖͔  ※Vue.js෦ͱ͸ϖύϘࣾ಺ͷVue.jsษڧձ

  11. ՝୊ طଘͷ)5.- $44 +BWB4DSJQU ϑΝΠϧ͕ෳࡶ

  12. طଘͷ)5.- $44 +BWB4DSJQUϑΝΠϧ͕ෳࡶ )5.-ͷߦ਺͕௕͗ͯ͢ಡղࠔ೉ $44Ϋϥεͷ࢖༻Օॴ͕෼͔Βͳ͍ɻ
 ࡟আͨ͠ΒσβΠϯ่Ε͕ൃੜ +BWB4DSJQUͷؔ਺ͷ࢖༻Օॴ͕෼͔Βͳ͍ɻ
 ࡟আͨ͠Βޡಈ࡞ͨ͠  KBWBTDSJQUKT

    IFBEFSUQM
  13. ՝୊ղܾ

  14. 7VFKTͷػೳͰղܾͰ͖ͳ͍͔

  15. ίϯϙʔωϯτͳΒղܾͰ͖Δ

  16. ίϯϙʔωϯτ w )5.-ཁૉΛ࠶ར༻ՄೳʹΧϓηϧԽ͠ΧελϜλάͱ͠ ͯར༻Ͱ͖Δ  var Header = { template:

    ‘<div class=“title”><p>A custom component!</p></div>’ } new Vue({ // ... components: { 'my-header': Header } }) <div id="example"> <my-header></my-header> </div>
  17. ίϯϙʔωϯτͷϝϦοτ # )5.-λάͷݻ·ΓΛίϯϙʔωϯτʹू໿Ͱ͖Δ
 # Մಡੑ͕͕͋Δ # ίϯϙʔωϯτΛ࠶ར༻Ͱ͖Δ # ίϯϙʔωϯτ಺ʹؔ࿈͢Δ+BWB4DSJQUॲཧ΋
 ·ͱΊΒΕΔ

    
  18. ίϯϙʔωϯτͷσϝϦοτ +BWB4DSJQUͱ)5.-ίʔυ͕ࠞͬͯ͟ݟͮΒ͍ʜ )5.-ͷमਖ਼ࠔ೉ʜ ଟ਺ͷίϯϙʔωϯτΛએݴ͢Δͱ؅ཧͮ͠Β͍ʜ 

  19. ͋Εɾɾɾ
 ָ͠Α͏ͱͨ͠͸͕ͣɺ
 ۤ௧΁ٯ໭Γ

  20. ͦ͜Ͱ
 ୯ҰϑΝΠϧίϯϙʔωϯτ!!

  21. ୯ҰϑΝΠϧίϯϙʔωϯτ wίϯϙʔωϯτຖʹ)5.-  +BWB4DSJQU $44ίʔυΛ
 ͭͷϑΝΠϧʹ෼͚Δ͜ͱ ͕Ͱ͖Δ w֦ுࢠ͸WVF IUUQTKQWVFKTPSHWHVJEFTJOHMFpMFDPNQPOFOUTIUNM

  22. ୯ҰϑΝΠϧίϯϙʔωϯτແ͠ <body id="home" class=' is__responsive'> <header> <div id="header" class="common__header__area js-common__header__area">

    <div class="common__header__wrap clearfix"> <h1 class="common__header__logo__wrap"> <a href="/" title="ϗʔϜϖʔδ࡞੒αʔϏεͳΒʮάʔϖʯ" class="common__header__logo__link" id="logo"> <img src="/img/common/logo.png" alt="ϗʔϜϖʔδ࡞੒αʔϏεͳΒʮάʔϖʯ by GMOϖύϘ" class="common__header__logo js-common__header__logo" /> </a> </h1> <div class="common__header__menu__list__signup__sp__wrap js-common__header__menu__list__signup__sp__wrap"> <a href="/signup/" class="common__button common__button__signup header__menu__list__signup_sp" id="header_start_btn_free_sp">͸͡ΊΔ</a> </div> <nav> <span class="fa fa-menu common__header__menu__icon js-common__header__menu__icon"></span> <span class="fa fa-cross common__header__menu__close__icon js-common__header__menu__close__icon"></span> <div class="common__header__menu__wrap js-common__header__menu__wrap"> <ul class="common__header__menu__list__wrap clearfix"> <li class="hidden__pc__block visible__tb__block visible__sp__block"> <a href="/" class="header__menu__list__title__home header__menu__sp__visible" id="menu_0_home">ϗʔϜ</a> </li>
  23. ୯ҰϑΝΠϧίϯϙʔωϯτ༗Γ <body> <header-menu></header-menu> <header-slide></header-slide> <signup-button></signup-button> </body> )FBEFS.FOVWVF )FBEFS4MJEFWVF 4JHOVQ#VUUPOWVF ίϯϙʔωϯτ୯ҐͰ

    ϑΝΠϧ෼ׂͰ͖Δ
  24. ୯ҰϑΝΠϧίϯϙʔωϯτΛ࢖͏ʹ͸ w8FCQBDL #SPTFSJGZͳͲͷϞδϡʔϧόϯυϥʔ͕ඞཁ IUUQTKQWVFKTPSHWHVJEFTJOHMFpMFDPNQPOFOUTIUNM

  25. 8FCQBDLΛ࢖͓͏ w ओྲྀ͸8FCQBDL w 8FCQBDL͸$44ը૾ͳͲ΋·ͱΊΔ͜ͱ͕Ͱ͖Δ w #SPTFSJGZ͸+BWB4DSJQUϑΝΠϧͷΈ 

  26. WVFDMJͱ͍͏ͷ͕͋Γ·ͯ͠

  27. WVFDMJͱ͸ w 7VFKTެࣜͷίϚϯυϥΠϯΠϯλʔϑΣʔε w ίϚϯυϥΠϯͰߴ଎͔ͭ؆୯ʹ։ൃ؀ڥ͕ߏஙͰ͖Δ w IUUQTHJUIVCDPNWVFKTWVFDMJ 

  28. ࠷ॳ͔ΒWVFDMJΛ࢖༻͢Δͷ͸Φεεϝ͠ͳ͍ w ཧ༝ͱͯ͠ w 8FCQBDL #BCFMͷઃఆํ๏ͷཧղʹͭͳ͕Βͳ͍ w ॳظͰੜ੒͞ΕΔઃఆϑΝΠϧ͕ෳࡶͳͷͰमਖ਼ࠔ೉ w ࣗ෼ͷߟ͑ͱͯ͠

    w ࣗ෼͕ཧղɾ؅ཧͰ͖Δ΋ͷΛ࢖ͬͯ΄͍͠ 
  29. ·ͱΊ w 8FCQBDL 7VFKTͰ୯ҰϑΝΠϧίϯϙʔωϯτΛ࢖༻ ͯ͠ɺίϯϙʔωϯτ։ൃΛ࢝ΊΑ͏ 

  30. 8FCQBDLͱ஥ྑ͘ͳΖ͏

  31. લఏ w XFCQBDLWͷ͓࿩Ͱ͢ w ʹϦϦʔε͞Εͨ͹͔Γ w OQN͸ΠϯετʔϧࡁΈͱ͢Δ 

  32. 8FCQBDLͱ͸Կ͔ʁ

  33. Ϟμϯͳ+BWB4DSJQUΞϓϦέʔγϣϯ޲͚ͷ
 ϞδϡʔϧόϯυϥʔͰ͋Δ

  34. Ϟδϡʔϧόϯυϥʔͱ͸ w ෳ਺ͷϞδϡʔϧ KT TBTTͳͲ ΛҰͭͷϑΝΠϧʹ
 όϯυϧͯ͠ ·ͱΊͯ ͘ΕΔ΋ͷ 

    ग़యIUUQTXFCQBDLKTPSH
  35. ·ͣ͸؆୯ʹ৮ͬͯΈΑ͏

  36. ΍ͬͯΈΔ͜ͱᶃ w ̎ͭͷ+BWB4DSJQUϞδϡʔϧϑΝΠϧΛ݁߹ͯ͠ΈΔ w ϒϥ΢βͷ$POTPMFλϒʹ)FMMP8PSMEͱग़ྗ͠Α͏ 

  37.  ϑΝΠϧͱσΟϨΫτϦߏ੒ $ tree . . ├── index.html ├── package-lock.json

    ├── package.json ├── src │ ├── app.js │ ├── hello.js │ └── world.js └── webpack.config.js 1 directory, 7 files
  38.  8FCQBDLͷΠϯετʔϧ $ npm init -y
 $ npm install —-save-dev

    webpack webpack-cli wW͔ΒίϚϯυϥΠϯΠϯλʔϑΣʔε͕෼ׂ͞ΕͨͷͰ
 XFCQBDLDMJͷΠϯετʔϧ΋ඞཁ
  39.  8FCQBDLઃఆϑΝΠϧ const path = require('path'); module.exports = {
 //

    ΤϯτϦϙΠϯτͷઃఆ entry: './src/app.js', output: { // ग़ྗϑΝΠϧ໊
 filename: 'bundle.js', // ग़ྗઌσΟϨΫτϦ
 path: path.join(__dirname, 'dist/') } } XFCQBDLDPOpHKT
  40. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <script src="dist/bundle.js"></script>

    </body> </html> // export defaultͰؔ਺ΛϞδϡʔϧͱͯ͠ެ։͢Δ
 export default function hello() { return 'Hello'; } export default function world() { return 'World'; } JOEFYIUNM TSDIFMMPKT TSDXPSMEKT  // ֎෦Ϟδϡʔϧ͔ΒΤΫεϙʔτ͞Εͨؔ਺ΛΠϯϙʔτ͢Δ
 import hello from './hello.js'; import world from './world.js'; console.log(hello() + world()); TSDBQQKT
  41.  XFCQBDLͰϏϧυͯ͠όϯυϧϑΝΠϧΛੜ੒͢Δ $ npx webpack Hash: e7d757560adbd755bcca Version: webpack 4.1.1

    Time: 265ms Built at: 2018-3-15 23:17:15 Asset Size Chunks Chunk Names bundle.js 592 bytes 0 [emitted] main Entrypoint main = bundle.js [0] ./src/app.js + 2 modules 205 bytes {0} [built] | ./src/app.js 97 bytes [built] | ./src/hello.js 54 bytes [built] | ./src/world.js 54 bytes [built] WARNING in configuration The 'mode' option has not been set. Set 'mode' option to 'development' or 'production' to enable defaults for this environment. $ tree . . ├── dist │ └── bundle.js ├── index.html ├── src │ ├── app.js │ ├── hello.js │ └── world.js └── webpack.config.js 2 directories, 6 files ૿͑ͯΔ
  42.  ϒϥ΢βͰόϯυϧϑΝΠϧΛಡΈࠐΉ දࣔ͞Εͨ

  43. ΍ͬͯΈΔ͜ͱᶄ w &4͕࢖͑ΔΑ͏ʹ͠Α͏ w खॱ w 8FCQBDLͷϩʔμʔઃఆͰ&4ܗࣜͷ+BWB4DSJQU
 ϑΝΠϧ͕ಡΈࠐΊΔΑ͏ʹઃఆ͢Δ 

  44.  #BCFMͷΠϯετʔϧ $ npm install --save babel-loader babel-preset-es2015 wCBCFMMPBEFS#BCFMͷ8FCQBDL༻ϓϥάΠϯ w8FCQBDLʹઃఆ͢Ε͹+BWB4DSJQUϑΝΠϧΛ&4ม׵͠

    ͯ͘ΕΔ
  45.  ϩʔμʔઃఆ … // লུ module: { rules: [ {

    test: /\.js$/, // ϩʔμʔର৅ͷ֦ுࢠ use: [{ loader: ‘babel-loader', // ར༻͢Δϩʔμʔ options: { presets: ['es2015'] } }] } ] } XFCQBDLDPOpHKT wϩʔμʔઃఆͱ͸ɺ$44ͳͲ+BWB4DSJQUҎ֎ͷϑΝΠϧΛ ಡΈࠐΉઃఆ
  46.  ࣮ߦͯ͠ΈΑ͏ import hello from './hello.js'; import world from './world.js';

    const message = hello() + ' ES6’ // ES6ͷม਺એݴΛ࢖༻ console.log(message); TSDBQQKT wTSDBQQKTʹ&4ه๏ͷमਖ਼Λͯ͠OQYXFCQBDLΛ࣮ߦ wϒϥ΢βͷ$POTPMFϩάʹग़ྗ͞ΕΔ දࣔ͞Εͨ
  47. ͬ͘͟ΓͱҰ࿈ͷྲྀΕ͸
 ෼͔Γ·ͨ͠Ͱ͠ΐ͏͔

  48. ։ൃ༻αʔόʔXFCQBDLEFWTFSWFS w ϩʔΧϧαʔόʔΛىಈͰ͖Δ w ϑΝΠϧͷมߋΛݕ஌ͯࣗ͠ಈϏϧυͯ͠ɺϒϥ΢βଆ΋ ࣗಈతʹϦϩʔυ w গͳ͍ઃఆͰ͙͢ʹར༻Ͱ͖Δ 

  49. XFCQBDLEFWTFSWFSͷઃఆखॱ  $ npm install —-save-dev webpack-dev-server const path =

    require('path'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.join(__dirname, 'dist') }, devServer: { contentBase: path.join(__dirname, 'dist') }, } XFCQBDLDPOpHKT ᶃXFCQBDLEFWTFSWFSΛΠϯετʔϧ ᶄ഑৴ݩσΟϨΫτϦΛࢦఆ͢Δ
  50. XFCQBDLEFWTFSWFSͷઃఆखॱ  $ npx webpack-dev-server ᶅXFCQBDLEFWTFSWFSΛىಈ

  51. ޙ൒
 7VFKTͷίϯϙʔωϯτ։ൃ؀ڥΛ
 ࡞Ζ͏

  52. खॱ ؀ڥߏங 8FCQBDLͷΠϯετʔϧ 8FCQBDL։ൃαʔόʔͷઃఆ WVF͕ಡΊΔΑ͏ʹઃఆ͢Δ ϩʔμʔઃఆ ୯ҰϑΝΠϧίϯϙʔωϯτͷදࣔઃఆ ίϯϙʔωϯτϑΝΠϧͷ࡞੒ 

  53. ؀ڥߏங w ·ͣ͸ϓϩδΣΫτͷσΟϨΫτϦͷதͰ
 QBDLBHFKTPOΛ࡞੒͢Δ  $ mkdir webpack-with-vue
 $ cd

    webpack-with-vue
 $ npm init -y
  54. 8FCQBDLͷΠϯετʔϧ w ࣍ʹ8FCQBDLͱ։ൃ༻αʔόʔΛΠϯετʔϧ w ͜͜·Ͱ͸؆୯Ͱ͢Ͷ  $ npm install —-save-dev

    webpack webpack-cli webpack-dev-server
  55. 8FCQBDL։ൃαʔόʔͷઃఆ  const path = require('path'); module.exports = { entry:

    './src/index.js', output: { filename: 'bundle.js', path: path.join(__dirname, 'dist') }, devServer: { contentBase: path.join(__dirname, 'dist') }, } XFCQBDLDPOpHKT <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> Hello World </body> </html> EJTUJOEFYIUNM த਎͸ۭ TSDJOEFYKT
  56. ։ൃ؀ڥαʔόʔΛ֬ೝ͠Α͏  $ npx webpack-dev-server ίϯιʔϧ্

  57. WVF͕ಡΊΔΑ͏ʹઃఆ͢Δ 7VFΛΠϯετʔϧ͢Δ  $ npm install —-save vue $ npm

    install --save-dev vue-loader vue-template- compiler css-loader 7VFKTͷ୯ҰϑΝΠϧίϯϙʔωϯτ WVFϑΝΠϧ Λѻ ͏ͨΊʹҎԼΛΠϯετʔϧ
  58. ϩʔμʔઃఆ const path = require('path'); module.exports = { entry: './src/index.js',

    output: { filename: 'bundle.js', path: path.join(__dirname, 'dist') }, module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', } ] }, devServer: { contentBase: path.join(__dirname, 'dist') }, } XFCQBDLDPOpHKT
  59. ୯ҰϑΝΠϧίϯϙʔωϯτͷදࣔઃఆ <!DOCTYPE html> <html> <head> <meta charset="utf-8">
 <script src="./bundle.js"></script> <title></title>

    </head> <body> <div id="app"></div> </body> </html> EJTUJOEFYIUNM import Vue from 'vue'; import App from './components/App.vue'; window.onload = function() { new Vue(App).$mount('#app'); } TSDJOEFYKT w 8FCQBDLͰϏϧυͨ͠+4ΛಡΈࠐΉ w 7VFͰϚ΢ϯτ͢ΔՕॴΛࢦఆ w ը໘ͷಡΈࠐΈ͕׬ྃͨ͠Β
 BQQʹ"QQWVFΛϚ΢ϯτ ஔ͖׵͑ʣ
  60. ίϯϙʔωϯτϑΝΠϧͷ࡞੒ <template> <div> <header-component></header-component> <p class=“blue”>This is App component.</p> </div>

    </template> <script> import Header from './Header.vue'; export default { components: { 'header-component': Header } } </script> <style> .blue { color: blue; } </style> TSDDPNQPOFOUT"QQWVF <template> <div> <p class="title">{{ title }}</p> </div> </template> <script> export default { data: function() { return { title: 'This is Header component’ } } } </script> <style> .title { font-size: 20px; font-weight: bold; } </style> TSDDPNQPOFOUT)FBEFSWVF
  61. ϒϥ΢βͰදࣔ͢Δͱ "QQ$PNQPOFOU )FBEFS$PNQPOFOU

  62. ͥͻ೔ใΞϓϦΛ ୯ҰϑΝΠϧίϯϙʔωϯτԽ
 ͯ͠Έ͍ͯͩ͘͞

  63. ·ͱΊ

  64. ·ͱΊ w 8FCQBDLͷ֓ཁɺ؆୯ͳ࢖͍ํ͕෼͔ͬͨ w 7VFKTͷ୯ҰϑΝΠϧίϯϙʔωϯτͷϏϧυ؀ڥͷߏங ํ๏͕෼͔ͬͨ w7VFKTͷ࣍ͷϨϕϧ΁ߦ͜͏ʂʂ