Slide 1

Slide 1 text

Module Harmony JSConf JP 2025 pixiv Inc. 森内建太 @petamoriken 2025.11.16

Slide 2

Slide 2 text

2 Self-Introduction ● A Deno contributor ● An advocate for ES2025 Float16Array ● I like to keep up with Web Standards ○ Sharing new stuff in the company's frontend community petamoriken pixiv WebDev engineer in Fukuoka

Slide 3

Slide 3 text

3 https://scrapbox.io/petamoriken/

Slide 4

Slide 4 text

4 好きな TC39 Proposals 発表ドラゴン ©ンバヂ https://x.com/nbaji9

Slide 5

Slide 5 text

5 Table of Contents ● ES Modules ● Current Specification ● Current Proposals ○ Import Phase Modifiers ○ Other Proposals ● To conclude

Slide 6

Slide 6 text

ES Modules 6

Slide 7

Slide 7 text

7 ES Modules import { foo } from "./foo.mjs"; import * as bar from "./bar.mjs"; import baz from "./baz.mjs"; import qux from "./qux.json" with { type: "json" }; export { foo } from "./foo.mjs"; const namespace = await import("./foo.mjs");

Slide 8

Slide 8 text

Current Specification 8

Slide 9

Slide 9 text

9 ES Module Graph : Module Record

Slide 10

Slide 10 text

10 ES Module Graph JS JS JS JS JSON JS JS * * ESM Integration for Wasm is progressing at the WasmWG : Module Record Wasm

Slide 11

Slide 11 text

11 Module Records (Abstract) Module Record Source Text Module Record Cyclic Module Record Synthetic Module Record

Slide 12

Slide 12 text

12 Module Records (Abstract) Module Record Source Text Module Record Cyclic Module Record Synthetic Module Record Wasm JS JSON, CSS

Slide 13

Slide 13 text

13 Module Records (Abstract) Module Record Source Text Module Record Cyclic Module Record Synthetic Module Record CommonJS Wasm JS JSON, CSS * no spec

Slide 14

Slide 14 text

14 Module Records (Abstract) Module Record Source Text Module Record Cyclic Module Record Synthetic Module Record CommonJS Wasm JS JSON, CSS * no spec Due to the spec, the cache cannot be purged (purgeable) cache

Slide 15

Slide 15 text

15 Import Phase Resolve Load (dependencies) Link Evaluate

Slide 16

Slide 16 text

16 Import Phase Resolve Load (dependencies) Link Evaluate

Slide 17

Slide 17 text

17 Import Phase Resolve Load (dependencies) Link Evaluate cache

Slide 18

Slide 18 text

18 Import Phase Resolve Load (dependencies) Link Evaluate

Slide 19

Slide 19 text

19 Import Phase Resolve Load (dependencies) Link Evaluate

Slide 20

Slide 20 text

20 Import Phase Resolve Load (dependencies) Link Evaluate

Slide 21

Slide 21 text

21 Import Phase Resolve Load (dependencies) Link Evaluate

Slide 22

Slide 22 text

22 https://speakerdeck.com/uhyo/require -esm-toecmascriptshi-yang

Slide 23

Slide 23 text

Current Proposals 23

Slide 24

Slide 24 text

24

Slide 25

Slide 25 text

25

Slide 26

Slide 26 text

26 Module Harmony (2024-12 TC39 meeting)

Slide 27

Slide 27 text

Import Phase Modifiers 27

Slide 28

Slide 28 text

28 Import Phase Modifiers Resolve Load (dependencies) Link Evaluate modifier: asset source defer import asset ref from "./foo.mjs"; const module = await import.source("./bar.mjs");

Slide 29

Slide 29 text

29 Asset References Resolve Load (dependencies) Link Evaluate asset source defer import asset ref from "./foo.mjs"; console.log(ref); // AssetReference object const namespace = await import(ref); ● No need to change the relative path even when the AssetReference object passes through modules

Slide 30

Slide 30 text

30 Asset References Resolve Load (dependencies) Link Evaluate asset source defer import asset imageRef from "./foo.png"; const img = new Image(); img.src = URL.createObjectURL(imageRef); ● Allows notifying the host (runtime, bundler) about the existence of asset files statically

Slide 31

Slide 31 text

31 Module Sources Resolve Load (dependencies) Link Evaluate asset source defer (Abstract) Module Source WebAssembly.Module ModuleSource Wasm JS

Slide 32

Slide 32 text

32 Module Sources Resolve Load (dependencies) Link Evaluate asset source defer import source module from "./foo.wasm"; console.log(module); // WebAssembly.Module object const instance = await WebAssembly.instantiate(module, {/* imports */}); ● Wasm modules can be statically added to ES Module Graph ● CSP's wasm-unsafe-eval is no longer needed, improving security

Slide 33

Slide 33 text

33 Module Sources Resolve Load (dependencies) Link Evaluate asset source defer import source module from "./foo.mjs"; console.log(module); // ModuleSource object const worker = new Worker(module); ● Modules for Web Workers can be statically added to ES Module Graph ● Dynamic Imports work, too

Slide 34

Slide 34 text

34 Module Sources Resolve Load (dependencies) Link Evaluate asset source defer const workerModule = module { self.addEventListener("message", (e) => {}); }; const worker = new Worker(workerModule); Module Expressions ● Possible to create inline modules for Web Workers

Slide 35

Slide 35 text

35 Deferring Module Eval Resolve Load (dependencies) Link Evaluate asset source defer import defer * as namespace from "./foo.mjs"; namespace.bar; // evaluate "./foo.mjs" ● Defer execution until the namespace object's getter is invoked (namespace imports only supported) ● Improve initial performance by delaying evaluation

Slide 36

Slide 36 text

36 Deferring Module Eval Resolve Load (dependencies) Link Evaluate asset source defer // math.mjs export defer { add } from "./math/add.mjs"; export defer { sub } from "./math/sub.mjs"; ● Enable "Tree Shaking" without heuristics Deferred re-exports // do not evaluate "./math/sub.mjs" import { add } from "./math.mjs";

Slide 37

Slide 37 text

Other Proposals 37

Slide 38

Slide 38 text

38 Module Declarations module Foo { export function foo() {} } import { foo } from Foo; ● Bundlers' implementation complexity increases with ES Modules ○ Proposal for additional syntax for bundlers ● Optimizing bundled JS files is challenging for engines

Slide 39

Slide 39 text

39 Import Sync const namespace = import.sync("./foo.mjs"); ● Bridge the gap with CommonJS using synchronous dynamic import ○ Personally, the difference in whether cache can be purged seems like a big gap... ● In a browser environment, the main thread cannot be blocked, so it might throw an exception

Slide 40

Slide 40 text

40 Import Bytes / Text import bytes from "./foo.png" with { type: "bytes" }; // Uint8Array backed by an Immutable ArrayBuffer console.log(bytes); ● Add bytes and text support to Synthetic Module Records ● Originally proposed in whatwg/html#9444 import text from "./foo.txt" with { type: "text" }; // string (normally) interpreted as UTF-8 console.log(text);

Slide 41

Slide 41 text

To conclude 41

Slide 42

Slide 42 text

My Impressions 42 ● ECMAScript has started accepting proposals for non-browser runtimes ○ It is likely a result of WinterTC's activities ○ Especially for Module Sources, Deno, Node.js, and Igalia are energetically pushing it forward ● Also proposed with consideration for bundlers