NTTドコモ様_dカーシェア
NTTドコモ様_dカーシェア
2014.12.04

ECMAScript6で書こう!WebPackとES6-loaderで環境を作り、ES6を先取り体験する方法

先生

こんにちは。私事ですが、サイトリニューアルに伴いあだ名が変わり、「先生」となりました。(元博士)
降格になった訳ではありません。馴染まなかっただけです。

さて、ES5のブラウザ対応も広まり、ES6の話題がちらほらと出始めました。

ES6ではClassやConstが加わることとなり、これまでのJavaScriptの書き方も変わってくることでしょう。

というわけで早速ES6でコードを書いてみたいと思いますが、普通に書いたのでは動かないブラウザが多数です。
そこで本日は、WebPackとES6-Loaderを使い、ES6で書きつつもES5にコンバートさせていく手順を紹介したいと思います。

環境

インストールの前に開発ディレクトリを作ります。今回はこんな感じにします。

/es6
┣ /node_modules
┣ /source
┗ package.json

Node.js

npmが使える状態になっている必要があります。Nodeのインストールとpackage.jsonの作り方については、過去の記事「Gulp.js入門 – コーディングを10倍速くする環境を作る方法まとめ」を参考にしてください。

WebPack

グローバルにWebPackをインストールします。

npm install -g webpack

ES6 Loader

Package.jsonはnpm initすれば作れます。
こちらも先ほどの「Gulp.js入門 – コーディングを10倍速くする環境を作る方法まとめ」で紹介しておりますので、参考にしてください。

そしてES6 Loaderをインストールします。

npm install es6-loader --save-dev

これで環境ができました。

WebPackの設定

先ほど作ったディレクトリの1番上にwebpack.config.jsというファイルを作ります。

/es6
┣ /node_modules
┣ /source
┣ package.json
┗ webpack.config.js

webpack.config.jsには以下のように記述します。

module.exports = {
    output: {
        filename: "[name].js"
    },
    module: {
        loaders: [
            { test: /\.js$/, loader: 'es6-loader' },
        ]
    },
    plugins: [
    ]
};

module.loadersに.jsファイルだったらex6-loaderを実行すると記述してあげます。

これで設定はOKです。

さっそくクラスとモジュールを試す

sourceディレクトリに以下のJSを作ります。

  • animal.js
class Animal {
	constructor(name) {
		this.name = name;
	}
}
export default Animal;

export default AnimalでAnimalクラスを外部にエクスポートしてimportできるようにしています。

  • dog.js
import Animal from './animal';
class Dog extends Animal{
	constructor(name) {
		super(name);
	}
	callName() {
		alert(this.name);
	}
}

var dog = new Dog('Natsu');
dog.callName();

上記のように「class クラス名」でクラスができます。constructorはclassがnewされたときに実行され、「class クラス名 extends 継承元クラス名」で継承ができます。簡単ですね!

また、super()を使って継承元のconstrutor関数を呼んだり、継承元の関数を指定して実行もできます。

そして、importを用いてエクスポートされているJSを呼び出すことができ、これによってdog.jsでAnimalクラスが使えるようになります。

しかし、このままでは多くのブラウザで実行できないため、最初にインストールしたWebPackを使います。

以下のコマンドを実行するとmain.jsが作成されます。

webpack ./js/dog.js

開くとこんな感じに。

/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;
/******/
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";
	var Animal = __webpack_require__(1)["default"];
	var Dog = (function(super$0){var PRS$0 = (function(o,t){o["__proto__"]={"a":t};return o["a"]===t})({},{});var DP$0 = Object.defineProperty;var GOPD$0 = Object.getOwnPropertyDescriptor;var MIXIN$0 = function(t,s){for(var p in s){if(s.hasOwnProperty(p)){DP$0(t,p,GOPD$0(s,p));}}return t};var SP$0 = Object.setPrototypeOf||function(o,p){if(PRS$0){o["__proto__"]=p;}else {DP$0(o,"__proto__",{"value":p,"configurable":true,"enumerable":false,"writable":true});}return o};var OC$0 = Object.create;if(!PRS$0)MIXIN$0(Dog, super$0);var proto$0={};
		function Dog(name) {
			super$0.call(this, name);
		}if(super$0!==null)SP$0(Dog,super$0);Dog.prototype = OC$0(super$0!==null?super$0.prototype:null,{"constructor":{"value":Dog,"configurable":true,"writable":true}});DP$0(Dog,"prototype",{"configurable":false,"enumerable":false,"writable":false});
		proto$0.callName = function() {
			alert(this.name);
		};
	MIXIN$0(Dog.prototype,proto$0);proto$0=void 0;return Dog;})(Animal);

	var dog = new Dog('Natsu');
	dog.callName();

