Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ESM移行は無理だけどおれもSindreのライブラリが使いたい!

 ESM移行は無理だけどおれもSindreのライブラリが使いたい!

依存しているライブラリが ESM only になってしまうことがあると思います。
そんなとき、自分たちが CommonJS だと素直に使えなくて困りますよね。
そこで、なんとかしてCommonJS環境から ESM only のパッケージをrequireする方法をご紹介します。推奨はしません。

208355d7af69fa84a78048f78077048a?s=128

sosukesuzuki

August 03, 2022
Tweet

More Decks by sosukesuzuki

Other Decks in Programming

Transcript

  1. ESM移行は無理だけどおれも Sindreのライブラリが使いたい! ワインと鍋.js

  2. About me • @__sosukesuzuki • Ubie ( ユビー ) •

    Prettier • Babel • 筑波大学 (B3?B4)
  3. 前提 • Prettierの話です ◦ CommonJS で書かれてる ◦ Node.js でソースコードをそのまま実行できる必要がある ◦

    配布するときはガッツリバンドルする • この方法を推奨するものではありません
  4. 2021年、世はECMAScript Modules時代に突入(?) • 2021年4月Node.js 10がEoLを迎えた • パッケージメンテナーはNode.js 10のサポートを終了し、Node.js 12以降のみをサポートするようになる •

    Node.js 12はECMAScript Modulesを完全にサポートするバージョンである • これはつまり、世はECMAScript Modules時代!!(?)
  5. 少なくともSindre SorhusはESM時代に突入! • 多くのNode.js用ライブラリの作者・メンテナーとして知られる Sindre SorhusはESMを強く推している ◦ ky, got, execa,

    tempy, chalk, type-fest, mem, etc… ◦ 自身のライブラリを続々と ESMへ移行したり、そのためのガイドを書いたりしている • ESMのみをサポートするライブラリを使うためには、基本的には使う側も ESMに移行する必要がある • 彼のライブラリに依存せずに自分のライブラリをメンテナンスするのはなかなか難しい • 多くのライブラリメンテナーも (自動的に)ESM時代に片足突っ込んでしまった! • ちなみに、unified とか remark の作者の wooorm も ESM 派
  6. 少なくともSindre SorhusはESM時代に突入! https://medium.com/sindre-sorhus/get-ready-for-esm-aa53530b3f77

  7. すぐにESM移行をするのはキツイ! • ECMAScript Modulesに移行することはややめんどい ◦ 全部書き換える必要がある、コードがでかいとめんどい ◦ dynamic require をそのまま

    dynamic import に置き換えることはできない (Promise) ◦ パッケージの配布方法やビルドスクリプトを変更する必要があるかもしれない ◦ 短期的なメリットはほとんどない ▪ 別にCommonJSでも動く ▪ Sindre のライブラリが使えなくても死なない • メジャーアップデートをする必要がある ◦ 色々予定や覚悟がね ...
  8. 残された選択肢 • Sindre SorhusライブラリについてはCommonJSをサポートする最後のバージョンを使い続ける • Sindre Sorhusライブラリと同じような機能を持つライブラリを自作する or 探す •

    重い腰をあげてECMAScript Modules移行を決行する
  9. 残された選択肢 • Sindre SorhusライブラリについてはCommonJSをサポートする最後のバージョンを使い続ける • Sindre Sorhusライブラリと同じような機能を持つライブラリを自作する or 探す •

    重い腰をあげてECMAScript Modules移行を決行する • 気合でCommonJSからESMパッケージを使う
  10. 気合でCommonJSからESMパッケージを使う • CommonJSからESMパッケージをrequireすることはできない ◦ dynamic importすればできるけど、全部 Promiseになるのでやりたくない • なので、ESMパッケージをCommonJSにしてしまおう

  11. ESMパッケージをCommonJSにする • あらかじめESMパッケージのリストを用意しておく ◦ https://github.com/prettier/prettier/blob/main/scripts/vendors/vendors.mjs ◦ const vendors = [“chalk”,

    /* その他 */, “tempy”]; • vendorsを全部esbuildでCJSに変換する! ◦ esbuild速すぎる ◦ require.resolve(vendor)を entry point にしてCommonJSファイルへとバンドルする • ./vensors にCJSファイルを置く ◦ ついでの型定義ファイルも (存在すれば)いい感じに生成しておく • (ライセンス情報を残しておく )
  12. ESMパッケージをCommonJSにする • というようなことをやってくれるスクリプトを書く ◦ https://github.com/prettier/prettier/tree/main/scripts/vendors ◦ npm scripts に vendors:bundle

    として登録してある
  13. ESMパッケージをCommonJSにする ./node_modules chalk (ESM) execa (ESM) got (ESM) ./vendros chalk

    (CJS) execa (CJS) got (CJS) esbuild
  14. ESMパッケージをCommonJSにする • ./vendors の中身はこんな感じ ◦ パッケージ名.js と パッケージ名.d.ts が並んでる

  15. ESMパッケージをCommonJSにする • depandabotとかで勝手にpackage.jsonのバージョンが更新されると node_modulesとvendorsでバージョ ンの整合性がとれないことがある • そういのはGitHub Actionsではじいてる ◦ -

    run: yarn run vendors:bundle && echo "Listing changed files:" && git diff --name-only --exit-code && echo "No files changed." • GitHub Actionsが落ちたら、メンテナーの手作業で yarn verndors:bundle の結果を追 push する
  16. この方法のダメな点 • 謎のレイヤーが挟まってデバッグしにくい • 謎のレイヤー自体のメンテコストがある • ESMパッケージを全部CJSにバンドルしてしまうのでTree Shakingとかない ◦ https://sosukesuzuki.dev/posts/how-to-reduce-prettier-size/

    で紹介したような手作業 Tree Shakingでサイズを 落とすしかない • 標準の仕組みに乗っかれないのは嫌な気持ちになる • ビルド職人みたいな人がいないと厳しそう
  17. やめよう!! • Prettier v3 ではコードベースのECMAScript Modules移行が行われるのでこの仕組みともおさらばでき る ◦ prettier/prettier/package.json の

    type は module ◦ prettier/prettier/dist/package.json の type は commonjs • うれしいね • 2022年9月にリリースしたい気持ちでいっぱいです