【javascript】Browserifyによるモジュールのバンドリング

こちらの記事は以下の書籍を参考に執筆しました

[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


javascriptに追加された機能の中で大きな位置を占めているのは**モジュール**である。
モジュールに関して**トランスパイル**だけでは不十分である。
>#####トランスパイル
プログラミング言語のソースコードを別のプログラミング言語のソースコードに変換する。

モジュールの最大の特徴はコードを複数のファイルに分割できる。
つまり、それらを1つのファイルに**バンドル**する必要がある。

#モジュールとは
プログラミング言語ではモジュール化されたコードがサポートされており、
Rubyでは`gem`、Pythonでは`egg`、Javaでは`パッケージ`と呼ばれている。

ES2015でモジュールが導入されるまでこの概念をサポートしなかったため、
javascriptでモジュールを使用するソリューションがコミュニティで作成され、
最も普遍的なものとなったのが**Node.js**である。

#Node.jsのモジュールの仕組み
Node.jsでのモジュールのインポートとエクスポートの方法は独特である。
Node.jsのモジュールではプログラムを複数のモジュールに分割できる。
それらのモジュールにはプログラムがカプセル化され、必要なAPIだけが公開される。

モジュールが公開するには明示的にエクスポートされたものだけなので何もラッピングする必要がない。
加えてモジュールが利用できるのはインポートされた場所だけなのでグローバル名前空間には影響しない。
#Browserify 
Browserifyは、開発中はNode.jsと同じ方法でモジュールを定義し、
開発が終わるとそれらのモジュールを1つのファイルにバンドルできるようにするツールである。

Browserifyにはトランスフォームの概念があり、Babelの**babelify**というトランスフォームを利用すれば
Browserifyと連携させる事ができ、ES2015のモジュールを利用できるようになる。

#BrowserifyとBabelのセットアップ
##Browserifyのインストール
以下のようにBrowserifyをグローバルインストールを実行。
```
$ npm install browserify --global
```
##babelifyを使ってプロジェクトをセットアップ
プロジェクトフォルダを作成し、以下のようにファイルを作成する。

```bash
babelify_example
|--dist
|--src
|   |--app.js
|   |--index.js
└--.babelrc
```

その後、プロジェクトのルートフォルダへ移動して
以下のコマンドを入力して、NPMプロジェクトとして初期化、
Babelのプリセット/プラグインとbabelifyをインストール。

```bash
$ npm init -y
$ npm install @babel/core --save-dev
$ npm install @babel/preset-env --save-dev
$ npm install @babel/plugin-proposal-decorators --save-dev
$ npm install babelify --save-dev
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


次にBabelの構成を`.babelrc`ファイルに追加する。

```json:babelrc
{
    "presets": ["@babel/preset-env"],
    "plugins": [
        ["@babel/plugin-proposal-decorators",{"legacy": true}]
    ],
    "sourceMaps":"inline"
}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



`Browserify`と`babelify`を使用する準備が終わったところで簡単なモジュールを記載してテストします。
`app.js`と`index.js`に以下のコードを入力。

```javascript:app.js
const MyModule={
  check();{
    console.log('Yahoo! module are working!');
  }
}
expect default MyModule;
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



```javascript:index.js
import MyModule from './app';

MyModule.check();
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



その後、のシェルコマンドでバンドルします。

```bash
$ browserify src/index.js --transform babelify --outfile dist/bunndle.js --debug
```
すると`dist`フォルダに`bundle.js`が作成されているのが確認できる。
先のコマンドについて説明すると

|引数|説明|
|:--|:--|
|src/index.js|アプリケーションの**エントリポイント**である。|
|--transform babelify|コードをバインドする前にbabelifyを使ってコードをトランスパイルする|
|--outfile dist/bunndle.js|出力ファイル先の指定|
|--debug|ソースマップを含める|

>###エントリポイント
他のモジュールをインポートするルートJavaScriptファイルのこと。
今回は`index.js`に`import`で他のモジュールをインポートしているため、src/index.jsを指定する。

browserifyに指定できる引数リストの確認は次のコマンドを実行する。

```
$ browserify help
```
###nodeコマンドで実行する
トランスパイルされた`bundle.js`をNode.jsで実行するには以下のコマンドを入力します。

```
$ node dist/bundle.js
```

すると以下の様に出力される

```
Yahoo! module are working!
```

###ブラウザで実行する
bundle.jsをブラウザで実行してみるために
ルートフォルダで以下のコードを作成する。

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Babelify example</title>
  </head>
  <body>
    <h1>Hello,ES6</h1>
    <script src="dist/bundle.js"></script>
  </body>
</html>
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



ブラウザで表示してみると`Hello,ES6`と表示され
console画面には`Yahoo! module are working!`と表示される。


###ここまでのまとめ
1. `check`メソッドを使って`app.js`のメッセージを記録するモジュールを作成
2. このモジュールを`index.js`でインポートし、`check`メソッドを呼び出す
3. Browserifyとbabelrcを利用してjavascriptのトランスファイルとバンドルを実効
4. バンドルされたコードをHTMLページにインクルードして、うまくいくことを確認


ソースコードを変更したらその都度再コンパイル(browserifyコマンドを実行)することを忘れないように。
browserifyコマンドをpacage.jsonにNPMスクリプトといて追加すれば、簡単にコンパイルできるようになる。

#まとめ
ES2015のモジュールをバンドルするためにBrowserifyをセットアップする方法について説明した。