本文書は”入門者/初心者にもわかるwebpack5の基礎(Loader編)”の続きです。ここまでの公開済みのwebpackに関する文書で複数のJavaScriptファイルを1つのファイルに束ねる方法とCSSのスタイルシートをJavaScriptファイルに組み込みLoaderの説明を行ってきました。今回の内容はwebpackでBabel(バベル)を使用した場合の設定手順の説明と動作確認を行っています。

Babelについて

JavaScriptに限らず便利なツールはさらに便利で使いやすくするため日々進歩/進化を繰り返しています。しかし一部でその進歩に追いついていない場面を頻繁に目にします。あなたの会社では今もWindows 7/XP/Vistaを使用しているかもしれません。Windows 7/XP/Vistaのような古いOSで動かせるブラウザには制限があり、古いブラウザではJavaScriptの新しい機能や構文を利用することができません。また、最近のブラウザの中でもJavaScriptの新しい構文に対応していないものもあります。ブラウザが対応していないものはブラウザがその構文を理解することができないためうまく処理を行うことができません。

そこで登場したのがBabelです。新しい構文を使って記述したJavaScriptのコードを古いブラウザでも理解できるようにコード変換を行なってくれるツールです。Babelを利用することで開発者は新旧のブラウザを意識することなく新しい構文を使って効率よくプログラムを作成することができます。

Babelが行う変換のことはtranspiler(トランスパイラ)とよばれています。新しい構文はどんなものかわからない場合はアロー関数を想像してください。以前はアロー関数を利用することができませんでしたがECMAScript 2015から利用することができます。
fukidashi

CMAScirpt 2015(「ES6」)が登場する前の手法でコーディングしている場合、また古いブラウザではプログラムが動かなくても問題ないという場合にはBabelを利用する必要はありません。

Babelと混同してしまう可能性が高いものにPolyfillというものがあります。Bableの場合は新しい構文(記述方法)を変換してくれますがPolyfillでは古いブラウザでは対応していない関数やライブラリを代替してくれるコードを提供してくれます。IE11ではPromiseをサポートしていないためPolyfillが必要となります。必要となるのはBabelではありません。

WebpackでのBabelの使い方

Bableをwebpackで利用するためにはインストールが必要になります。Babelの公式サイトにアクセスして上部のSetupのリンクをクリックして、webpackでのインストール方法の確認を行います。

babelトップページ
babelトップページ

Bableが使用できるビルドツールやフレームワークがたくさんあることを確認できます。Build systemsカテゴリーのwebpackをクリックしてください。

Bableが使用できる環境
Bableが使用できる環境

インストール手順から設定方法までwebpackの動作に必要なことはすべて記述されているのでこの流れ通りに設定を行います。

webpackでのbabelのインストール方法
webpackでのbabelのインストール方法

前準備

動作確認を行うためにはnpmのインストールが事前に行われている必要があります。またnpmでwebpack, webpack-cli, css-loader, style-loader, scss-loader, node-scssをインストールし、package.jsonのscriptsに以下のwebpackコマンドの設定が完了している環境で動作確認を行っています。


  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack --mode development",
    "build": "webpack --mode production",
    "watch": "webpack --mode development --watch"
  },

ここまでの環境を構築するためのパッケージのインストール方法については下記の文書に記載しています。

Bableのインストール

公式ドキュメントの手順に沿ってbabel-loaderとbabel/coreのインストールを行います。bable/coreの前には”@”がつきます。


 % npm install --save-dev babel-loader @babel/core

added 44 packages, and audited 365 packages in 3s

33 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

webpack.config.jsへのbabelの追加

webpack.config.jsのmoduleにbabelのルールを追加します。追加する値も公式ドキュメント上の手順を参考に設定します。


const path = require('path')

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }, 
  module:{
    rules:[
        {
            test:/\.scss$/,
            use:['style-loader','css-loader','sass-loader']
        },
        { 
            test: /\.js$/, 
            exclude: /node_modules/, 
            loader: "babel-loader" 
        }        
   ]
  }
}

preset(プリセット)の設定

webpack.config.jsにbable-loaderを設定しただけではまだ変換を行うことはできません。変換が必要な新しい構文にはbabelのPlugin(プラグイン)が必要になります。

元々のJavaScriptではClassは使用することができませんでしたが新しい機能の一つとして現在のJavaScriptではClassも使用することができます。Classを変換する場合は、Classes(@babel/plugin-transform-classes)というプラグインがありそのプラグインを使って変換を行う必要があります。

