Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
require(ESM)とECMAScript仕様
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
uhyo
April 25, 2024
Technology
3.2k
7
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
require(ESM)とECMAScript仕様
Meguro.es #27 @ oRo
uhyo
April 25, 2024
More Decks by uhyo
See All by uhyo
型があると何が嬉しいか
uhyo
2
51
Baseline対応のDOMの型定義を作った
uhyo
3
800
AIのReact習熟度を測る
uhyo
2
880
React、まだ楽しくて草
uhyo
7
4.8k
TypeScript 7.0の現在地と備え方
uhyo
6
3.6k
React 19時代のコンポーネント設計ベストプラクティス
uhyo
20
10k
型定義でAIと会話する:型を通じてAIに意図を伝えるテクニック
uhyo
1
100
タグ付きユニオン型を便利に使うテクニックとその注意点
uhyo
3
1.1k
ECMAScript仕様の最新動向: プロセスの変化と仕様のトレンド
uhyo
3
930
Other Decks in Technology
See All in Technology
データ活用研修 データマネジメント【MIXI 26新卒技術研修】
mixi_engineers
PRO
4
810
PLaMo 3.0 Primeの事後学習
pfn
PRO
0
210
【5分でわかる】セーフィー エンジニア向け会社紹介
safie_recruit
0
53k
テックカンファレンス三大ステークホルダーの文化人類学 ─ 違いを認め合う関係性作り
bash0c7
5
1.3k
AIで楽になるはずが、なぜ疲れる?
kinopeee
0
150
データ活用研修 問いの発見と仮説構築【MIXI 26新卒技術研修】
mixi_engineers
PRO
1
690
書籍セキュアAPIについて
riiimparm
0
390
13年運用タイトルのサーバーサイドが辿り着いた現在地 ― モンスターストライクにおける技術・組織・AI活用から得た知見
mixi_engineers
PRO
1
340
歴史から理解するクラウドインフラのしくみ
kizawa2020
0
190
基調講演:人とAIをつなぐIoTの今と未来 ー 「フィジカル」と「デジタル」が出会うその先へ【SORACOM Discovery 2026】
soracom
PRO
0
360
plamo-3-translateの開発
pfn
PRO
0
220
なぜ、あなたのエージェントは言うことを聞かないのか
segavvy
1
590
Featured
See All Featured
Odyssey Design
rkendrick25
PRO
2
740
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.4k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
510
Prompt Engineering for Job Search
mfonobong
0
390
Producing Creativity
orderedlist
PRO
348
40k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
420
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
160
Balancing Empowerment & Direction
lara
6
1.2k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
240
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
2.2k
How to Ace a Technical Interview
jacobian
281
24k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
470
Transcript
require(ESM)とECMAScript仕様 2024-04-25 Meguro.es #27 @ oRo
発表者紹介 uhyo 株式会社カオナビ フロントエンドエンジニア 普段はTypeScriptとかReactをやっている。 好きな⾔語機能はジェネレータ関数。
JavaScriptの最近のニュース Node.jsが require(ESM) のサポートを追加。 require先がtop-level awaitを含まない ESモジュール (sync ESM) であれば、
CJSファイルからrequireできる。
This Talk require(ESM) って、ECMAScript仕様の視点で ⾒るとどういうことなんだっけ? を解説します
CJSとかESMの復習
ScriptとModule ECMAScript仕様上、JavaScriptプログラムは 2種類に分類される。 •Script: 昔からあるやつ •Module: import/exportが使えるやつ 両者は構⽂レベルで異なる。 (importなどをScriptで使うのは構⽂エラー)
ScriptとModule ScriptかModuleかは外的要因によって決まる (ことが多い) HTML <script> // Scriptとしてパースされる </script> <script type=“module”>
// Moduleとしてパースされる </script> Node.js foo.cjs // Scriptとしてパースされる bar.mjs // Moduleとしてパースされる
ESモジュールグラフ import/exportでつながるモジュールグラフが形成 される。
モジュールの種類 モジュールはJavaScriptファイルとは限らない。 .js .js .mjs .js .js .js .html .json
.wasm .css
モジュールの種類 ECMAScriptでは3種類に分類される。 (下は上の部分クラス) (Abstract) Module Record … 全てのモジュール Cyclic Module
Record … 他のモジュールをimport可能 Source Text Module Record … JavaScriptで書かれた モジュール ※ 厳密に⾔えばAbstract Module Recordも他のモジュールに依存可能だが、ES仕様で扱う依存グラフには表れない
モジュールの種類 .js .js .mjs .js .js .js .html .json .wasm
.css
Node.jsのCJSとESMの関係は? CommonJSのモジュールはECMAScriptモジュー ルではない。ECMAScript側から⾒たらどういう 扱いなのか? .mjs .cjs 特にこうやってESMからCJSをimportする場合
Node.jsのCJSとESMの関係は? 多分CommonJSモジュールはESMから⾒たら Abstract Module Recordに相当する。 .mjs .cjs
モジュールの種類と仕様 (Abstract) Module Record … 全部ホスト依存 Cyclic Module Record …
モジュールグラフの探索周り は仕様で明記 Source Text Module Record … 全部仕様で明記 この仕様により、JS以外のモジュールを扱うことができ る。JS以外のモジュールの挙動は、⼀部または全部が ホスト依存となる。 ※ ESモジュールのホストの例: Node.js、HTML仕様、webpackなど
Node.jsのCJS Abstract Module Recordの挙動は、仕様で 決められた制約を守ればホスト環境の⾃由。 つまり、.cjsから何がexportされるのかとか、 同期的に実⾏されるといった詳細はNode.jsが ⾃由に決められる。 .mjs .cjs
本題
require(ESM)の仕様上の解釈 require(“./module.mjs”)のようにすると、 module.mjsが同期的に実⾏される。 このことをES仕様に沿って記述できるか? ES仕様と⽭盾する処理にはならないのか? が気になる
既存の類例 ⾮モジュールからモジュールを実⾏する機能と して、import()がすでに存在する。 この構⽂であれば、ScriptからでもModuleを 実⾏できる。もちろんNode.jsのCJSからでも。 import(“module”).then(mod => …) “module”をモジュール解決して実⾏し、モジュール名前空間オ ブジェクトに解決されるPromiseを返す
import()の仕様レベルの挙動
import()の仕様レベルの挙動 import(“module”) HostLoadImportedModule … モジュール解決してModule Recordを取得 module.LoadRequestedModules() … 依存モジュール読み込み module.Link()
… Environment Recordを初期化 module.Evaluate() … モジュールグラフに従って実⾏ ざっくりこの4段階でモジュールを実⾏できる。
HTML仕様の例 HTML仕様でも、モジュールを実⾏することはEvaluate()で表現 (LoadRequestedModulesとLinkは別のところで呼んでる)
ES仕様におけるモジュールの実⾏ module.Evaluate()を呼び出すことでモジュールが実 ⾏される。Evaluateには次の制約がある。 •Promiseを返す。モジュールの実⾏が完了すると fulfillする • Evaluateを呼ぶ前にLinkの呼び出しが成功して いる必要がある
ES仕様におけるモジュールの実⾏ module.Link()はモジュールの実⾏の準備をする。 Linkには次の制約がある。 • Linkを呼ぶ前にLoadRequestedModulesの 呼び出しが成功している必要がある
ES仕様におけるモジュールの実⾏ module.LoadRequestedModules()はモジュールの 依存先を全部読み込む。Promiseを返す。 LoadRequestedModulesはホスト定義の HostLoadImportedModuleを利⽤して実際の 読み込みを⾏う。 (HostLoadImportedModule⾃体は同期的にも⾮同期的にも 動作可能と定義されている)
ES仕様におけるモジュールの実⾏ 仕様上の制約として、この順に実⾏する必要がある。 HostLoadImportedModule ↑利⽤ module.LoadRequestedModules() ↑前提 module.Link() ↑前提 module.Evaluate()
ES仕様におけるモジュールの実⾏ require(ESM)の処理をES仕様で記述する場合も制約を守る必要がある。 HostLoadImportedModule ↑利⽤ module.LoadRequestedModules() ↑前提 module.Link() ↑前提 module.Evaluate()
ES仕様におけるモジュールの実⾏ HostLoadImportedModule 同期実⾏可能 ↑利⽤ module.LoadRequestedModules() Promiseを返す ↑前提 module.Link() 同期実⾏ ↑前提
module.Evaluate() Promiseを返す
ES仕様におけるモジュールの実⾏ HostLoadImportedModule 同期実⾏可能 ↑利⽤ module.LoadRequestedModules() Promiseを返す ↑前提 module.Link() 同期実⾏ ↑前提
module.Evaluate() Promiseを返す
Evaluate()の同期実⾏ 実はsync ESMのみをサポートする前例が Service Workerに存在する。 モジュールをService Workerとして登録する場合、 TLAを含むモジュールを登録することはできない。
Service Workerの仕様を⾒る 登録されたモジュールを実⾏するところの仕様
Service Workerの仕様を⾒る module.Evaluate()の結果のPromise 最初から解決済
Sync ESMのEvaluate() 実はES仕様では、TLAを持たないSource Text Module RecordのEvaluate()は、最初から 解決済みのPromiseを返すことが保証されている。 (=TLAを含まないモジュールグラフは仕様上同期的に 実⾏できる) Evaluate()が返したPromiseをもらった瞬間に
捨てればOK。
ES仕様におけるモジュールの実⾏ HostLoadImportedModule 同期実⾏可能 ↑利⽤ module.LoadRequestedModules() Promiseを返す ↑前提 module.Link() 同期実⾏ ↑前提
module.Evaluate() Promiseを返す
LoadRequestedModules()の定義を⾒る
ES仕様におけるモジュールの実⾏ 詳細は省くが、HostLoadImportedModule()が同期的に動く 環境であれば、 LoadRequestedModules()が返すPromiseも 最初から解決されている。 こちらも同期的に実⾏可能。 (返ってきたPromiseはやはり捨てる)
補⾜: エラー処理について どちらも返ってきたPromiseを捨てることで同期的に 処理可能だが、エラーの場合の対応は必要。 そこは処理系特権でPromiseの中⾝を同期的に確認し、 エラー処理を⾏う。
まとめ
まとめ Node.jsが新たに実装したrequire(ESM)は、 実装されてもECMAScript仕様とは⽭盾しないことが 分かった。 (仕様上Promiseの中⾝を同期的に⾒るというずるが必要になるが、 多分実装でカバーできる) 安⼼して使おう!