入門者/初心者にもわかるwebpack 5の基礎(Babel編)
本文書は”入門者/初心者にもわかる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を利用することで開発者は新旧のブラウザを意識することなく新しい構文を使って効率よくプログラムを作成することができます。
CMAScirpt 2015(「ES6」)が登場する前の手法でコーディングしている場合、また古いブラウザではプログラムが動かなくても問題ないという場合にはBabelを利用する必要はありません。
Babelと混同してしまう可能性が高いものにPolyfillというものがあります。Bableの場合は新しい構文(記述方法)を変換してくれますがPolyfillでは古いブラウザでは対応していない関数やライブラリを代替してくれるコードを提供してくれます。IE11ではPromiseをサポートしていないためPolyfillが必要となります。必要となるのはBabelではありません。
WebpackでのBabelの使い方
Bableをwebpackで利用するためにはインストールが必要になります。Babelの公式サイトにアクセスして上部のSetupのリンクをクリックして、webpackでのインストール方法の確認を行います。
Bableが使用できるビルドツールやフレームワークがたくさんあることを確認できます。Build systemsカテゴリーのwebpackをクリックしてください。
インストール手順から設定方法までwebpackの動作に必要なことはすべて記述されているのでこの流れ通りに設定を行います。
前準備
動作確認を行うためには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に対応するプラグインも下記の画像から確認することができます。
Pluginのリスト情報からClassのPluginである@babel/plugin-transform-classesを確認するとインストールを行った@bable/preset-envに含まれていることがわかります。preset-envを利用することでClassを使ったコードを記述するとBabelによってClassに対応するコードに変換されます。
presetのインストールが完了したら、こちらも公式ドキュメントに記載されている通り、プロジェクトフォルダの直下にbabel.config.jsonファイルを作成して、以下を記述します。
mac $ touch babel.config.jso
{
"presets": ["@babel/preset-env"]
}
作成時のディレクトリ構成は下記のようになっています。
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の入ったコードを処理できていることはわかります。
動作確認したブラウザが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コードを変換できることが確認できました。