Skip to content

fix: name build outputs after the exports map paths - #243

Open
unrevised6419 wants to merge 1 commit into
strapi:mainfrom
unrevised6419:fix/output-file-names-from-exports
Open

unrevised6419 wants to merge 1 commit into
strapi:mainfrom
unrevised6419:fix/output-file-names-from-exports

Conversation

@unrevised6419

Copy link
Copy Markdown
Contributor

What does it do?

Writes each build output to the path its exports condition points at, instead of always writing index.mjs (ESM) and index.js (CommonJS).

  • createViteConfig takes the output file names from bundle.output.esm / bundle.output.cjs (the import / require paths), relative to the output directory. build and watch both use it, so both behave the same.
  • ./strapi-admin and ./strapi-server now need only one of import or require, not both. ESM-only and CJS-only plugins can now be built. verify already allowed this.
  • build warns when an extension makes Node load a file in the wrong module format: require → .js in a "type": "module" package, or import → .js in a package that isn't "type": "module". It's a warning, not an error, so existing builds keep working.
  • If import and require point to different directories, the build now fails with a clear error. Before, it silently wrote both files into the require directory. Supporting split directories would need a separate Vite build per format, because emptyOutDir must not clear a shared parent such as dist.

init still writes "type": "commonjs" with index.mjs / index.js, which stays correct. Plugins that follow that layout get exactly the same files as before.

Why is it needed?

"type": "module" plugins can't be built correctly today. CommonJS always lands in index.js, which Node loads as ESM in such a package, so Strapi fails at boot with exports is not defined in ES module scope. A require: ./dist/server/index.cjs path is never written, and ESM-only plugins are rejected by validation (exports["./strapi-server"].require is a required field). Details and repro are in #242.

How to test it?

pnpm check covers it. New tests:

  • src/__tests__/e2e/build.test.ts
    • a "type": "module" plugin with import: ./dist/server/index.js and require: ./dist/server/index.cjs builds exactly index.cjs and index.js, and a child Node process loads both, through require and import;
    • the .js CommonJS warning is logged for a "type": "module" package;
    • an ESM-only plugin builds only dist/server/index.js, and it loads through import.
  • src/__tests__/e2e/verify.test.ts: verify passes for the built ESM-only plugin.
  • New fixtures: esm-type-plugin, esm-only-plugin.

Without the source changes, 5 of the new tests fail. Existing tests are unchanged and pass.

Related issue(s)/PR(s)

Closes #242

Related: #241 (type declarations have the same one-file-for-both-formats problem; not addressed here). It touches the same files as #239 (--bundle). Whichever merges second needs a small rebase: #239 renames BundleConfig.type to name, and the new messages here use bundle.type.

🤖 Generated with Claude Code

The build only used the `import` / `require` paths to choose the output
directory and always wrote `index.mjs` and `index.js`. In a
`"type": "module"` plugin the CommonJS output then landed in a `.js` file
that Node loads as ESM, and a `.cjs` require path was never written.

Each output file is now written to the path its exports condition points
at. `./strapi-admin` and `./strapi-server` need only one of `import` or
`require`, which allows ESM-only plugins. The build warns when an
extension makes Node load a file in the wrong module format.

Closes strapi#242

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Oct 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 24659d4

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@strapi/sdk-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@sonarqubecloud

sonarqubecloud Bot commented Oct 2, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug]: build ignores exports file names and package.json#type, breaking "type": "module" plugins

1 participant