つぶやき勉強会 拡大版 webpack入門編

今回は webpack についてです。

rails5.1に取り込まれるなど、いよいよ感が出てきましたね。
この記事で、概要を掴んで、動かせるようになっておきましょう。
webpacker(rails 5.1)との絡みもあるよ！

---

# 対象読者、前提条件、環境
- webpack何それおいしいの？な人
- 間違いがあったらご指摘お願いします
- webpack 2.3.3  
  最近2.x系がでた。公式は2.x系を推奨、rails5.1も2.x系

---

## 目標
大規模アプリケーション向けにwebpackを導入できるようになる。
（🌾 SPAじゃないって意味での大規模アプリケーション）

---

# What is webpack?
<img width="416" alt="スクリーンショット 2017-03-27 21.00.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/7442/b39de303-e12a-5035-1f58-c8e0bb6ff1dc.png">

---

## what is webpack?
- nodejsで動く、jsのコンパイラのイメージ
- jsにモジュールの概念がくる
- いろんな前処理ができる
  - minifyとかsourcemap生成とか
- Hot Module Replacement(ブラウザ自動更新的な)
- css,imgもモジュールになる

---

## jsにモジュールの概念がくる

- 読み込み順序を気にしなくていい
- 再利用しやすい
- ネームスペース汚染対策

---

### 読み込み順序を気にしなくていい
- これまで

```hoge.html
<script src="js/common.js"></script><!-- 最初に読む -->
<script src="js/util.js"></script>
<script src="js/hoge.js"></script><!-- util.jsが先 -->
```

---

### 読み込み順序を気にしなくていい

- これから

```hoge.html
<script src="js/hoge.js"></script>
```
webpackが1つにまとめてくれる
js同士の依存関係はよしなにしてくれる

---

### 再利用しやすい

ブラウザに向けたjsでも

- commonjs
- es2015(es6)
- AMD

で書ける！！！

---

### ネームスペース汚染対策
即時関数がいらない！
ネームスペースがモジュール単位で区切られる

- グローバルに変数置きすぎて意味不明に
- グローバルに変数置きすぎて名前がかぶる

とかが減る

---

## ちなみに過去5年のGoogleTrends

