こんにちは。私事ですが、サイトリニューアルに伴いあだ名が変わり、「先生」となりました。(元博士)
降格になった訳ではありません。馴染まなかっただけです。
さて、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選
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。