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