30歳からのプログラミング

30歳無職から独学でプログラミングを開始した人間の記録。

webpack2の初歩

今まで、複数のファイルのバンドルにはbrowserifyを使っていた。
特に不満はなかったのだが、webpackに乗り換えていくことにした。

ネット上の記事を見てもwebpackを使っているケースは多いし、webpack-dev-serverという開発用サーバーも簡単に立てられるらしい。

今年の1月にv2が正式リリースされたので、それに準拠した内容を学んでいく予定。
この記事では、2.4.1を使っている。

初期設定

まずはwebpackのインストールから。

$ npm install -D webpack

package.jsonを編集して、npm scriptでwebpackを実行できるようにする。

{
  ...
  "scripts": {
    "start": "webpack -p --watch",
    "build": "webpack -p"
  },
  ...
}

--watchオプションをつけておくと、ファイルの変更を検知して都度、自動的にリビルドしてくれる。

最後に、webpack.config.jsという設定ファイルをルートディレクトリに作成する。

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

const config = {
  context: path.resolve(__dirname, 'src'),
  entry: './main.js',
  output: {
    path: path.resolve(__dirname, 'public'),
    filename: 'bundle.js',
  },
};

module.exports = config;

このように設定すると、src/main.jsをエントリポイントとして、バンドルしたファイルをpublic/bundle.jsとして出力するようになる。

ファイルのバンドル

早速、使ってみる。

まず、バンドルしたファイルを読み込むhtmlファイルを作っておく。

<!-- public/index.html -->
<!DOCTYPE html>
<html>
<head>
  <title>webpack</title>
</head>
<body>
  <div id="app"></div>
  <script src="bundle.js"></script>
</body>
</html>

次に、エントリポイントとなるsrc/main.js

// src/main.js
const elem = require('./parts');

const app = document.querySelector('#app');
app.innerHTML = elem;

最後に、src/main.jsが読み込んでいるsrc/parts.jsを作成する。

// src/parts.js
module.exports = 'hogehoge';

この状態で$ npm run buildを実行してpublic/index.htmlを開くと、画面にhogehogeと表示されており、バンドルが上手くいったことを確認できる。

Babelの導入

ただファイルをバンドルするだけならこれで十分なのだが、現実的には、Babelによるトランスパイルも行うことが多いと思う。
ファイルの読み込みにしても、requireではなくimport/exportを使うことが主流になっている。

browserifyの場合は、babelifyを使うことでトランスパイルを同時に行っていた。
もちろんwebpackでも同じことが出来る。

ただその前に、ちょっと気になることがあったので記録しておく。

import/exportはトランスパイルしないと使えないと理解しているが、webpack2では、トランスパイルなしでも使えたのだ。

先程のsrc/main.jssrc/parts.jsを、以下のように書き換えた。

// src/main.js
import elem from './parts';

const app = document.querySelector('#app');
app.innerHTML = elem;
// src/parts.js
export default 'test test';

この状態で$ npm run buildしたところ、問題なくビルドできた。
そのため、import/exportを使いたいだけなら、Babelを導入しなくても問題ない、ということになる。

ただ、やはりきちんとBabelを入れておいたほうがいいだろう。
後述するReactのビルドなどでは結局必要になるし、敢えて入れない理由は何もないと思う。

ということでまずは、ES2015のトランスパイルを行えるようにしていく。

まず、必要なパッケージをインストールする。

$ npm i -D babel-core babel-loader babel-preset-es2015

次に、Babelの設定ファイルである.babelrcを作成。

{
  "presets": ["es2015"]
}

最後に、webpack.config.jsの内容を変更する。

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

const config = {
  context: path.resolve(__dirname, 'src'),
  entry: './main.js',
  output: {
    path: path.resolve(__dirname, 'public'),
    filename: 'bundle.js',
  },
  module: {
    rules: [{
      test: /\.js$/,
      include: path.resolve(__dirname, 'src'),
      use: [{
        loader: 'babel-loader',
        options: {
          presets: [
            'es2015',
          ],
        },
      }],
    }],
  },
};

module.exports = config;

この状態でwebpackを実行すると、バンドルとトランスパイルを同時に行える。

Reactのビルド

Babelを使えるので、Reactのビルドも当然行える。

$ npm i -D babel-preset-reactでプリセットをインストールし、.babelrcwebpack.config.jsのプリセットの設定を書き換えるだけである。

["es2015"]
↓
["es2015", "react"]

これでビルドできるようになったので、実際にReactのコードを書いてみる。

$ npm i -S react react-dom
// src/main.js
import React from 'react';
import ReactDOM from 'react-dom';

import Hello from './parts';

ReactDOM.render(<Hello />, document.querySelector('#app'));
// src/parts.js
import React from 'react';

export default function () {
  return (
    <div>
      Hello, React!
    </div>
  );
}

そして$ npm run build$ npm startでwebpackを使うと、ビルドされる。
public/index.htmlを開くと、Hello, React!と表示されているはずである。

参考資料