Node.js Dual Package の対応をしたつもりができてなかった
原因は aws-kms-provider
の package.json
に "type": "module"
を書いていなかったから
"type": "module"
を書けば解決する、と思いきやそんな簡単な問題ではない
ライブラリ内でモジュールを import するときに拡張子を明示しないと ERR_MODULE_NOT_FOUND
が発生してしまう
javascript - Error [ERR_MODULE_NOT_FOUND]: Cannot find module - Stack Overflow
この問題に対して ky はどうしているかというと、ts ファイルで import するときに ./hoge.js
という形で import していた
ただこれは https://zenn.dev/teppeis/articles/2021-10-typescript-45-esm#識別子周りの議論 で紹介されているように、抵抗がある...
unplugin は tsup を使用してモジュールをバンドルすることによって、import の拡張子気持ち悪い問題を解決しているっぽい
最近だと unbuild もありなのかなあ
unjs 的には siroc との棲み分けをどうしているんだろう
そもそも手で tsc するのは色々つらいしこれを気に止めたい
対応は Publish ESM and CJS in a single package が参考になりそう
試してみてるけど、unbuild より tsup のほうが良さそう
unbuild はドキュメンテーションが追いついていないみたいなので、config のオプションの意味を確認するにはソースコードを読みに行くしかなくてつらい
tsup はよしなにドキュメントがあるので嬉しい
多分同じようなツールだと思うので、tsup を使う、で良さそう
拡張子問題、わかりやすい
ESM の問題点
方針
- 既存パッケージは tsup で bundle して、esm/cjs の両方に対応する
- 新規パッケージは import 時に
.js
を明記して Pure ESM として実装する
早速、tsup で bundle して動作確認したところ、次のエラーが出た
file:///Users/odan/source/github.com/odan-sandbox/aws-kms-provider-syntax-error-sandbox/node_modules/aws-kms-signer/dist/index.mjs:6
throw new Error('Dynamic require of "' + x + '" is not supported');
^
Error: Dynamic require of "keccak" is not supported
at file:///Users/odan/source/github.com/odan-sandbox/aws-kms-provider-syntax-error-sandbox/node_modules/aws-kms-signer/dist/index.mjs:6:9
at file:///Users/odan/source/github.com/odan-sandbox/aws-kms-provider-syntax-error-sandbox/node_modules/aws-kms-signer/dist/index.mjs:44:25
at ModuleJob.run (node:internal/modules/esm/module_job:195:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:337:24)
at async loadESM (node:internal/process/esm_loader:88:5)
at async handleMainPromise (node:internal/modules/run_main:61:12)
原因は https://github.com/odanado/aws-kms-provider/blob/3d732fd79a85d182efa3879825ea3f93f6971114/packages/aws-kms-signer/src/crypto.ts#L4 で require しているせいだった
keccak
を require しているけど、それを使っている hash 関数はどこからも参照されてなかったので require ごと消して対応した
次は aws-kms-provider の対応を行ったら次のエラーが出た
node:internal/process/esm_loader:94
internalBinding('errors').triggerUncaughtException(
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/odan/source/github.com/odan-sandbox/aws-kms-provider-syntax-error-sandbox/node_modules/web3-provider-engine/subproviders/hooked-wallet' imported from /Users/odan/source/github.com/odan-sandbox/aws-kms-provider-syntax-error-sandbox/node_modules/aws-kms-provider/dist/index.mjs
Did you mean to import web3-provider-engine/subproviders/hooked-wallet.js?
at new NodeError (node:internal/errors:371:5)
at finalizeResolution (node:internal/modules/esm/resolve:394:11)
at moduleResolve (node:internal/modules/esm/resolve:944:10)
at defaultResolve (node:internal/modules/esm/resolve:1041:11)
at ESMLoader.resolve (node:internal/modules/esm/loader:530:30)
at ESMLoader.getModuleJob (node:internal/modules/esm/loader:251:18)
at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:79:40)
at link (node:internal/modules/esm/module_job:78:36) {
code: 'ERR_MODULE_NOT_FOUND'
}
これはどうしようもなさそうなので、元々の ts のコードで .js
をつけて import するように修正した
file:///Users/odan/source/github.com/odan-sandbox/aws-kms-provider-syntax-error-sandbox/node_modules/aws-kms-provider/dist/index.js:8
import { KmsSigner } from "aws-kms-signer";
^^^^^^^^^
SyntaxError: Named export 'KmsSigner' not found. The requested module 'aws-kms-signer' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from 'aws-kms-signer';
const { KmsSigner } = pkg;
at ModuleJob._instantiate (node:internal/modules/esm/module_job:127:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:191:5)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:337:24)
at async loadESM (node:internal/process/esm_loader:88:5)
at async handleMainPromise (node:internal/modules/run_main:61:12)
Node.js v17.4.0
これは aws-kms-ethers-signer
が依存に持っている aws-kms-signer
が npm にアップロードされているものだったためにエラーになっている
yarn resolutions でローカルの aws-kms-signer
を向くようにしたら解決した
最終的に tsup を使用した方法で cjs/esm 両方に対応して解決した