ES6 in Practice

Post on 08-Jan-2017

21.429 views 1 download

Transcript of ES6 in Practice

ES6 in Practice@teppeis

Firefox Dev Conf 2015 Nov 15

Hello!• Teppei Sato, @teppeis

• Cybozu, Inc. / kintone

kintone.com

MUST BUY!

https://gihyo.jp/dp/ebook/2015/978-4-7741-7477-8

いまES6を正しく使うために

• ES6, ES7, ECMAScriptとは

• ES6 Modules • ES6 ≠ Babel • TypeScript • Rollup • HTTP/2

ほとんどModulesの話になっちゃいました :)

ECMAScript

ES6

ECMAScript

• ざっくり言えばJavaScriptの仕様

• Ecma Internationalが標準化 (ECMA-262)

• ISOでも標準化 (ISO/IEC 16262)

• TC39 (Technical Committee) が策定

• メンバーは全ブラウザベンダーとWeb関連企業

ECMAScript 6

• 2015年6月に公開されたESの最新仕様

• ES5から6年ぶりの大幅改定!

New syntax• Arrow Function • Classes • Modules • Block Scope (let/const) • Extended Object

Literal • Default Params • Rest Params • Spread Operator

• Destructuring • Iterator • Generator • Template Literal • Tail Call Optimization

New built-in classes and objects

• Promise • Map • Set • WeakMap/WeakSet • TypedArray • Symbol • Proxy/Reflect

Improvement of existing classes

• String • RegExp • Array • Object • Math • Number

ES6 compatibility tablehttps://kangax.github.io/compat-table/es6/

ES6 or ES2015?http://blog.cybozu.io/entry/9081

ES6 or ES2015?

• 正式にはECMAScript 2015

• 来年以降、ES2016, ES2017と年次リリースされていくため(後述)

• でも、慣れ親しんでる&短いのでES6もまだまだ使われてます

ES.next

The TC39 Process: Annual• 機能単位で仕様を策定

• 各仕様提案の策定は5段階のStage

Stage 0: Strawman (idea)

Stage 1: Proposal (problem, solution and demo/polyfill)

Stage 2: Draft (initial spec)

Stage 3: Candidate (review and feedback)

Stage 4: Finished (two implementations at least)

• Stage 4を毎年ES201Xとしてリリース

Stage 0: Strawman• アイデアレベル

• GitHubにPRすれば誰でも提案可能

• Send PR to github.com/tc39/ecma-262 !

Stage 4: Finished• 仕様公開の準備完了

• 2つ環境で実装済み

ES2016?

ES2016 (ES7) はどうなる?• 2016年6月に公開予定

• 主にES6のバグ修正

• 2016年1月のTC39 Meetingの時点で Stage 4になっている提案

• Array#includes はFF, Chrome, WKで実装済み

• 他は exponential operator (**), async/await, SIMD

ES7言うな問題• ES2016(ES7)にはほとんど新機能入らない

• ES6以降の提案仕様をまとめてES7と言いがち

• ES7 Decorator, ES7 Object.observe…

• ES.nextと言おう

• ブラウザに実装されてもキャンセルされる場合も

@domenic said

specversionnumbersarebullshites6,es2015,es2016…whocares?

youshouldnot.

http://www.slideshare.net/domenicdenicola/the-state-of-javascript-2015

ES6 Modules

Good Points

• 1ファイル 1モジュール

• staticで宣言的なsyntax

• strictモード

• 循環参照に対応

Syntax

Default export/import

// export.js export default function() { return "foo"; }

// import.js import foo from "./export.js"; foo();

Named export/import

// export.js export function foo() { return "foo"; } export class Bar {} export var baz = "baz";

// import.js import {foo, Bar, baz} from "./export.js";

foo(); new Bar(); console.log(baz); // "baz"

Mixed

// export.js export default function() { return "Default"; } export function foo() { return "Named"; }

// import.js import def, {foo} from "./export.js";