個別のプラグインをまとめたものにpreset(プリセット)がありpresetのインストールを行うことでプラグインを個別にインストールすることなく変換を行うことができます。ここでもClasses(@babel/plugin-transform-classes)という個別のプラグインではなくプリセットをインストールします。


mac $ npm install @babel/preset-env --save-dev

preset-envはすべてのES2015-ES2020のコードをES5のコードに変換してくれます。

Plugin(プラグイン)一覧はBabel公式ドキュメントから確認することができます。ES2015のarrow-functionに対応するプラグインも下記の画像から確認することができます。

babel plugin(プラグイン)一覧
babel plugin(プラグイン)一覧

Pluginのリスト情報からClassのPluginである@babel/plugin-transform-classesを確認するとインストールを行った@bable/preset-envに含まれていることがわかります。preset-envを利用することでClassを使ったコードを記述するとBabelによってClassに対応するコードに変換されます。

classに関するプラグイン
classに関するプラグイン

presetのインストールが完了したら、こちらも公式ドキュメントに記載されている通り、プロジェクトフォルダの直下にbabel.config.jsonファイルを作成して、以下を記述します。


mac $ touch babel.config.jso

{
  "presets": ["@babel/preset-env"]
}

作成時のディレクトリ構成は下記のようになっています。

babelrc作成時のディレクトリ構成
babelrc作成時のディレクトリ構成

Babelによる変換の確認

Classを作成して、babelによって本当に変換が行われるのか確認を行いましょう。index.jsにClassを利用したコードを記述します。


class Test {
  constructor(name) {
    this.name = name;
  }

  logger () {
    console.log("Hello", this.name);
  }
}

let test = new Test('world');

test.logger();

webpackを実行するとindex.jsに対してbabelの処理が行われ、bundle.jsが作成されます。


mac $ npm run dev

> test@1.0.0 dev /Users/mac/Document/test
> webpack --mode development

Hash: cb470bcb1d402518a7f1
Version: webpack 4.31.0
Time: 3260ms
Built at: 2019-05-21 20:12:08
    Asset      Size  Chunks             Chunk Names
bundle.js  4.79 KiB    main  [emitted]  main
Entrypoint main = bundle.js
[./src/index.js] 1010 bytes {main} [built]

index.htmlのscriptタグに作成したbundle.jsを指定するとConsoleにHello Worldが表示され、ブラウザがClassの入ったコードを処理できていることはわかります。

ブラウザでConsoleの確認
ブラウザでConsoleの確認

動作確認したブラウザがJavaScriptのClassをサポートしている場合はコンソールに”Hello world”が出力されてもBabelで変換されたかどうかはわかりません。変換されているか確認するためにwebpackによって生成されたbundle.jsの中身を確認します。

bundle.jsファイルの中からClassの処理が記述されている場所を探します。下記の部分がClassが変換されている箇所です。


***/ (function(module, exports) {

eval("function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor))

Babelを利用しない場合のbundle.jsも確認します。Babelを使用していない場合はファイルに記述したコードClassがそのまま出力されるためBabelにより変換が行われていることを確認することができます。


/***/ (function(module, exports) {

eval("class Test {\n  constructor(name) {\n    this.name = name;\n  }\n\n  logger () {\n    console.log(\"Hello\", this.name);\n  

/***/ })

Polyfillの利用

IE11などの古いブラウザの場合Promiseなどを利用するとサポートされていないので利用することができません。その場合はPollyfillが必要となります。babelでPolyfillを利用するためにcore-jsライブラリのインストールを行います。


% npm install core-js@3

インストールを行うのとcore-jsの3.17.2バージョンがインストールされました。core-jsを利用するためにbabel.config.jsonファイルに以下の設定を行います。


{
  "presets": [
    [
      "@babel/env",
      {
        "useBuiltIns": "usage",
        "corejs": "3"
      }
    ]
  ]
}

Promiseなどがコードに含まれている場合にビルドを行うと下記のようなコードが追加されていることを確認することができます。


require("core-js/modules/es.promise.js");

source map(ソースマップ)の作成

webpack.config.jsファイルにdevtoolを設定することでsource mapを作成することができます。


module.exports = {
  module: {
    rules: [
//略
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
    ],
  },
  devtool: 'source-map',
};

npm run devを実行してください。distフォルダの中にmap.js.mapファイルが作成されます。変換前のJavaScriptファイト、変換後のJavaScriptファイルの対応関係が記述されています。

まとめ

Bable(バベル)という名前を聞いた時、何か難しいと思ったかもしれませんがBabelの公式サイトに記載されている手順に従えばwebpackと簡単に連携できJavaScriptコードを変換できることが確認できました。