esbuild に CJS として import してほしいのに ESM として import されちゃうときのプラグイン
import 文を書くと esbuild は該当パッケージを ESM として読みに行く。
どういうことかというと、import 先のパッケージが Conditional Exports でこんな風に書いてる場合、./foo.mjs
をバンドルする。
{
"exports": {
"import": "./foo.mjs",
"require": "./bar.js"
}
}
基本的にこれは望ましい挙動なんだけど、場合によってはうまくバンドルできなかったりする。
たとえば、foo.mjs
がこんな感じのとき。実装の実態は bar.js
にあるんだけど createRequire
を使って foo.mjs
が ESM の口になってるような感じ。
imprt module from "node:module";
const require = module.createRequire(import.meta.url);
const bar = require("./bar.js");
export { bar };
こういうのを esbuild でバンドルすると imoport.meta.url
は空オブジェクトになるし、それを解決したとしても createRequire
で作った require
で読み込んだモジュールはそもそもバンドルされない。
なので指定したモジュールを ESM ではなく CJS として読みに行くようにするプラグインがあると便利なのかもしれない。
require
の方のモジュール解決のアルゴリズムに乗っかるので CJS の方を読みに行く。
import path from 'node:path';
import module from 'node:module';
const require = module.createRequire(import.meta.url);
/**
* @param {Array<string>} specifiers
* @returns {import('esbuild').Plugin}
*/
function resolveCjsPlugin(specifiers) {
const filter = new RegExp(specifiers.join('|'));
return {
name: 'resolveCjs',
setup(build) {
build.onResolve({ filter }, (args) => {
return {
path: path.join(require.resolve(args.path)),
};
});
},
};
}
export default resolveCjsPlugin;
本当はこんなことしたくない...
Author And Source
この問題について(esbuild に CJS として import してほしいのに ESM として import されちゃうときのプラグイン), 我々は、より多くの情報をここで見つけました https://zenn.dev/sosukesuzuki/articles/d8220ba2d869f0著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol