Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
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.3k
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
Reactの設計論
uhyo
24
14k
型があると何が嬉しいか
uhyo
3
140
Baseline対応のDOMの型定義を作った
uhyo
3
950
AIのReact習熟度を測る
uhyo
2
1k
React、まだ楽しくて草
uhyo
7
5k
TypeScript 7.0の現在地と備え方
uhyo
6
3.8k
React 19時代のコンポーネント設計ベストプラクティス
uhyo
20
11k
型定義でAIと会話する:型を通じてAIに意図を伝えるテクニック
uhyo
1
120
タグ付きユニオン型を便利に使うテクニックとその注意点
uhyo
3
1.2k
Other Decks in Technology
See All in Technology
AgentCore Runtime上にAgentic Coding基盤を構築・展開する際の設計ポイントと限界点 / Design considerations and limitations when building an agentic coding platform on AgentCore Runtime
har1101
5
480
山手線を徒歩で一周してわかった、 位置情報アプリは「足」が最強のデバッガー
hinakko
0
170
CLIライブラリ開発を支える技術
htnabe
0
140
あけおめLINE 傾向とその対策
nasa9084
0
180
絵ではじめるKubernetesセキュリティ
aoi1
4
690
AIエージェントの一手は 誰も見ていない - Falco拡張OSS「Prempti」とeBPFで サーバーレス実行基盤を二層防御する
keitah
0
320
フルカイテン株式会社 エンジニア向け採用資料
fullkaiten
0
12k
SREの視点で考えるSIEM活用術 〜AWS環境でのセキュリティ強化〜
cscengineer
PRO
0
130
おい、エージェントを使って終わらせろ
nwiizo
2
760
映像変換サーバーなしで端末内でHLSを生成してライブ配信
hikarusato
0
130
開発投資の期待値を上げるプロダクトロードマップづくり ~プロダクトエンジニアが越境して事業を伸ばす~
kekekenta
1
230
アプリをもっと"iOSアプリっぽく"する小さな工夫 / Small Touches That Make Your App Feel More Like an iOS App
matsuji
2
970
Featured
See All Featured
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
540
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
700
Abbi's Birthday
coloredviolet
4
10k
The Cult of Friendly URLs
andyhume
79
7k
Writing Fast Ruby
sferik
630
63k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
870
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
470
Designing for Timeless Needs
cassininazir
1
480
Are puppies a ranking factor?
jonoalderson
2
3.9k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
1
410
Being A Developer After 40
akosma
91
590k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
550
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の中⾝を同期的に⾒るというずるが必要になるが、 多分実装でカバーできる) 安⼼して使おう!