webpackでbuildする時にdead codeを削除する方法

## はじめに
この記事では、特定ファイルの特定メソッドだけをbundleしたい場合どうやるか？をやっていきます。ケースとしてはutilityが用意されているけど、その中の1つのメソッドしか使用しないような場合です。

そのような時、不要なメソッドまでbundleすると出力されるファイルのサイズが大きくなりますので、できるだけ小さく保つためにはこういう細かい工夫が必要なんですね。

※npmの代わりにyarnを使っています

## 条件
早速ですが、webpackでこれをやりたい場合条件があります。

* ES2015の記法を使うこと(importやexportなど）
* 使われないコードを削除するminifierを使うこと（UglifyJSPluginなど）

こちらが必須条件となっているようですので、おとなしく条件に則り試していきます。
※記事中で使うコードは

[Getting Started](https://webpack.js.org/guides/getting-started/)
[Tree Shaking](https://webpack.js.org/guides/tree-shaking/)

を使用しています。


## 使用するコード
とりあえず使うコードを貼っていきます。

```package.json
{
  "name": "webpack-demo",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "^3.5.6"
  }
}
```

```webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/index.js',

  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};
```

```dist/index.html
<html>
  <head>
    <title>Getting Started</title>
  </head>
  <body>
    <script src="bundle.js"></script>
  </body>
</html>
```

```src/math.js
export function square(x) {
  return x * x;
}

export function cube(x) {
  return x * x * x;
}
```

```src/index.js
// math.jsの中のcubeメソッドのみをインポート
import { cube } from './math.js';

function component() {
  var element = document.craeteElement('pre');
  element.innerHTML = [
    'Hello webpack!',
    '5 cubed is equal to ' + cube(5) // インポートしたcubeメソッドを使用
  ].join('\n\n');

  return element;
}

document.body.appendChild(component());
```

ポイントは`src/math.js`にsquareとcubeというメソッドがありますが、cubeしか使われないようになっていることです。(=squareはdead code)

ここまで用意でしたら`yarn install`して準備完了です。


## bundle実行
`yarn run build`でbunldeを実行しましょう。うまく実行できたら`dist/bundle.js`が出力されているはずです。`dist/bundle.js`の中身でポイントとなる箇所を見てみましょう。

```dist/bundle.js
"use strict";
/* unused harmony export square */
/* harmony export (immutable) */ __webpack_exports__["a"] = cube;
function square(x) {
  return x * x;
}

function cube(x) {
  return x * x * x;
}
```

このように使用していないコードの上に`unused harmony export square`というコメントがあることがわかります。bundleされたファイルにおいて、「使用しないメソッド」ということが認識されているみたいです。

ただこれで十分かというとそうではありません。結局使われないコードもbundleされたファイルに存在しているためです。

こんな不要なコードは消してしまいましょう！ということで`uglifyjs-webpack-plugin`というプラグインを使って削除していきます。


## uglifyjs-webpack-pluginを使ってdead code削除
まずはプラグインをインストールしましょう。

```bash
$ yarn add --dev uglifyjs-webpack-plugin
```

インストールできたらプラグインを使う設定を加えます。

```webpack.config.js
const path = require('path');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
  entry: "./scr/index.js',
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, 'dist')
  },
  plugins: [
    new UglifyJSPlugin()
  ]
};
```

これでもう一度`yarn run build`します。
出力された`dist/bundle.js`を見てみると圧縮されていることがわかります。

`cube`メソッドについては`function r(e){return e*e*e}n.a=r`といったコードに圧縮されていましたが、`square`メソッドはgrepに引っかかりませんでした。
うまくdead codeである`square`メソッドのみ削除されてそうですのでこれで完成です。


## おわりに
特定ファイルの特定メソッドだけbundleする(=dead code)を削除ということをやってきましたが、webpack自身が持つ機能とプラグインを入れてコードを数行追加するだけで不要コードを削除することができました。

「方法」なんてお題で書きましたが、minifyすると勝手に消えるので言えないかもしれませんが。。

簡単かつ出力されるファイルサイズが小さくなるという実用性まであるので使わない手はないと思いました。