Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Upcoming SlideShare
What to Upload to SlideShare
Next
Download to read offline and view in fullscreen.

Share

Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜

Download to read offline

2021/02/25(木) Node学園 35時限目の発表資料
https://nodejs.connpass.com/event/203464/

Node.js の ES Modules 対応について

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜

  1. 1. Na#ve ESM への道 ∼ 最終章: Babel / TypeScript Modules との闘い ∼ Node 学園 35 時限目 / 2021-02-24 @teppeis 1
  2. 2. 自己紹介 • @teppeis / Teppei Sato • サイボウズから来ました。 • もちろん We are hiring!!! • プロダクト開発チーム • フロントエンドエキスパートチーム 2
  3. 3. Node.js の ES Modules 対応って どうなったの? 3
  4. 4. 前回までのあらすじ 2015 年の ES Modules (ESM) 策定からときは流れ、Node.js での ESM 対応は混迷を極めた1 。 しかし 2018 年 10 月、 Node.js Modules Team は ESM 対応計画 2 を なんとかまとめあげ、ようやく実装が進んでいった。 そして 2020 年末にはその計画が実装完了し、2021 年は Na8ve ESM 時代が到来するかに見えた。 2 Plan for New Modules Implementa5on · nodejs/modules 1 前回スライドを参照: You Don't Know ES Modules, Teppei Sato (2016) 4
  5. 5. Node.js ESM 実装状況 基本機能は Node v12.20+, v14.13+ で フラグ無し で提供済み3 • Na$ve ESM import / export • CommonJS interoperability (CJS Interop) • package.json imports / exports mapping 3 ESM import / export と CJS interop は v15 系で stability: stable, v12, v14 系は次の minor リリースで stable になる 予定。imports / exports mapping は v15 系で stable になったが v12, v14 は未定。 5
  6. 6. 2021 年は Na've ESM の時代に? • 前述の通り、Node v12 系以上は ESM を実装済み • Node v10 は 2021-04-30 に EOL • つまり、5 月以降は全 Node 環境で Na5ve ESM が利用可能! • やったー、全部 ESM で書こうぜー 6
  7. 7. h"ps:/ /blog.sindresorhus.com/get-ready-for-esm-aa53530b3f77 7
  8. 8. h"ps:/ /twi"er.com/jus2nfagnani/status/1356012934564958212 8
  9. 9. そんな風に思っていた時期が 私にもありました。 9
  10. 10. 鬼門: CJS Interop 10
  11. 11. CJS Interop CJS から ESM へスムーズな移行を進めるために検討されてきた相 互互換機能 • CJS から ESM をロードできる • ESM から CJS をロードできる 仕様の複雑さと既存パッケージとの互換性から、ここまで Node の ESM 対応を遅らせてきた鬼門でもある 11
  12. 12. import ESM from CJS // esm.mjs export default "foo"; export const named = "bar"; // cjs.js const { default: def, named } = await import("./esm.mjs"); //// def: "foo" //// named: "bar" • dynamic import を使用 • ESM と同じ使い勝手で、違和感はない 12
  13. 13. import CJS from ESM: named import // cjs.js exports.named = "foo"; // esm.mjs import { named } from "./cjs.js"; //// named: "foo" • exports のプロパティが named import される 13
  14. 14. import CJS from ESM: default import // cjs.js module.exports = "foo"; // esm.mjs import cjs from "./cjs.js"; //// cjs: "foo" • module.exports が default import される 14
  15. 15. ところで Babel と TypeScript はどうだっけ? 15
  16. 16. Babel / TypeScript の ESM → CJS 変換 // Before (ESM in Babel) export default "foo"; // After (CJS) Object.defineProperty(exports, "__esModule", { value: true }); exports.default = "foo"; • default export は、exports.default に変換される • おや?Node.js の CJS Interop と仕様が違うぞ! 16
  17. 17. Babel / TypeScript で CJS にトランスパイルされた npm パッケージを Na5ve ESM からロードしたいけど // node_modules/foo/index.ts export default "foo!"; // main.mjs import foo from "foo"; //// foo: { default: "foo!" } default export された値を 期待通りに default import できない! 17
  18. 18. 無理矢理書くこともできるが // node_modules/foo/index.ts export default "foo!"; // main.mjs import def from "foo"; const { foo } = def; //// foo: "foo!" これなら動くが、import したい全ての npm パッケージについて内 部的に Babel / TS を使っているかを調べて書き分ける必要があり、 書き味も体験も非常に厳しい。 18
  19. 19. Babel Modules ≠ ES Modules TypeScript Modules ≠ ES Modules 19
  20. 20. ここまでは Babel / TypeScript ベースの CJS な npm パッケージを Na5ve ESM からロードする話 20
  21. 21. TypeScript で Na-ve ESM を書くのは もっと厳しい 21
  22. 22. TypeScript で Na-ve ESM を出力したい 公式にはサポートされてないので基本的に厳しい • .mjs を出力できない • .mjs を入力できない • moduleResolution:node が Node の ESM 仕様と異なる • imports / exports mapping に未対応 22
  23. 23. TypeScript で無理矢理書くこともできるが // foo.ts export default "foo!"; // main.ts import foo from "./foo.js"; import 文で拡張子を省略せず .js を指定し(.ts ではない)、 pacakge.json で type:"module" にすることで、変換後に Na$ve ESM として無理矢理動かすことは可能。 しかし ts-node など周辺ツールが未対応で jest も動かせない。 23
  24. 24. TypeScript Modules を import 不可能 // node_modules/foo/index.ts export default "foo!"; // main.ts import def from "foo"; const { foo } = def; //// TS2339 Error: Property 'foo' does not exist on type 'String'. TS が CJS に変換したパッケージに同梱された型定義が Node ESM 仕様と食い違うため、TS Na-ve ESM から default import しようと すると 型エラーかランタイムエラーのどちらか になる。 24
  25. 25. 今後どうなるのか? 25
  26. 26. Babel / TypScript 陣営の動き • Babel は新オプション importInterop:"node" を検討している4 • TypeScript は最近の動きは見えない • 2020 年 3 月に新しい moduleResolution フラグを作る方針 というコメント5 があったが、続報なし 5 Design Mee*ng Notes, 3/27/2020 · Issue #37897 · microso=/TypeScript 4 Implement importInterop: "node" op+on for module transforms by nicolo-ribaudo · Pull Request #12838 · babel/babel 26
  27. 27. Babel / TypeScript が対応しても • 既に npm 公開された大量の Babel / TS Modules はトランスパイ ル済みであり、挙動は変わらない • 更新のない Babel / TS Modules は Na4ve ESM からは扱いにく い存在として残り続ける • npm 界に ESM 対応のアップデートが広がるのを待つしかない • 時間が解決するのか... 27
  28. 28. Sindre はどうしてるの? そんなこともあろうかと、既存の TypeScript ベースの npm パッケージにあら かじめ workaround を仕込んでいた!6 export default got; module.exports = got; module.exports.default = got; module.exports.__esModule = true; これで TypeScript からも Na-ve ESM からも default import 可能。 ただし dirty hack で副作用もあるのでご利用は計画的に。 6 h$ps:/ /github.com/sindresorhus/got/blob/v11.8.1/source/index.ts#L127-L130 28
  29. 29. ところで、 どうして Na$ve ESM を書きたいんだっけ? • 皮肉にも、CJS Interop の実装が進んだ結果、CJS でも特に不満 がない状況になりつつある • ESM のセールスポイントだった tree-shaking も、静的解析の発 展により Webpack や Parcel が CJS にも対応し始めた • それでも ESM を書くと キマる んだ! 29
  30. 30. まとめ • Na$ve ESM は Node.js の中だけなら 5 月から自由に使える • しかし Babel / TypeScript ベースの npm パッケージを default import すると いろいろハマって厳しい • この状況は各種ツールと既存 npm パッケージが更新されるまでだいぶ続き そう • TypeScript で Na$ve ESM が書けるようになるのはまだまだ先 • しばらくは TypeScript で CJS を書く今の生活が続きそう 30
  • zuisener

    Sep. 9, 2021
  • MasaharuTASHIRO

    May. 29, 2021
  • maemichiyuya

    Mar. 10, 2021
  • hkoba

    Feb. 27, 2021
  • syuichitsuji

    Feb. 26, 2021

2021/02/25(木) Node学園 35時限目の発表資料 https://nodejs.connpass.com/event/203464/ Node.js の ES Modules 対応について

Views

Total views

12,602

On Slideshare

0

From embeds

0

Number of embeds

3,191

Actions

Downloads

4

Shares

0

Comments

0

Likes

5

×