webpack+Babel+Three.jsの構成を作成しよう

Three.jsは3D表現の制作に役立つ人気のJSライブラリです。使い方は記事「Three.js入門」で説明したことがあります。Three.jsを例に、npmモジュールをwebpackで取り込む汎用的な方法について学んでいきましょう。

npmモジュールのインストール

必要なモジュールをインストールしましょう。上述のwebpack+Babelの構成と同じです。

npm install -D webpack babel-core babel-loader babel-preset-env 

実行用の「three」モジュールもインストールしましょう。こちらは実行ファイルに含まれるモジュールとして利用したいので、コマンドオプション「-S」をつけています。「-S」を指定するとdependenciesにモジュールが記載されます。npm v5以上のユーザーであれば「-S」を省略してもかまいません。

npm install -S three

これをインストールすると、package.jsonファイルは次の内容になります。scriptsは自前のビルドコマンドを記述しておきます。scriptsdevDependenciesdependencies以外の情報は省略しています。

{
  "scripts": {
    "build": "webpack"
  },
  "dependencies": {
    "three": "^0.86.0"
  },
  "devDependencies": {
    "babel-core": "^6.25.0",
    "babel-loader": "^7.1.1",
    "babel-preset-env": "^1.6.0",
    "webpack": "^3.3.0"
  }
}

webpackの設定ファイル:webpack.config.js

webpackの設定ファイルには次のように記述します。rulesの部分でbabel-loaderを指定し、excludenode_modulesフォルダーを除外します。

module.exports = {
  // メインとなるJavaScriptファイル(エントリーポイント)
  entry: './src/main.js',
  // ファイルの出力設定
  output: {
    //  出力ファイルのディレクトリ名
    path: `${__dirname}/build`,
    // 出力ファイル名
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        // 拡張子 .js の場合
        test: /\.js$/,
        use: [
          {
            // Babel を利用する
            loader: 'babel-loader',
            // Babel のオプションを指定する
            options: {
              presets: [
                // env を指定することで、ES2017 を ES5 に変換。
                // {modules: false}にしないと import 文が Babel によって CommonJS に変換され、
                // webpack の Tree Shaking 機能が使えない
                ['env', {'modules': false}]
              ]
            }
          }
        ],
        // node_modules は除外する
        exclude: /node_modules/,
      }
    ]
  },
  // ソースマップを有効にする
  devtool: 'source-map'
};

以上で設定は完了です。npm run buildコマンドを入力すると、srcフォルダに配置したJSファイルがトランスパイルされ、buildフォルダにbundle.jsファイルが出力されます。

ここまでの手順をサンプルファイルとしてGitHubで公開していますので、参考ください。

サンプルの実行結果は次となります。

webpack+ECMAScript 2017の構成を作成しよう

ECMAScript 2017仕様のJavaScriptをフルに利用するには、さらに設定が必要です。Babelはアロー関数やクラス、letconstといった新しい構文を下位バージョンに変換しますが、PromiseArray.includes()といった機能までは変換しません。後者を利用するにはポリフィルを導入する必要があります。

ここではBabelが提供する「babel-polyfill」の組み込み方を解説します。

npmモジュールのインストール

必要なモジュールをインストールしましょう。今回はポリフィルとして「babel-polyfill」もインストールします。

npm install -D webpack babel-core babel-loader babel-preset-env babel-polyfill

これをインストールすると、package.jsonファイルは次の内容になります。scriptsは自前のビルドコマンドを記述しておきます。scriptsdevDependenciesdependencies以外の情報は省略しています。

{
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "babel-core": "^6.25.0",
    "babel-loader": "^7.1.1",
    "babel-polyfill": "^6.23.0",
    "babel-preset-env": "^1.6.0",
    "webpack": "^3.2.0"
  }
}

webpackの設定ファイル:webpack.config.js

webpackの設定ファイルには次のように記述します。エントリーポイントentrybabel-polyfillの指定を追加するのがポイントです。

module.exports = {
  // メインとなるJavaScriptファイル(エントリーポイント)
  entry: [
    'babel-polyfill', // Polyfillも含める
    './src/main.js',
  ],
  // ファイルの出力設定
  output: {
    // 出力ファイルのディレクトリ名
    path: `${__dirname}/build`,
    // 出力ファイル名
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        // 拡張子 .js の場合
        test: /\.js$/,
        use: [
          {
            // Babel を利用する
            loader: 'babel-loader',
            // Babel のオプションを指定する
            options: {
              presets: [
                // env を指定することで、ES2017 を ES5 に変換。
                // {modules: false}にしないと import 文が Babel によって CommonJS に変換され、
                // webpack の Tree Shaking 機能が使えない
                ['env', {'modules': false}]
              ]
            }
          }
        ],
        // node_modules は除外する
        exclude: /node_modules/,
      }
    ]
  },
  // ソースマップを有効にする
  devtool: 'source-map'
};

以上で設定は完了です。npm run buildコマンドを入力すると、srcフォルダに配置したJSファイルがトランスパイルされ、buildフォルダにbundle.jsファイルが出力されます。

ここまでの手順をサンプルファイルとしてGitHubで公開しています。

サンプルのコードではECMAScript 2015から2017までの様々なAPIを試しています。変換前後の結果を見比べてみると面白いです。例えばECMASrcipt 2016のべき乗演算子(Exponentiation Operator)を使ったコード3 ** 2はBabelによってMath.pow(3, 2)に変換されています(次の図版はクリックで拡大できます)。

最後に

最近のブラウザではECMAScript 2015以上の言語仕様が標準で使えるようになってきました。とはいえ、未だ一定のシェアがあるIE 11のサポート期間が2025年となっているため、ECMAScript 5との付き合いは続きそうです。トランスパイラとしてのBabelはIE 11対応の需要によって数年は使われるでしょう。

モジュールバンドラーの役割は複数のファイルをまとめることです。ES Modulesはやがて各種ブラウザが対応し利用できるようになっていくでしょう(2017年7月現在、標準で使えるのはSafari 10のみ)。ただ、HTTP/1.1環境下では同時リクエスト数の上限があるため、モジュールバンドラーによってまとめる利点が依然として存在します。npmモジュールのバンドルにも役立つことを考えると、モジュールバンドラーの寿命はトランスパイラよりも長いかもしれません。

モジュールバンドラーとしてのwebpackは多機能であるがゆえに設定が複雑です。本記事で紹介した設定は一例に過ぎないので、コピペするだけではなく理解したうえで応用しなけば現場では全く役に立ちません。

前回の記事「最新版で学ぶwebpack 3入門」には、JavaScriptの圧縮やソースマップ、webpack-dev-serverなどについて解説しています。あわせて参照くださいませ。