def(); // "Default" foo(); // "Named"

Defaultがオススメ• ES6 ModulesはDefault Exportが最も使いやすいようにデザインされている

• Named Exportは、バインディング名を知らないとimportできない

• まずはシンプルな1module 1exportから

Static and Declarative

Staticであるメリット• 実行前にパース時点で依存関係がわかる

• 実行前に各種SyntaxErrorを投げられる

• Browserify系バンドルツールを書きやすい

• 最適化しやすい

重複したexport default

SyntaxError!

// export.js export default function() { return "foo1"; } export default function() { return "foo2"; }

存在しないモジュールをimport

SyntaxError!

// import.js import foo from "./missing-module.js";

存在しないバインディングをimport

// export.js export function foo() { return "foo"; }

// import.js import bar from "./export.js";

SyntaxError!

注意:

• default exportのプロパティとnamed exportは異なる

Default export property

// export.js export default { foo: "Default Property" }; export var foo = "Named";

// import.js import def, {foo} from "./export.js";

console.log(def.foo); // "Default Property" console.log(foo): // "Named"

Strict Mode

Script or Module• ES6では実行前にScriptかModuleか指定

• Moduleの場合:

• 強制strictモード ("use strict"; 不要)

• トップレベルthisはundefined (非window)

• トップレベル変数がグローバルにならない

Strict mode in Modules

// in module console.log(this); // undefined var foo = 1; // module local, not global

// Error! with (obj) {}

// Error! var obj = {a: 1, a: 1};

ところで

Script or Module、 どうやって指定するの?

そもそも、 ブラウザからどうやって モジュール読むんだっけ?

Node.jsからは?

モジュール名の識別子は Node/CommonJSと同じルール? 拡張子.jsは不要?

既存のCommonJSモジュールと相互運用できる?

動的にモジュールを読むときは? RequireJSみたいにフックできる?

まだです…

https://flic.kr/p/4ZaDRz

ES6 Modules

• ES6で最も熱望された機能

• ES6で最も実装が遅れそうな機能

• 半分しか仕様が決まってない

ES6 Modules• ES6で定義

• Syntax

• Semantics

• ES6で未定義

• Loader

• Dynamic API

whatwg/loader

github.com/whatwg/loader• ブラウザのローダーを中心に議論中

• Dave Herman (Mozilla)

ブラウザでの読み込み方法(案)

<!-- external file --> <script type="module" src="./path/to/module.js"></script>

<!-- inline --> <script type="module"> import foo from "./path/to/module.js"; foo(); </script>

<!-- 従来の普通のscript要素ではmoduleを使えない -->

識別子(案)

// 相対URL import foo from "./path/to/module.js";

// 絶対URL import foo from "https://example.com/path/to/module.js";

jsc shellでES6 Modules体験• JavaScriptCoreが初期実装 (Constellation++)

• http://nightly.webkit.org/

• Download the latest binary for Mac OS

$ WebKit.app/Contents/Frameworks/10.11/ \ JavaScriptCore.framework/Versions/A/Resources/jsc \ -m ./module.js

Roadmap of Loader

https://github.com/whatwg/loader/blob/master/roadmap.md

ES6 Modules in Node.js

議論はまだ開始せず• npmはNode.js待ち

• Node.jsはV8待ち

• V8はwhatwg/loader待ち

論点: CommonJSとの相互運用• ES6 Modules importでCommonJSを読む

• CommonJS require()でES6 Modulesを読む

CommonJSはStaticに解析できない

// module.js if (someCondition) { exports.foo = "foo"; }

// import.js import foo from "./module.js";

Babel

BabelのCommonJS変換• 識別子の解釈はNode.jsと同じ

• CommonJSとの相互運用を重視強気に解釈して今動くことを優先

Babel export

// source export default {foo: 1};

// transpiled (with babel v5) Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = { foo: 1 }; module.exports = exports["default"];

Babel import

// source import foo from "./module.js" foo();