![material_002.jpg](https://qiita-image-store.s3.amazonaws.com/0/7442/a30900d8-e9c6-4277-7f25-b6f57292cadb.jpeg)

ぶっちぎりwebpack

---

## ちなみに過去5年のGoogleTrends
タスクランナーも入れてみる

![material_001.jpg](https://qiita-image-store.s3.amazonaws.com/0/7442/23a229d9-062f-0918-d895-dcb78eabd8af.jpeg)

webpack以外はダウントレンド

---

## webpack導入

---

## webpack導入
### npmでok

```
$ npm install --save webpack@1.14
```

---

## webpack導入

### rails 5.1 beta

新規作成時

```
$ rails new with-webpack --webpacker
```

すでにあるプロジェクトにインストールする

```
$ vi Gemfile
gem 'webpacker', github: "rails/webpacker"
$ bundle install
$ bin/rails webpacker:install
```

※ yarnが必要になります（npmの上位互換的なやつ）

---

## webpackを使う
### 知っておくこと
1. entry

### やること
1. configを書く
2. コードを書く
3. コンパイルする

---
###  知っておくこと entry
jsの依存関係を解決するときの出発点になるファイル

![スクリーンショット 2017-03-27 17.39.09.png](https://qiita-image-store.s3.amazonaws.com/0/7442/0919f6c5-6cb0-01ae-0928-a81221d241fc.png "スクリーンショット 2017-03-27 17.39.09.png")

- ≒ htmlで読むjsファイル
- sassで言うところのパーシャルはentryじゃない
  - toppage.sass ← entry的
  - _color.sass

---
### やること configを書く
ファイル名は `webpack.config.js` がデフォ

```webpack.config.js
module.exports = {
  // ここに設定を書いていく
};
```

---

### configを書く

![material_016.jpg](https://qiita-image-store.s3.amazonaws.com/0/7442/ed100387-239f-1357-a0fe-b5dc9eb14605.jpeg)

`entry.js` と `user.js` が `require('./modal')` してる状態

---

### configを書く

```webpack.config.js
module.exports = {
  entry: {              // entryとなるファイルを指定する
    entry: './entry.js',
    user: './user.js'
  },
  output: {             // entryの出力先を指定する
    filename: '[name].js',  // [name]はentryのkey
    path: __dirname + '/build'
  }
};
```

`./build/entry.js` , `./build/user.js` ができる。
`modal.js` に関しては特に何も書かなくていい。

---

### configを書く
entryがたくさんあるとそれぞれ書いていられない
→ コンパイル時に走査する

```webpack.config.js
var glob = require('glob');

var path = __dirname + '/js';
var entries = glob.sync("**/*.js", {cwd: path}).reduce(function (entries, file) {
  entries[file] = [path + file];
  return entries;
}, {});

module.exports = {
  entry: entries,
  output: {
    filename: '[name]',
    path: __dirname + '/build'
  }
}
```

---

## コードを書く

---

## コードを書く
commonjs

```modal.js
var Modal = function() {
};

Modal.prototype.show = function(msg) {
    console.log(msg);
};

var var_in_modal = 'hogehoge';

module.exports = Modal;  // キモ
```

```entry.js
var Modal = require('./modal');

var modal = new Modal();
modal.show('entry in modal');
```

```user.js
var Modal = require('./modal');

var modal = new Modal();
modal.show('complate!');
modal.show(var_in_modal);
```

---

## コンパイルする

```
$ webpack                        // webpack.config.js でコンパイル
$ webpack --config myconfig.js   // configを明示的に指定
$ webpack --watch                // ファイルの変更監視 開発中は基本的にこれで
$ webpack user.js out.js         // ファイルを明示的に指定
```

---

## webpack使う rails 5.1 編

- js置き場所 `app/javascript/packs/`
commonjs, es2015 お好きな方をどうぞ

- config `config/webpack/*.js`
環境ごとに用意する

- コンパイル

```
$ ./bin/webpack
$ ./bin/webpack-watcher
```

- js読み込み

`<%= javascript_pack_tag 'calendar' %>`

---

## webpack使う ライブラリ編
- webpackを使うときは、ライブラリ管理はできるだけnpmに寄せる  
→ ライブラリのロードをwebpackがよしなにやってくれる
- bowerとの連携も可

---

## webpack使う ライブラリ編

```webpack.config.js
var vendorPath = __dirname + '/vendor';

module.exports = {
  resolve: {
    modules: ['node_modules', vendorPath],  // ライブラリの場所を指定
    alias: {
      bxslider: 'bxslider/dist/jquery.bxslider.js'  // keyでrequireできる
    }
  }
}
```

(2.x系で変更が入っているので1.x系と混同しないように注意 [参考](https://webpack.js.org/guides/migrating/#resolve-root-resolve-fallback-resolve-modulesdirectories))

---

## webpack使う jQuery plugin編

jQuery pluginは厄介
→ jQuery pluginの作り方は様々なので、それぞれに対応する必要がある

単純なpluginは `$` , `jQuery` が `undefined` で落ちるので、

```
module.exports = {
    plugins: [
        new webpack.ProvidePlugin({
            $: 'jquery',
            jquery: 'jquery',
            jQuery: 'jquery',
            'window.jQuery': 'jquery'
        })
    ]
};
```

これで読める。
jQueryに関しては、もう頼らない風潮が出てきているのこれを機に検討するのもいいかと思います

---

# まとめ
1. webpackはnodejs製のツール
2. commonjs, ES2015でモジュールを書ける
3. entryを頂点に依存関係をよしなにまとめてくれる

---

# (きっと)参考(にする)サイト
- [webpack](http://webpack.github.io/docs/)
- [Rails5.1のwebpack実装、webpacker gem簡単解説 - Qiita](http://qiita.com/itkrt2y/items/69c31e695b1b39915d00)
- [【意訳】Webpackの混乱ポイント - Qiita](http://qiita.com/chuck0523/items/caacbf4137642cb175ec)
- [ReactやwebpackもサポートしたRails 5.1の新機能・変更点 - Qiita](http://qiita.com/ryohashimoto/items/a8ba7bb8d6f340894188)
- [webpack+babel環境でフロントエンドもES6開発 - Qiita](http://qiita.com/HayneRyo/items/74892d3a37ee96a5df60)

---

🌏