-
Notifications
You must be signed in to change notification settings - Fork 12
fix(build): inject createRequire banner to support CJS deps in ESM bundles #166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,4 +34,16 @@ export default defineConfig({ | |
| // runtime, so every npm dependency (AWS SDK, @actions/core, @octokit/…) must | ||
| // be bundled in. Node.js built-ins stay external automatically (platform:'node'). | ||
| noExternal: [/.*/], | ||
| // CJS packages bundled into ESM (e.g. tunnel@0.0.6 via @actions/http-client) | ||
| // call require('net') / require('tls') at runtime. esbuild's __require shim | ||
| // checks `typeof require !== "undefined"` — which is false in pure ESM — and | ||
| // throws "Dynamic require of 'net' is not supported". Injecting createRequire | ||
| // as a top-level banner supplies a real require() before the shim runs, | ||
| // so those CJS modules can load Node.js built-ins normally. | ||
| // NOTE: this banner uses import/import.meta.url — only valid in ESM output. | ||
| // If format is ever extended to include 'cjs', this must be conditioned or | ||
| // moved to a format-specific banner ({ esm: '...' }) to avoid a parse error. | ||
| banner: { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [LOW] Banner uses ESM-only syntax — will silently break if The injected banner contains an If a future maintainer extends // NOTE: this banner uses import/import.meta.url — only valid in ESM.
// If format is ever extended to include 'cjs', this must be conditioned
// or moved to a format-specific banner (banner: { esm: '...' }).
banner: {
js: "import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);",
},Not a current bug; just a maintenance note.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done — the three-line ESM-only warning comment has been added directly above the |
||
| js: "import { createRequire } from 'node:module'; var require = createRequire(import.meta.url);", | ||
| }, | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[LOW] Module-scoped
requirein security-sensitive bundle — acknowledgedconst require = createRequire(import.meta.url)introduces a workingrequire()into the module scope of every output bundle. In pure ESM without this banner, norequireexists at all.A few things are worth being aware of (not blockers):
requireis module-scoped, not global —globalThis.requirestaysundefined, so only code already executing inside the bundle can call it.require()calls in bundled deps route through esbuild's__requireshim (which delegates to thisrequire), so the exposure is bounded to the bundle's existing dependency graph.tunnel,@actions/core, AWS SDK) are known to pass user-controlled input torequire()— but the action handles API keys and signed commits, so it's worth keeping in mind if new CJS dependencies are added.Empirically confirmed to not cause issues in any current code path. ✅