【JavaScript】ビルドとは何か〜webpackを使ってビルドする

この辺が曖昧だったので、書き残しておきます。

- ビルドとは何か
- なぜビルドが必要か
- ビルドでは何を行なっているのか
- ビルドしたらどうなるのか

# Node.jsの特徴
- JavaScriptをサーバーサイドで動かすための実行環境。
- モジュール機能（他ファイルの読み込み）
- ノンブロッキングI/Oで処理を効率化

## 参考記事
[ノンブロッキングI/O (non-blocking I/O)](https://wa3.i-3-i.info/word1617.html)
[ノンブロッキングI/Oと非同期I/Oの違いを理解する](https://blog.takanabe.tokyo/2015/03/26/240/)
[Node.js を5分で大雑把に理解する](https://qiita.com/hshimo/items/1ecb7ed1b567aacbe559)
[Node.jsについて調べてみた](https://qiita.com/kyrieleison/items/f726061803a0e536c3e1)
[JavaScriptが辿った変遷](https://qiita.com/naoki_mochizuki/items/cc6ef57d35ba6a69117f)
[npm とか bower とか一体何なんだよ！Javascript 界隈の文脈を理解しよう](https://qiita.com/megane42/items/2ab6ffd866c3f2fda066)

# ビルドツール
Node.jsスタイルのコードは、そのままの状態ではブラウザで動きません。ソースコードを元にして、実際に動くプログラム（実行可能ファイル）を作ってあげる必要があります。
その作成処理のことを``ビルド``と言います。

ビルドを実行するためには、``ビルドツール``を使用します。

## 概要
以下、[10年遅れたJavaScriptの知識をざっくり10分でアップデートしよう](https://www.webprofessional.jp/anatomy-of-a-modern-javascript-application/)より引用。

>最近のWebアプリケーションは、開発時のコードと実際の製品に使われるコードが異なります。開発者はブラウザーにサポートされていない可能性がある最新バージョンのJavaScriptでコードを書いたり、node_modulesフォルダー内のサードパーティ製パッケージとその依存オブジェクトを多用したり、静的解析ツールや圧縮ツール（Minifier）などを使ったりして開発します。これらをすべて変換、効果的にデプロイして、大半のWebブラウザーが理解できる形にするのがビルドツールです。

## 何を行うのか
以下、[キャッチアップJavaScriptビルド](https://www.slideshare.net/khit9/javascriptjs2016)より引用。

- モジュール管理（依存性解決）
- テンプレート管理
- UT/操作テスト
- 構文チェック
- 圧縮/難読化
- CSSプリプロセッサー
- ES2015コンパイル
- altJSコンパイル

簡単に補足します。

- CSSプリプロセッサーとは、独自の構文でCSSを生成するプログラムのこと。コンパイルにより、純粋なCSSより可読性や保守性が高くなります。
- ES2015（ES6）はJavaScriptの新基準ですが、古いブラウザでは対応していない場合があります。そのため、コンパイルで互換性のあるES5に変換します。（トランスパイル）
- altJSとは、コンパイルによりJavaScriptに変換されるプログラミング言語のこと（代替JavaScript）。従来のJavaScriptより可読性と保守性が高く、コーディングの負担を減らします。

テンプレート管理が何を意味しているのか、よくわからなかったです。
文字列の組み込みのことでしょうか・・・？

## タスクランナーとは
ビルドツールで行われている処理（タスク）を自動化してくれるツールのこと。
grupやGruntが挙げられます。

ネットで調べた限り、ビルドツールとタスクランナーの区分は曖昧でした。
webpackの立ち位置が微妙なところです。

## npmとは
Node.jsのパッケージ管理ツール。
Node.jsと同時にインストールされます。

各種ビルドツールは、npmを使ってインストールすることができます。
今回は、``webpack``を使ってみます。

## 参考記事
[CSS プリプロセッサー](https://developer.mozilla.org/ja/docs/Glossary/CSS_preprocessor)
[CSSプリプロセッサ（CSSメタ言語）のお勉強](https://wb-hp.com/blog/2016/08/01/css-preprocessors.html)
[最近のビルドツールって何なの？](http://m-hiyama.hatenablog.com/entry/20150511/1431306678)
[タスクランナー(Gulp)の入門の入門](http://frontend-takuyan.hateblo.jp/entry/gulp-first)
[【保存版】gulp, webpack, parcel...増え続けるタスクランナーの特徴を理解して最適なものを選択しよう](https://hirata.blog/201712_taskrunner/)
[JavaScriptをやっているとnpm/yarn/gulp/grunt/webpackなど、たくさんのツールがあって混乱したので、それぞれの役割と違いをざっくりとまとめた](https://qiita.com/uchiko/items/9972cfe9341df7ba4a8d)
[プログラミングが便利に！2018年に取り入れたいオススメのタスクランナー5選](https://ferret-plus.com/9383)
[Webpackってどんなもの？](https://qiita.com/kamykn/items/45fb4690ace32216ca25)

# 実演
## 初期化
テスト用ディレクトリを作成し、移動します。

```
$ mkdir js_test
$ cd js_test
```

初期化します。
いくつか質問がありますが、全てEnterで大丈夫です。

```
$ npm init
```

初期化後、ディレクトリ内に``package.json``が生成されます。

## webpackのインストール
webpackをローカルインストールします。

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

ディレクトリ直下に``package-lock.json``と``node_modulesディレクトリ``が生成されます。

webpackのバージョンを確認します。

```
$ npx webpack -v
4.39.1
```

このバージョンでは、``webpack-cli``というライブラリも必要になります。
webpackと同じく、ローカルインストールします。

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

インストール後、package.jsonの``devDependencies``に追記されました。

```package.json
{
  "name": "js_test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.39.1",
    "webpack-cli": "^3.3.6"
  }
}
```

## webpackの設定
ビルドするためには、元のソースコードの場所とビルド後に生成される実行ファイル（bundleファイル）についての情報が必要です。
元のソースコードで一番最初に読み込まれるファイルは、``エントリ-ポイント``と呼ばれます。

ディレクトリ直下に設定ファイル``webpack.config.js``を作成します。

```
$ touch webpack.config.js
```

次のように設定します。

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

module.exports = {
    // エントリーポイントの設定
    entry: './src/my-main.js',
    // ビルド後、'./dist/my-bundle.js'というbundleファイルを生成する
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'my-bundle.js'
    }
};
```

## テストファイルの作成
テストファイルを作成します。
文字列を返すメソッドを記述し、それをモジュールとして別ファイルで読み込んで出力します。

```
$ touch my-index.html
$ mkdir src
$ mkdir dist
```

```my-index.html
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
<script type="text/javascript" src="dist/my-bundle.js" charset="utf-8"></script>
</body>
</html>
```

```
$ cd src
$ touch my-main.js
$ touch my-func.js
```

```my-main.js
var func = require('./my-func');

var res = document.createTextNode(func());
document.body.appendChild(res);
```

```my-func.js
module.exports = function () {
    return 'my-test';
};
```

## エイリアスコマンドの設定
webpackコマンドを簡単に実行するために、エイリアスコマンドを設定します。
package.jsonのscriptに以下を記述します。

```package.json
"build": "webpack --mode development"
```

もしくは

```package.json
"build": "webpack --mode production"
```

modeにより、生成されるbundleファイルの内容が異なります。（動作は同じです。）
modeを指定しない場合は、ビルド実行時に警告が発生します。

この設定により``npm run build`` でビルドを実行する事が可能になりました。

## ビルド実行

エイリアスコマンドを設定したので、早速実行してみます。

```
$ npm run build
```

実行後、bundleファイルである``dist/my-bundle.js``が生成されます。
ブラウザで出力した文字列を確認できれば、ビルド成功です。

## ビルドせずに動作を確認したい

ビルドせずに動作を確認したい場合は、``watchオプション``を利用します。
package.jsonのscriptに以下を記述します。

```package.json
"watch": "webpack --watch"
```

``npm run watch``を実行すると、コードの変更が検知されるようになります。そのため、（画面をリロードすれば）ビルドせずに動作を確認する事ができます。

## デベロッパーツール上で元のファイルを確認したい
デベロッパーツールの``Sourcesタブ``では、ビルド元のファイルを確認する事ができません。

それらを表示させたい場合は、webpack.config.jsに以下を記述します。

```webpack.config.js
devtool: 'inline-source-map'
```

これで、デベロッパーツール上で``my-main.js``と``my-main.js``の内容を確認する事ができます。

## 参考記事
[package.jsonの中身を理解する](https://qiita.com/dondoko-susumu/items/cf252bd6494412ed7847)
[package-lock.jsonについて知りたくても聞けなかったこと](https://qiita.com/yfujii1127/items/7ca887a45e0855917279)
[勉強メモ/npmの使い方(node.js=v0.11.16, npm=2.3.0, 2015-03時点)](https://qiita.com/msakamoto_sf/items/a1ae46979a42d6948ebd)
[npm 5.2.0の新機能！ 「npx」でローカルパッケージを手軽に実行しよう](https://qiita.com/tonkotsuboy_com/items/8227f5993769c3df533d)
[webpack.config.jsがわからない](https://qiita.com/one-kelvin/items/b810aafb6b5ef90789a3)
[npmとwebpack4でビルド - jQueryからの次のステップ](https://qiita.com/civic/items/82c0184bcadc50965f91)
[step by stepで始めるwebpack](https://qiita.com/howdy39/items/48d85c430f90a21075cd)
[新人にドヤ顔で説明できるか、今風フロントエンド開発ハンズオン(Git/Node.js/ES6/webpack4/Babel7)](https://qiita.com/riversun/items/29d5264480dd06c7b9fb)
[React.jsでビルドされる前のコードをブラウザで確認する](https://qiita.com/keng0o/items/fa7a17cf22dbc7d71e74)