// transpiled "use strict"; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } var _moduleJs = require("./module.js"); var _moduleJs2 = _interopRequireDefault(_moduleJs); (0, _moduleJs2["default"])();

CommonJSとの相互変換

// module.js function React() {} React.Component = ... module.exports = React;

// import.js import Ract, {Component} from "react";

問題点• staticなsyntax errorが失われている

• default exportとnamed exportを併用不可

Babel 6 Shock

https://flic.kr/p/5oHM46

module.exportsに入れなくなった

// source export default {foo: 1};

// transpiled (with babel v6) Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = { foo: 1 }; // module.exports = exports["default"]; これが消えた

// import with CommonJS var foo = require("./foo").default; // .defaultが必要に

Babel Risk

https://flic.kr/p/87pcQk

Babel Risk

• ES6 Modulesは仕様未決定が多い分、Babelの独自解釈成分が強い

• Babelの解釈変更やNode.js/ブラウザの正式実装で、今書いているBabel版ES6

Modulesのコードが動かなくなる可能性

@sebmck said

https://speakerdeck.com/sebmck/javascript-transformation-jsconf-2015?slide=52

TypeScript

TypeScript export

// source export default {foo: 1};

// transpired exports.__esModule = true; exports["default"] = { foo: 1 };

TypeScript import

// export.ts function foo() {return 1;} export = foo;

// import.ts import foo from "./export"; // Error!

ES6 Modules in TypeScript

• 旧形式のモジュールは旧形式でロード、ES6モジュールはES6形式でロード

• 文法が2種類あるのはスマートではないが、 相互運用の独自解釈が少ないため堅牢

• 旧形式が独自なのでES6への移行に動機

Transpilers for ES6

トランスパイラを使う理由• 生産性の高い機能を実行環境に実装される前から使いたい

• 標準化されているから(altJSとは違って)相互運用性があり将来も動作するはず

ES6 Modulesを今使う?• 標準化はまだ途中、相互運用性はツール依存、将来動作しない可能性も

• staticな文法の利点が薄い

• 結局Browserifyする

• リスクリターンをよく考慮しましょう

Rollup

Rollup

• Next-generation ES6 Module Bundler

• staticな文法を最大限活用

• 最適化で未使用のバインディングを削除

http://rollupjs.org/

jsnext:main in package.json

{ "name": "my-package", "version": "0.1.0", "main": "dist/index.js", "jsnext:main": "src/index.js" }

https://github.com/rollup/rollup/wiki/jsnext:main

jsnext:main

• ES6コードとCommonJSコードを両方ともnpmパッケージに載せる仕組み

• staticな強みと、後方互換による資産の活用、 両方のメリットを活かせる

• Node.js/npmの未来へのヒント?

ES6 Modules with HTTP/2

生ES6 Modulesは速い?遅い?• ブラウザにES6 Modulesがネイティブに実装されたら、依存は実行時に解決される

• 非同期にリクエストを大量になげる通信コスト

HTTP/1.x では遅い• 多量のTCP接続: 多量の依存ファイル

• ラウンドトリップタイム: 深いネストした依存

• これまでのRequireJS等と同じ問題

• r.js: 本番環境用の事前ビルドツールで解決

HTTP/2で解決?• 多量のTCP接続: 多重化で解決!

• ラウンドトリップタイム: 解決できず…

ラウンドトリップタイムの解決• ただのServer Pushではキャッシュ制御に難点

• クライアントで制御: ServiceWorker

• サーバーで制御: H2O cache-aware server pusher

• 現実世界での探求はまだまだこれから!

http://teppeis.hatenablog.com/entry/2015/05/es6-modules-and-http2

Conclusion

Conclusion

• 「ES6はいまから使える」言い過ぎた :)

• ES6/ES7を正しく理解しよう

• BabelとES6の違いを正しく認識しよう

• ES6 Modulesはこれからだ!

MUST BUY!

https://gihyo.jp/dp/ebook/2015/978-4-7741-7477-8

Thanks!