/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";
	var Animal = (function(){var PRS$0 = (function(o,t){o["__proto__"]={"a":t};return o["a"]===t})({},{});var DP$0 = Object.defineProperty;var GOPD$0 = Object.getOwnPropertyDescriptor;var MIXIN$0 = function(t,s){for(var p in s){if(s.hasOwnProperty(p)){DP$0(t,p,GOPD$0(s,p));}}return t};
		function Animal(name) {
			this.name = name;
		}DP$0(Animal,"prototype",{"configurable":false,"enumerable":false,"writable":false});
	;return Animal;})();
	exports["default"] = Animal;

/***/ }
/******/ ])

実行させると……

実行できました!
ES6-loaderを使うことでES5で動作するように変換してくれます。これで未来のコーディングが体験できます。

なお、現在対応されている機能についてはこちらに記載されています。

WebPackの機能例:JSの圧縮

WebPackは今回紹介したもの以外にも数多くの機能を持っています。そのうちの1つとして、JSの圧縮をしてみましょう。

先ほどはグローバルにWebPackをインストールしましたが、今度はローカルにインストールします。

npm install web pack --save-dev

続いてwebpack.config.jsを以下のように変更します。

var webpack = require('webpack');
module.exports = {
    output: {
        filename: "[name].js"
    },
    module: {
        loaders: [
            { test: /\.js$/, loader: 'es6-loader' },
        ]
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin(),
    ]
};

この状態で再びWebPackコマンドを実行します。

webpack ./js/dog.js

すると今度はmain.jsが圧縮された状態で出力されます。

!function(t){function e(n){if(r[n])return r[n].exports;var o=r[n]={exports:{},id:n,loaded:!1};return t[n].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var r={};return e.m=t,e.c=r,e.p="",e(0)}([function(t,e,r){"use strict";var n=r(1)["default"],o=function(t){function e(e){t.call(this,e)}var r=function(t,e){return t.__proto__={a:e},t.a===e}({},{}),n=Object.defineProperty,o=Object.getOwnPropertyDescriptor,a=function(t,e){for(var r in e)e.hasOwnProperty(r)&&n(t,r,o(e,r));return t},u=Object.setPrototypeOf||function(t,e){return r?t.__proto__=e:n(t,"__proto__",{value:e,configurable:!0,enumerable:!1,writable:!0}),t},c=Object.create;r||a(e,t);var i={};return null!==t&&u(e,t),e.prototype=c(null!==t?t.prototype:null,{constructor:{value:e,configurable:!0,writable:!0}}),n(e,"prototype",{configurable:!1,enumerable:!1,writable:!1}),i.callName=function(){alert(this.name)},a(e.prototype,i),i=void 0,e}(n),a=new o("Natsu");a.callName()},function(t,e){"use strict";var r=function(){function t(t){this.name=t}{var e=(function(t,e){return t.__proto__={a:e},t.a===e}({},{}),Object.defineProperty);Object.getOwnPropertyDescriptor}return e(t,"prototype",{configurable:!1,enumerable:!1,writable:!1}),t}();e["default"]=r}]);

このようにWebPackはさまざまなプラグインやローダーを使ってJavaScriptをコンパイルすることができます。詳しくは公式サイトをごらんください。

LIGではこのWebPackとAngularJSで開発をおこなうなどしています。

まとめ

いかがでしたでしょうか。

ほんの触りだけの紹介でしたが、ES6が楽しみになりましたでしょうか。
WebPackとES6-loaderを使うことでES5へコンバートできるので、AltJSの選択肢の1つとして考えても良いのではないかと思います。

また、今回使用したサンプルはGithubにて公開しておりますので、興味のある方はこちらよりダウンロードまたはフォークしてみてください。

それでは、Enjoy ES6!

 

【先生に聞いてみよう!】

業務で安心して使える厳選AngularJSモジュール8選+α

LIG主催のAngularJS勉強会 #ngCurryが開催されました

LIGのソースコードレビュー会で使用している共有ツールとライブラリの活用方法の紹介

AngularJS勉強会 ng-mtg#6に登壇してきました

フロントエンド開発を裏から支えるデバッグアプリケーション4選