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

ES6 in Practice

Jan 08, 2017

Download

Technology

Teppei Sato
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
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!