Dynamic require of "os" is not supported
Dynamic require of "fs" is not supported
Dynamic require of "path" is not supported
-
Comment Answer by user @ctjlewis on evan/esbuild pull request titled "Rewrite require() calls of Node built-ins to import statements when emitting ESM for Node#2067": link to comment evanw/esbuild#2067 (comment)
-
Similar answer, that doesn't check for the existance of the methods before creating them is provided by @guushamann on evanw/esbuild#1921 (comment)
Approach by @ctjlewis
See the BuildOptions
below:
const ESM_REQUIRE_SHIM = `
await (async () => {
const { dirname } = await import("path");
const { fileURLToPath } = await import("url");
/**
* Shim entry-point related paths.
*/
if (typeof globalThis.__filename === "undefined") {
globalThis.__filename = fileURLToPath(import.meta.url);
}
if (typeof globalThis.__dirname === "undefined") {
globalThis.__dirname = dirname(globalThis.__filename);
}
/**
* Shim require if needed.
*/
if (typeof globalThis.require === "undefined") {
const { default: module } = await import("module");
globalThis.require = module.createRequire(import.meta.url);
}
})();
`;
/** Whether or not you're bundling. */
const bundle = true;
/** Tell esbuild to add the shim to emitted JS. */
const shimBanner = {
"js": ESM_REQUIRE_SHIM
};
/**
* ESNext + ESM, bundle: true, and require() shim in banner.
*/
const buildOptions: BuildOptions = {
...common,
format: "esm",
target: "esnext",
platform: "node",
banner: bundle ? shimBanner : undefined,
bundle,
};
esbuild(buildOptions);
For a minified version of the shim, you can use the following (in general, you should not add minified code to the top of your bundle contexts because a stranger on GitHub tells you to, but feel free to verify it):
const ESM_REQUIRE_SHIM = `
await(async()=>{let{dirname:e}=await import("path"),{fileURLToPath:i}=await import("url");if(typeof globalThis.__filename>"u"&&(globalThis.__filename=i(import.meta.url)),typeof globalThis.__dirname>"u"&&(globalThis.__dirname=e(globalThis.__filename)),typeof globalThis.require>"u"){let{default:a}=await import("module");globalThis.require=a.createRequire(import.meta.url)}})();
`;
The end result of these build options are a single ESM bundle with all non-builtin modules inlined, and a global require() shimmed for any CJS imports that are left in the bundle (e.g. builtins like events).
If your program depends on esbuild
, you will need to add it to your externs, i.e. { external: ["esnext"] }
.
Additional solution whenesbuild is running via nx using package @nx/esbuild
Comment answer by user @valclarkop on evan/esbuild How to fix "Dynamic require of "os" is not supported"#1921
File: project.json
{
"targets":{
"build":{
"executor":"@nx/esbuild:esbuild",
"esbuildOptions":{
"legalComments":"inline",
"banner":{
"js":"const require = (await import('node:module')).createRequire(import.meta.url);const __filename = (await import('node:url')).fileURLToPath(import.meta.url);const __dirname = (await import('node:path')).dirname(__filename);"
}
}
}
}
}
For sveltjs you can use this SHIM but, you also need to use this
sveltjs
pull request to be able to pass build options through to esbuild sveltejs/kit#9398