ECMAScript 2015(略:ES2015)以上の言語仕様でJavaScriptを書くことが、昨今のウェブのフロントエンドエンジニアの基本テクニックです。しかし、ECMAScript 2015以上の仕様のJavaScriptで記述すると、Internet Explorer 11など古いブラウザでは動作しないこともあります。そこでBabelなどのトランスパイラと呼ばれるツールを使って、ES2015・ES2016・ES2017・ES2018の仕様で記述したJavaScriptファイルを互換性のあるECMAScript 5に変換します

トランスパイラとして一番有名なのが「Babel」というツールです。ただ、BabelにはECMAScript Modules(importexport文のこと。以下、ES Modulesと記載)のJSファイルをまとめる機能が提供されていません。そのため、ES ModulesのJSファイルをまとめるモジュールバンドラー(例:webpackRollup等)をBabelと合わせて使うのが一般的です。

このページではトランスパイラのBabelとモジュールバンドラーのwebpackを連携する方法を網羅的に解説します。使い方として次の5種類を解説します。

※webpackの基本的な使い方は前回の記事「最新版で学ぶwebpack 4入門」を参照ください。

webpack+Babelの構成を作成しよう

webpackとBabelを最小構成で作っていきましょう。

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

webpackとBabelなど必要なモジュールをインストールしましょう。Babelは複数のモジュールを組み合わせて使う形式上、「babel-core」「babel-loader」「babel-preset-env」と3種類を最低限インストールする必要があります。もちろん「webpack」と「webpack-cli」も指定します。

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

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

▼package.jsonファイル

{
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.1",
    "webpack": "^4.0.0",
    "webpack-cli": "^2.0.9"
  },
  "private": true
}

webpackの設定ファイル

webpackの設定ファイルには次のように記述します。rulesの部分でbabel-loaderを指定しているのがポイントです。Babelはプリセットの設定に応じてECMAScriptのバージョンを下位にトランスパイルします。

presetsプロパティーにenvの指定することで、最新仕様(執筆時点ではECMAScript 2017)の構文をECMAScript 5に変換できます。Loaderのオプションの指定が煩雑ですが、presetsプロパティーにenvの指定を忘れないように注意ください。

▼webpack.config.jsファイル

module.exports = {
  // モード値を production に設定すると最適化された状態で、
  // development に設定するとソースマップ有効でJSファイルが出力される
  mode: 'development',

  // メインとなるJavaScriptファイル(エントリーポイント)
  entry: './src/app.js',

  module: {
    rules: [
      {
        // 拡張子 .js の場合
        test: /\.js$/,
        use: [
          {
            // Babel を利用する
            loader: 'babel-loader',
            // Babel のオプションを指定する
            options: {
              presets: [
                // env を指定することで、ES2018 を ES5 に変換。
                // {modules: false}にしないと import 文が Babel によって CommonJS に変換され、
                // webpack の Tree Shaking 機能が使えない
                ['env', {'modules': false}]
              ]
            }
          }
        ]
      }
    ]
  }
};

※プリセット「babel-preset-env」は「ECMAScript 5/6/7 compatibility tables」に基づきターゲットブラウザを指定できたりと様々な機能が提供されています。例えば、ターゲットブラウザがSafari 10だけでよければ、ES5まで落として変換する必要はなく、ES2015(ES6)をターゲットにすれば良いということになります。興味がある方はドキュメントを参考ください。

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

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

webpack+Babel+jQueryの構成を作成しよう

jQueryは言わずと知れた汎用的なJSライブラリです。webpackやBabelに興味のあるフロントエンドエンジニアであれば、「いまどき、jQueryを使いたくない」という方もいるかもしれません。しかし、現場では使わざるを得ない状況の方も多いはずです。ここでは、npmモジュールのjQueryをwebpackで取り込む方法について紹介します。

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

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

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

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

npm install -S jquery

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

▼package.jsonファイル

{
  "scripts": {
    "build": "webpack"
  },
  "dependencies": {
    "jquery": "^3.3.1"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.3",
    "babel-preset-env": "^1.6.1",
    "webpack": "^4.0.0",
    "webpack-cli": "^2.0.9"
  },
  "private": true
}

webpackの設定ファイル

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

▼webpack.config.jsファイル

module.exports = {
  // モード値を production に設定すると最適化された状態で、
  // development に設定するとソースマップ有効でJSファイルが出力される
  mode: 'production',

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

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

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

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

webpack+Babel+Reactの構成を作成しよう

Reactウェブアプリケーションの開発に役立つ人気のJSライブラリです。2017年9月現在の最新版であるReact 16を例に、npmモジュールをwebpackで取り込む方法について学んでいきましょう。

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

必要なモジュールをインストールしましょう。上述のwebpack+Babelの構成に加えて、トランスパイル用に「babel-preset-react」が必要となります。

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

実行用の「react」と「react-dom」もインストールしましょう。こちらは実行ファイルに含まれるモジュールとして利用したいので、コマンドオプション「-S」を指定します。

npm install -S react react-dom

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

▼package.jsonファイル

{
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.3",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "webpack": "^4.0.0",
    "webpack-cli": "^2.0.9"
  },
  "dependencies": {
    "react": "^16.2.0",
    "react-dom": "^16.2.0"
  },
  "private": true
}

webpackの設定ファイル

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

オプションのプリセットにはenvの指定だけでなく、reactを記述するのがポイントです。これによって、JSXと呼ばれるReact特有のシンタックス(JavaScriptの中にDOM要素を記述する方法)を解釈できるようになります

▼webpack.config.jsファイル

module.exports = {
  // モード値を production に設定すると最適化された状態で、
  // development に設定するとソースマップ有効でJSファイルが出力される
  mode: 'development',

  // メインとなるJavaScriptファイル(エントリーポイント)
  entry: './src/main.js',
  // ファイルの出力設定
  output: {
    //  出力ファイルのディレクトリ名
    path: `${__dirname}/dist`,
    // 出力ファイル名
    filename: 'main.js'
  },
  module: {
    rules: [
      {
        // 拡張子 .js の場合
        test: /\.js$/,
        use: [
          {
            // Babel を利用する
            loader: 'babel-loader',
            // Babel のオプションを指定する
            options: {
              presets: [
                // env を指定することで、ES2018 を ES5 に変換。
                // {modules: false}にしないと import 文が Babel によって CommonJS に変換され、
                // webpack の Tree Shaking 機能が使えない
                ['env', {'modules': false}],
                // React の JSX を解釈
                'react'
              ]
            }
          }
        ]
      }
    ]
  }
};

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

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

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

Reactの初期設定を簡単にするツール「create-react-app」からReactを始める人も多いと思います。create-react-appのビルドでは、内部的にwebpackとBabelが使われています。

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

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

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

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

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

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

npm install -S three

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

▼package.jsonファイル

{
  "scripts": {
    "build": "webpack"
  },
  "dependencies": {
    "three": "^0.90.0"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.3",
    "babel-preset-env": "^1.6.1",
    "webpack": "^4.0.0",
    "webpack-cli": "^2.0.9"
  },
  "private": true
}

webpackの設定ファイル

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

▼webpack.config.jsファイル

