ES2015のモジュール管理
ES Modulesを使用するために
ここまで説明してきたES Modulesですが、上記の通りWHATWGによって仕様策定が進んでいるものの、2017年4月時点ではES Modulesの機能をサポートしている環境はありません。ES Modulesを使用するには、Babelなどのトランスパイラが必要となります。
トランスパイラ
トランスパイラとはES2015などの新しいバージョンのコードをES5などの以前のバージョンに変換して、以前のバージョンのブラウザでも動作するコードに変換してくれるツールのことです。
トランスパイラとして代表的なものとしてはBabelがあります。ECMAScript 6 compatibility tableを参照すると、2017年4月時点でBabelはES2015の71%の項目についてサポートしていることがわかります。
ECMAScript 6 compatibility table
Babelを使用してES2015で書かれたファイルを変換するには下記のコマンドを実行します。下記の例ではsrcフォルダにあるapp.jsファイルを変換し、distフォルダへ保存します。
$ babel src/app.js --out-file dist/app.js
実際にES Modulesで書かれたファイルを変換してみると、下記のようなCommonsJS形式のコードに変換されることがわかります。
// ---ES2015 app.js--- import { square, num } from './lib' console.log(square(4)) console.log(num) // ---lib.js--- function square(x) { return x * x } const num = Math.E + Math.PI export { square, num }
// ---app.js--- 'use strict'; var _lib = require('./lib'); console.log((0, _lib.square)(4)); console.log(_lib.num); // ---lib.js--- "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function square(x) { return x * x; } var num = Math.E + Math.PI; exports.square = square; exports.num = num;
このようにトランスパイラを使用することで、ES2015の記述をCommonJSの記述に変換できます。しかしこのままではCommonJS形式のコードになっているため、ブラウザ上で実行することができません。ブラウザで実行可能な形式にするにはBrowserifyやWebpackを使用してビルドする必要があります。本章では近年利用されることが多くなってきたWebpackを利用したビルドについて解説していきます。
Webpackとは
Webのコンテンツには、様々なアセットが含まれます。Webpackはこれらのアセットをモジュールとして扱い、それらのモジュールの依存関係を解決しつつ、静的なアセットを生成するビルドツールです。
Webpackを使用することで、複数に分割したJavaScriptファイルを依存関係を解決しながら結合や圧縮をすることができます。またBabelなどのトランスパイラとも連携ができるため、現在のフロントエンド開発では欠かすことのできないツールとなっています。
Webpackを使用するには、Node.jsが必要となります。詳細な設定は割愛しますがNode.jsをインストールした後に、npmからWebpackをインストールしてください。セットアップ完了後、WebpackからBabelを利用するために必要なパッケージを導入していきます。インストールするパッケージは「package.json」に記述しておきます。
{ "name": "ES2015_project", "version": "1.0.0", "description": "Setting for Webpack.", "main": "app.js", "scripts": { "build": "webpack" }, "author": "Hiroaki Imai", "devDependencies": { "babel-core": "^6.24.0", "babel-loader": "^6.4.1", "babel-preset-es2015": "^6.24.0", "webpack": "^2.3.2" } }
今回はES2015用のBabelのプリセットを使用するため、Babelの設定ファイル(.babelrc)を作成します。
{ "presets": [ ["es2015", {"modules": false}] ] }
「npm install」コマンドを実行すると、必要なパッケージがインストールされます。パッケージインストール後、ES2015のコードをビルドするための設定ファイルを準備します。
const path = require('path') module.exports = { entry: './src/app.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'app.bundle.js' }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: 'babel-loader' } ] } }
上記の設定例では「./src/app.js」にて記述されたコードが「app.bundle.js」という名前で「dist」フォルダ以下に出力されます。この「app.bundle.js」をHTMLファイルから読み込むことで、ES2015で記述されたコードをブラウザ上で動かせるようになります。
最後に
本連載では6回に渡り、ES2015の背景から言語として追加された機能や非同期処理、モジュール管理といったES2015の魅力的な仕様について解説してきました。ES2015の導入を見送っていた方にとっては改めて導入を検討するきっかけに、またすでに導入していた方にとっても、ES2015の機能を再確認する良いきっかけになれば幸いです。
ECMAScriptとしては、ES2015以降もJavaScriptについては活発に議論が進められており、前回のES2015が備えるモダンな非同期処理で解説したAsync Functionsを始めES2017以降に導入されるであろういくつかの機能がリリース前段階のStage 4(Finished Proposals)となっています。
Finished Proposals - Ecma TC39
JavaScriptという言語は様々な分野へ活用の場を広げており、Web開発においてなくてはならない存在となってきています。これからも日々の開発に積極的に活用していき、JavaScriptがますます魅力的な言語となるように盛り上げていきましょう!