webpack事始め

#webpackとは

webpackとは各種ファイルを指定のファイルの中に取り込んで、関連の機能を一つのファイルにバンドルする(=統合する)機能を提供しています。

ファイルのフォーマットはJS以外にもStyleSheetや画像データ、jsonもバンドルできます。

#用語の整理
###モジュール
機能ごとに分割されたファイル。
###バンドル(バンドルファイル)
統合されたファイルの事。
・バンドルを生成する = まとめられたファイルを生成する。
・モジュールをバンドルする = モジュールを統合する。

#webpackを導入する事のメリット
ブラウザ上でデータを取得するにはhtmlを取得した後に、再度、JSや画像をサーバーに要求しなければいけません。(＝取得するデータ数が多いほど、画面の描画に時間がかかる事になります)

その為、個々のファイル群を１つのJSファイルにバンドルすると、ファイルのリクエスト数を減らす事が出来る＝ページの読み込み速度の問題も改善し、UXの向上にも良い影響をもたらす事ができます。

webpackはモジュールをかき集めて、`一つのJSファイル`として、出力する事ができます。
モジュールの価値は他のファイルに必要なモジュール機能を取り入れて、利用できる点にあります。

また、ローカルサーバーの起動、JSファイルの圧縮など、包括的な制作環境を提供してくれます。Gulpやnpm scriptsで、設定ファイルが煩雑化しがちだったものが、webpback一式でフロント周りの必要な技術が揃えられるのが大きな利点なのかなと思います。


#導入してみる

Node.jsをインストールしてなければ、以下公式サイトからインストールしましょう。

https://nodejs.org/ja/

まず、webpackを管理するための準備として、`package.json`を生成する。
(package.jsonはインストールしたパッケージを管理するjson形式で記録されたファイル)

```terminal
$npm init -y
```

次にwebpackをインストールする

```terminal
$npm info webpack //最新バージョンを確認してみる
$npm install --save-dev webpack@4.40.2　//現時点での最新バージョンをインストール
```

さらにwebpack-cliをインストールする

```terminal
$npm info webpack-cli //最新バージョンを確認してみる
$npm install --save-dev webpack-cli@3.3.8　//現時点での最新バージョンをインストール
```

`package.json`を確認すると、上記インストールされた事が確認できる。

```json:package.json
{
  "name": "webpackStudy",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/10mi8o/webpack.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/10mi8o/webpack/issues"
  },
  "homepage": "https://github.com/10mi8o/webpack#readme",
  "devDependencies": {
    "webpack": "^4.40.2",
    "webpack-cli": "^3.3.8"
  }
}
```

#簡単なファイル構成でバンドルを試してみる

まず、バンドルしたファイルの出力先になるdistディレクトリを作成。

```terminal
$mkdir dist
```

バンドルするjsファイルを作成

```terminal
$mkdir src
$touch src/index.js
$touch src/utilities.js
```

検証用のhtmlファイルを作成。
この時点では、`main.js`は生成されていません

```terminal
$touch dist/index.html 
```

```html:index.html
<!doctype html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    WebPackを勉強しましょう!!
    <script src="main.js"></script> //バンドルされたjsファイルを読み込む
</body>
</html>
```

ブラウザ上で変更をリアルタイムに確認したい場合に便利な`live-server`をインストールしておきます。

```terminal
$npm install --save-dev live-server //インストール
$npx live-server //サーバー起動 npxコマンドは、ローカルにインストールしたnpmのバイナリを相対パスを指定する事なく使えるようになるので便利です。
```

次にモジュールを作成しましょう。先ほど作成した`utilities.js`には与えた引数の２乗を返させましょう。

```js:utilities.js
// ある数字を引数として与えるとその数字の２乗の数を返す
function double(num) {
    return num**2;
}
```

モジュールの価値は他のファイルにそのモジュールの機能を取り入れて利用できる事にあります。

他のファイルで利用できるようにする為には、exportを実装します。
関数だけでなく、定数も定義できます。

utilities.jsを以下のように書き換えましょう。

```js:utilities.js
// ある数字を引数として与えるとその数字の２乗の数を返す
export function double(num) {
    return num**2;
}

//定数もexportできる
export const NAME = '10mi8o';
```

続いて、src/index.jsで利用できるようにします。
(importする関数名ピンポイントで指定したい場合は{}で囲って指定)
(jsの場合は.jsは省略可能)


```js:index.js
import { NAME, double } from './utilities';

console.log(double(2));
console.log(NAME);
```


`as`を利用して名前をつけたい場合は以下のように書くこともできます。

```js:index.js
import * as utilities from './utilities';

console.log(utilities.double(2));
console.log(utilities.NAME);
```

`as`は名前の衝突を防ぐ際にも使えます。

```js:index.js
import { NAME as NAME_OF_10mi8o } from './utilities';

console.log(NAME_OF_10mi8o);
```

webpackに関する設定を定義できるファイルを作成します。

`pathモジュール`は`npm install`する必要はありません。nodeモジュールとしてデフォルトで入っています。
https://nodejs.org/api/path.html

require('path’)を書くと、ファイルやディレクトリのパスを操作できるようになります。`path.resolve`という関数は、絶対パスに変換してくれます。

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

```js:webpack.config.js
// 出力は絶対pathで指定しなければいけない為、node.jsのpathモジュールを使用する
const path = require('path');
const outputPath = path.resolve(__dirname, 'dist');

module.exports = {
    // バンドルするファイルを指定
    entry: './src/index.js',
    output: {
        // バンドルしてmain.jsとして出力
        filename: 'main.js',
        path: outputPath
    }
}
```

最後にmain.jsを生成します。

```terminal
$npx webpack
```

ブラウザ上でlogが出力されてるかも確認してみましょう。
<img width="260" alt="スクリーンショット 2019-09-22 10.45.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33632/d21af85c-c264-1204-5d24-89366da6dc68.png">
出力されてますね。

以上ざっくりですが、簡単にwebpackに入門しました。