module.exports = {
  // モード値を production に設定すると最適化された状態で、
  // development に設定するとソースマップ有効でJSファイルが出力される
  mode: 'development',

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

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

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

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

webpack+Babel+Vue.jsの最小構成

Vue.js公式サイト

Vue.jsはReactやAngularと並んで注目を集めるJSライブラリです。vue-cliを使うのが最も簡単ですが、vue-cliはwebpack 3をベースにしているため、少し環境設定が古めです。この解説ではwebpack4とBabelとVue.jsを最小構成で作っていきます。

Vue.jsは様々な記述方法が可能なので、ここで紹介する構成は一例に過ぎません。アンケートで調べたところ、Vue.jsの開発では単一ファイルコンポーネントが最も使われているようなので、その構成で解説します。

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

webpackとBabelなど必要なモジュールをインストールしましょう。.vueファイルを読み込むために、vue-loaderやvue-template-compilerを入れておきます(必須)。.vueファイルではCSSも扱うので、css-loaderやfile-loaderも必要となります。

npm i -D babel-core babel-loader babel-preset-env css-loader file-loader vue-loader vue-template-compiler webpack webpack-cli 

実行用の「vue」モジュールもインストールしましょう。

npm i -S vue

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

package.jsonファイル

{
  "scripts": {
    "build": "webpack",
    "watch": "webpack --watch"
  },
  "dependencies": {
    "vue": "^2.5.16"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.6.1",
    "css-loader": "^0.28.11",
    "file-loader": "^1.1.11",
    "vue-loader": "^14.2.2",
    "vue-template-compiler": "^2.5.16",
    "webpack": "^4.4.1",
    "webpack-cli": "^2.0.13"
  },
  "private": true
}

webpackの設定ファイル

webpackの設定ファイルには次のように記述します。resolveの部分でaliasを指定することや、プラグインVueLoaderPluginを指定することも重要です。拡張子vueやcssに対してもルールを設定し、extensionsの箇所にはvueファイルを登録しておきます。要は設定するところが多いので大変です。

webpack.config.jsファイル

const { VueLoaderPlugin } = require('vue-loader');

module.exports = {
  // モード値を production に設定すると最適化された状態で、
  // development に設定するとソースマップ有効でJSファイルが出力される
  mode: 'production',

  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ],
      },

      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        // Babel のオプションを指定する
        options: {
          presets: [
            // env を指定することで、ES2018 を ES5 に変換。
            // {modules: false}にしないと import 文が Babel によって CommonJS に変換され、
            // webpack の Tree Shaking 機能が使えない
            ['env', {'modules': false}]
          ]
        }
      },
    ]
  },
  // import 文で .ts ファイルを解決するため
  resolve: {
    // Webpackで利用するときの設定
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    },
    extensions: ['*', '.js', '.vue', '.json']
  },
  plugins: [
    // Vueを読み込めるようにするため
    new VueLoaderPlugin(),
  ],
};

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

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

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

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

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

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

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

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

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

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

▼package.jsonファイル

{
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.3",
    "babel-polyfill": "^6.26.0",
    "babel-preset-env": "^1.6.1",
    "webpack": "^4.0.0",
    "webpack-cli": "^2.0.9"
  },
  "private": true
}

webpackの設定ファイル

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

▼webpack.config.jsファイル

module.exports = {
  // モード値を production に設定すると最適化された状態で、
  // development に設定するとソースマップ有効でJSファイルが出力される
  mode: 'production',

  // メインとなるJavaScriptファイル(エントリーポイント)
  entry: [
    'babel-polyfill', // Polyfillも含める
    './src/app.js',
  ],
  // ファイルの出力設定
  output: {
    // 出力ファイルのディレクトリ名
    path: `${__dirname}/dist`,
    // 出力ファイル名
    filename: 'main.js'
  },

  module: {
    rules: [
      {
        // 拡張子 .js の場合
        test: /\.js$/,
        use: [
          {
            // Babel を利用する
            loader: 'babel-loader',
            // Babel のオプションを指定する
            options: {
              presets: [
                // env を指定することで、ES2018 を ES5 に変換。
                // {modules: false}にしないと import 文が Babel によって CommonJS に変換され、
                // webpack の Tree Shaking 機能が使えない
                ['env', {'modules': false}]
              ]
            }
          }
        ]
      }
    ]
  }
};

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

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

サンプルのコードではECMAScript 2015(ES6)からECMAScript 2018(ES9)までの様々なAPIを試しています。変換前後の結果を見比べてみると面白いです。例えば、ES2016のべき乗演算子(Exponentiation Operator)を使ったコード3 ** 2はBabelによってMath.pow(3, 2)に変換されています(次の図版はクリックで拡大できます)。ES2017のpadEnd()メソッドや、ES2018の非同期イテレーションも動作します。

最後に

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

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

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

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

連載一覧