webpackのチュートリアル記事の紹介とハマりポイント、その解決法

webpackについてきちんと理解しようと思っていろいろと調べていたところ次の記事がとてもよかったので紹介します。ただ、少しハマったポイントがあったのでその内容を備忘とともにシェアします。

# 記事へのリンク
- [Webpack your bags](http://js.studio-kingdom.com/webpack/getting_started/webpack_your_bags)

# ハマった現象① - webpackがinstallできない
これは自分の単純(?)なミスです。
作業を開始するときに作業ディレクトリは「(home)\work\study\webpack」のようにしていました。この状態で「npm init -y」すると、自動で作成されるpackage.jsonに記載される自分のモジュール名(name)がディレクトリ名「webpack」になります。

```package.json(抜粋)
{
     "name": "webpack",
         ...
```

この状態でwebpackをインストールしようとすると「モジュール名が被っているからインストールできないよ」のようなことでnpmさんに怒られました。
対処法としてはディレクトリを切りなおす方法もあるのですが、面倒くさいですし、「\study\webpack」にしておきたかったのでモジュール名を「webpack-study」に変更して対応しました。

```package.json(抜粋)
{
     "name": "webpack-study",
         ...
```

一見、つまらない問題ですが普段は躓かない「npm install」でのっけからこけたので少し焦りました。そして当然ググっても回答はありません。冷静にエラーメッセージを読めばすぐに解決できました。

# ハマった現状② - JQueryがbundleされない
- 「最初のローダーの設定」のセクション
   (ES2015でJSを記述するためにbabel-loaderを導入するところ

- 現象
  正常にwebpackのプロセス自体は正常に終了。
  何も考えずにページを開くとjqueryのあたりでエラー
 「--display-modules」を付けてwebpackするとJQueryがbundleされないことが判明。

## 原因
babel-loaderの適用先のディレクトリを次のようにincludeを指定しています(抜粋)。

```webpack.config.js
            {
                test:   /\.js/,
                loader: 'babel',
                include: __dirname + '/src',
            }
```

このincludeの指定がうまく効いていない。
その結果、「require」→「import」に変更したけれども、babel-loaderが働かずにJQueryが必要なモジュールとして認識できていなかったっぽい。

試しに「module.export」の上あたりに次のようなコードを埋め込んで見ました。

```javascript
console.log(`__dirname = [${__dirname}]`);
console.log(`__dirname + /src = [${__dirname}/src]`);
// --- 出力 ---
// __dirname = [C:\Users\PC User\work\study\webpack]
// __dirname + /src = [C:\Users\PC User\work\study\webpack/src]
```

上記の結果を見るとパスのデリミタが「\」と「/」で混在していることが問題のようです。
- 僕の作業マシンはWindowsなのでデリミタが「/」のOSで開発されている場合は問題は発生しないと思います。
- 「C:\Users\PC User\work\study\webpack」がプロジェクトの作業ディレクトリになります。
- ES2015のテンプレートリテラルを使用しています。webpack.config.jsをES2015で記述するために下記の「ちなみに - webpack.config.jsをES2015で書く」を参照してください。

## 対応方法１
そもそも、なぜincludeを指定するか？
紹介した記事にも記載があるのですが、仮にincludeをしない場合、babel-loaderは作業ディレクトリ配下のすべてのjsを参照してしまうので、node_modules配下にあるJQueryの本体とかも見に行ってエラーになってしまうようです。これを回避するために、babel-loaderの対象ディレクトリを指定する必要があります。
「node_modules」をbabel-loaderの対象にしなければ良いわけなので「include」とは逆の、除外指定「exclude」を使用すると問題が解決します。

```webpack.config.js
            {
                test:   /\.js/,
                loader: 'babel',
//                include: __dirname + '/src',
                exclude: /node_modules/,
            }
```
参考：[webpackでbabel際はnode_modulesをexcludeし忘れるべからず](http://qiita.com/haribote/items/73ede4fcdf9c942f1c4f)

## 対処方法２
たとえば、babel-loaderを効かせたいJSと効かせたくないJSが混在している場合、対処方法１のようなブラックリスト方式では対応がしにくくなるかなと思いました。たとえば、既存プロジェクトのJSを少しずつモダンな環境へ移行していく場合など。おそらく「__dirname + "/src"」を「__dirname + "\src」にするのが簡単なのですが、それだとmacなどで開発するメンバーがいた場合に困ってしまいます。

そこで使用するのが「path」モジュールです。
「path」モジュールはNode.jsのプリセットモジュールです。
https://nodejs.org/api/path.html#path_path

※ちなみに「__dirname」もNode.jsのグローバルオブジェクトです
https://nodejs.org/docs/latest/api/globals.html#globals_dirname

これで開発環境でのpath関連の違いが吸収できます。

```webpack.config.js
var path = require('path'); // これを追加しないと使えません
:
            {
                test:   /\.js/,
                loader: 'babel',
                 path.join(__dirname, "/src")
            }
```

確認のログ出力。

```javascript
console.log(`path.join(__dirname, "/src") = [${path.join(__dirname, "/src")}]`);
// --- 出力 ---
// path.join(__dirname, "/src") = [C:\Users\PC User\work\study\webpack\src]
```

チームで開発する場合やOSSにするものは常にpathモジュールを使用するべきだと思いました。

# ちなみに - webpack.config.jsをES2015で書く
webpack.config.jsをリネームしてwebpack.config.babel.jsにするとwebpack.config.jsをES2015で記述できます。そのため上述のwebpack.configは次のように書き換えることができます。

```javascript
//var path = require('path');　↓が書き換え版
import path from 'path';
:
// module.exports = { ↓が書き換え版
export default {
```

途中で出てきたログ出力にテンプレートリテラルが登場させてしまったのですが、書き換えたくなかったし、参考になればと思ってこんな感じで記載しました。わかりにくかったらすみません。

# ちなみに② - JQueryのインストールの仕方
チュートリアルではJQueryとwebpackのインストールするとき、次のようにオプションに違いがあります。

```
$ npm install jquery --save
$ npm install webpack --save-dev
```

結論からいうとどちらも「--save-dev」でOKのようです。
そのため次のコマンドでOKです。

```
$ npm install jquery webpack --save-dev
```

「--save-dev」は開発時に必要なモジュール(ビルドやLint関連など)をインストールときに使用し、「--save」は実行時に必要なライブラリをインストールときに使用するようです。この実行時というのはNode.jsで動くJSの実行時のことで、今回のようなケースではJQueryはwebpackが利用するだけですからビルド時に参照できれば良いということになります。JQueryはフロントエンドからすると実行時にあればよいライブラリなので少し紛らわしいですね。bundle.jsにJQueryもJQueryを参照するJSもすべて１つになるので実行時には必要ないという「とらえ方」もできます。

また、実際は「--save」でも「--save-dev」でもどちらでもきちんとbundleされるようなので、今のところはどっちでもいいような気がしています。どちらにある「べき」かは今のところ、自分の中では判断がつかないので、ご助言を頂けると助かります。

この辺りについて言及する必要がある場合にはNode.jsをより詳しく調べたほうが良いと考えてますので、これに関して調べて何か気づきや思い付きがあったら、また別の記事を書こうと思います。