es6 in practice

94
ES6 in Practice @teppeis Firefox Dev Conf 2015 Nov 15

Upload: teppei-sato

Post on 08-Jan-2017

21.429 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: ES6 in Practice

ES6 in Practice@teppeis

Firefox Dev Conf 2015 Nov 15

Page 2: ES6 in Practice

Hello!• Teppei Sato, @teppeis

• Cybozu, Inc. / kintone

Page 3: ES6 in Practice

kintone.com

Page 4: ES6 in Practice

MUST BUY!

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

Page 5: ES6 in Practice

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

• ES6, ES7, ECMAScriptとは

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

Page 6: ES6 in Practice

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

Page 7: ES6 in Practice

ECMAScript

Page 8: ES6 in Practice

ES6

Page 9: ES6 in Practice

ECMAScript

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

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

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

• TC39 (Technical Committee) が策定

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

Page 10: ES6 in Practice

ECMAScript 6

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

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

Page 11: ES6 in Practice

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

Page 12: ES6 in Practice

New built-in classes and objects

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

Page 13: ES6 in Practice

Improvement of existing classes

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

Page 14: ES6 in Practice

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

Page 15: ES6 in Practice

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

Page 16: ES6 in Practice

ES6 or ES2015?

• 正式にはECMAScript 2015

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

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

Page 17: ES6 in Practice

ES.next

Page 18: ES6 in Practice

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としてリリース

Page 19: ES6 in Practice

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

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

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

Page 20: ES6 in Practice

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

• 2つ環境で実装済み

Page 21: ES6 in Practice

ES2016?

Page 22: ES6 in Practice

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

• 主にES6のバグ修正

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

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

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

Page 23: ES6 in Practice

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

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

• ES7 Decorator, ES7 Object.observe…

• ES.nextと言おう

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

Page 24: ES6 in Practice

@domenic said

specversionnumbersarebullshites6,es2015,es2016…whocares?

youshouldnot.

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

Page 25: ES6 in Practice

ES6 Modules

Page 26: ES6 in Practice

Good Points

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

• staticで宣言的なsyntax

• strictモード

• 循環参照に対応

Page 27: ES6 in Practice

Syntax

Page 28: ES6 in Practice

Default export/import

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

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

Page 29: ES6 in Practice

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"

Page 30: ES6 in Practice

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"

Page 31: ES6 in Practice

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

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

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

Page 32: ES6 in Practice

Static and Declarative

Page 33: ES6 in Practice

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

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

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

• 最適化しやすい

Page 34: ES6 in Practice

重複したexport default

SyntaxError!

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

Page 35: ES6 in Practice

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

SyntaxError!

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

Page 36: ES6 in Practice

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

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

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

SyntaxError!

Page 37: ES6 in Practice

注意:

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

Page 38: ES6 in Practice

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"

Page 39: ES6 in Practice

Strict Mode

Page 40: ES6 in Practice

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

• Moduleの場合:

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

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

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

Page 41: ES6 in Practice

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};

Page 42: ES6 in Practice

ところで

Page 43: ES6 in Practice

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

Page 44: ES6 in Practice

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

Page 45: ES6 in Practice

Node.jsからは?

Page 46: ES6 in Practice

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

Page 47: ES6 in Practice

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

Page 48: ES6 in Practice

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

Page 49: ES6 in Practice

まだです…

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

Page 50: ES6 in Practice

ES6 Modules

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

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

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

Page 51: ES6 in Practice

ES6 Modules• ES6で定義

• Syntax

• Semantics

• ES6で未定義

• Loader

• Dynamic API

Page 52: ES6 in Practice

whatwg/loader

Page 53: ES6 in Practice

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

• Dave Herman (Mozilla)

Page 54: ES6 in Practice

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

<!-- 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を使えない -->

Page 55: ES6 in Practice

識別子(案)

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

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

Page 56: ES6 in Practice

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

Page 57: ES6 in Practice

Roadmap of Loader

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

Page 58: ES6 in Practice

ES6 Modules in Node.js

Page 59: ES6 in Practice

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

• Node.jsはV8待ち

• V8はwhatwg/loader待ち

Page 60: ES6 in Practice

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

• CommonJS require()でES6 Modulesを読む

Page 61: ES6 in Practice

CommonJSはStaticに解析できない

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

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

Page 62: ES6 in Practice

Babel

Page 63: ES6 in Practice

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

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

Page 64: ES6 in Practice

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"];

Page 65: ES6 in Practice

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"])();

Page 66: ES6 in Practice

CommonJSとの相互変換

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

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

Page 67: ES6 in Practice

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

• default exportとnamed exportを併用不可

Page 68: ES6 in Practice

Babel 6 Shock

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

Page 69: ES6 in Practice

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が必要に

Page 70: ES6 in Practice

Babel Risk

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

Page 71: ES6 in Practice

Babel Risk

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

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

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

Page 72: ES6 in Practice

@sebmck said

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

Page 73: ES6 in Practice

TypeScript

Page 74: ES6 in Practice

TypeScript export

// source export default {foo: 1};

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

Page 75: ES6 in Practice

TypeScript import

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

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

Page 76: ES6 in Practice

ES6 Modules in TypeScript

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

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

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

Page 77: ES6 in Practice

Transpilers for ES6

Page 78: ES6 in Practice

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

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

Page 79: ES6 in Practice

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

• staticな文法の利点が薄い

• 結局Browserifyする

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

Page 80: ES6 in Practice

Rollup

Page 81: ES6 in Practice

Rollup

• Next-generation ES6 Module Bundler

• staticな文法を最大限活用

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

Page 82: ES6 in Practice

http://rollupjs.org/

Page 83: ES6 in Practice

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

Page 84: ES6 in Practice

jsnext:main

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

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

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

Page 85: ES6 in Practice

ES6 Modules with HTTP/2

Page 86: ES6 in Practice

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

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

Page 87: ES6 in Practice

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

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

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

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

Page 88: ES6 in Practice

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

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

Page 89: ES6 in Practice

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

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

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

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

Page 90: ES6 in Practice

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

Page 91: ES6 in Practice

Conclusion

Page 92: ES6 in Practice

Conclusion

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

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

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

• ES6 Modulesはこれからだ!

Page 93: ES6 in Practice

MUST BUY!

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

Page 94: ES6 in Practice

Thanks!