You Don't Know ES Modules

Embed Size (px)

Text of You Don't Know ES Modules

  • YOU DON'T KNOW ES Modules

    @teppeis

    Node #21

    June 29, 2016

  • Hello! Teppei Sato, @teppeis Cybozu, Inc. / kintone

  • kintone.com

    http://kintone.com

  • (Module )

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

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

  • History of JavaScript Modules

  • Module PatternExt.namespace("myNameSpace"); myNameSpace.app = function() { // private variables var privVar1 = 11;

    // private functions var btn1Handler = function( button, event ) { }; // public space return { // public methods init: function() { // ... } }; }();

  • AMD (RequireJS)

    define(['require', 'dep1', 'dep2'], function(require) { var dependency1 = require('dep1'), dependency2 = require('dep2'); return function() {}; });

  • CommonJS Module (CJS)

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

    // main.js var foo = require('./foo');

  • ex) browserify, webpack

    var moduleName = 'foo'; if (someCondition) { moduleName = 'bar'; } var module = require(moduleName);

  • Node.js

    3rd party

  • ES6 Modules

  • export/import

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

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

  • Awesome!

    parse

    write one, run anywhere!?

    `Module` is the new script strict

    top level `this`: undefined `await`: future reserved word

  • 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

    1 module 1 export

  • :

    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"

  • 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!

  • Rollup: tree shakinghttp://rollupjs.org/

    http://rollupjs.org/

  • MS Edge https://blogs.windows.com/msedgedev/2016/05/17/es6-modules-and-beyond/

    https://blogs.windows.com/msedgedev/2016/05/17/es6-modules-and-beyond/

  • Standard and Universal

  • ES Syntax

    Node

    Write once, run anywhere!?

  • Module is the new script

  • Script or Module

    ES6 2

    15.1.9 `ScriptEvaluationJob(sourceText)` 15.2.1.16.1 `ParseModule(sourceText)`

    Script Module

  • Module

    strict

    top level scope, not global scope top level `this`: undefined `await`: future reserved word

    top level await

    HTML comment

  • in Modules

    // SyntaxError! (strict mode) with (obj) {}

    console.log(this); // undefined

    var foo = 1; // module local, not global

    var await = 1; // SyntaxError! (future reserved word)

    // SyntaxError! (HTML comment)

  • https://twitter.com/domenic/status/743981311568785408

    https://twitter.com/domenic/status/743981311568785408

  • ECMAScript

  • ECMAScript

    module fetch

    Loader API API

  • : whatwg/html

    Node.js: nodejs/node-eps Loader API

    whatwg/loader

  • Loading semantics whatwg/loader

  • whatwg/loader This repository consolidates work on the

    ECMAScript module loading semantics with the integration points of Web browsers, as well as Node.js.https://github.com/whatwg/loader

    ``

    whatwg/html (#83)

    roadmap

    https://github.com/whatwg/loader/issues/83#issuecomment-166444178

  • Dynamic Loader API (reflection)

    System.loader.import('./foo.js').then(foo => { // use foo! });

  • Loader pipeline (hooks)

    1. resolve 2. fetch 3. translate 4. instantiate

  • Modules in browsers whatwg/html

  • whatwg/html

    PR: https://github.com/whatwg/html/pull/443

    4.12 The elements > Scripting script

    8.1 Web app APIs > Scripting fetch, parse

    https://github.com/whatwg/html/pull/443

  • External module

    Inline module import fo from './foo.js'; console.log(foo());

  • type=module

    MIME module type

    MIME

  • scope var foo = 1; console.log(typeof foo); // undefined console.log(window.foo); // 1 var foo = 2; console.log(window.foo); // 1 console.log(foo); // 2 console.log(typeof foo); // undefined console.log(window.foo); // 1 var foo = 3; console.log(window.foo); // 1 console.log(foo); // 3

  • import

    URL

    "/", "./", "../" URL

    TypeError!

    URL

    inline: document base external, imported: URL

    ".js"

  • // OK import "https://example.com/lodash.js"; import "/lodash.js"; import "./lodash.js"; import "../lodash.js";

    // NG import ".../lodash.js"; import "lodash.js"; import "lodash";

  • defer

    fetch

    fetch

    DOM

  • async

    fetch

    module fetch

  • cors mode

    import

    CORS

    CDN

    // from `https://example.com/foo.html` import $ from 'https://cdn.example.com/jquery.js';

    // cdn.example.com must send `Access-Control-Allow-Origin` header

  • crossorigin crossorigin import cookie

    (credentials mode)

    default: omit "anonymous": same-origin "use-credentials": include

    cookie

    JS

  • Module Workers

    module importScripts TypeError

    // Web Worker const worker = new Worker("worker.js", {type: "module"});

    // Service Worker navigator.serviceWorker.register("sw.js", {type: "module"});

  • realm URL

    URL HTTP 1

    realm

    import './foo.js'; // sends HTTP request import './foo.js'; // doesn't send request

  • UTF-8 meta Content-Type charset

    Content-Type JavaScript MIME Type

    Chrome/IE `X-Content-Type: nosniff`

    module export

    script src URL fetch

    document insert

  • Edge: https://blogs.windows.com/msedgedev/2016/05/17/es6-modules-and-beyond/ Preview

    Chrome: https://bugs.chromium.org/p/v8/issues/detail?id=1569 Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=568953 WebKit: https://bugs.webkit.org/show_bug.cgi?id=147340

    JSC const

    https://bugs.chromium.org/p/v8/issues/detail?id=1569https://bugzilla.mozilla.org/show_bug.cgi?id=568953https://bugs.webkit.org/show_bug.cgi?id=147340

  • Modules in Node.js nodejs/node-eps

  • ES6 Modules

  • npm Node.js

    Node.js V8

    V8 whatwg/loader

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

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

  • ES Modules CJS Modules ES Modules

    import "cjs" require("esm")

  • ES Modules

    2 : Module or Script

    ES6 ``

    Node.js CJS Script require, module, exports

  • Module or Script?

    // global scope? function foo(value) { // the arguments object is modified? value = value || ''; var args = [].slice.call(arguments); // what is `this`? args.unshift(this); return args; } foo(null);

  • How to detect

    New Pragma: "use module"; New file extension: .mjs Content sniffing package.json

  • New Pragma: "use module";

    strict

    `"use module;`

    Cons Unacceptable boilerplate tax :

  • New file extension: .mjs ".mjs" Module

    `import './foo'` foo.mjs, foo.js

    Cons "*.js"

    : .jsx

    Modules .mjs

    bin

  • Content sniffing

    Module

    Script

    Cons import/export

  • package.json (a): entry point package.json module

    type=module

    Rollup jsnext:main

    { // ... "main": "old/index.js", "module": "lib/index.js", // ... }

  • package.json (a): entry point Cons

    package.json

    Module

    import ( )

    import "foo/bar";

  • package.json (b): white list

    package.json Module

    import

    { // files and directories: "modules": ["special.js", "lib", "bin/hello.js"],

    // if package never uses CJS Modules "modules": ["."], }

  • .mjs draft

  • Defense of .js

  • Defense of .js https://github.com/dherman/defense-of-dot-js/ Dave Herman, Yehuda Katz, Caridy Patio package.json (a)(b)

    modules.root pacakg