Skip to content

fix(app-tools): stop writing the ESM loader files twice - #8819

Merged
keepview merged 1 commit into
mainfrom
fix/app-tools-esm-loader-copy-race
Aug 25, 2026
Merged

fix(app-tools): stop writing the ESM loader files twice#8819
keepview merged 1 commit into
mainfrom
fix/app-tools-esm-loader-copy-race

Conversation

@keepview

Copy link
Copy Markdown
Contributor

Summary

src/esm is matched by the ./src/** entry, so the bundler emits those files itself. It also sits in output.copy, and in the ESM outputs both land on the same .mjs paths — two writers for one file. When the writes interleave the file is left truncated.

bin/modern.js loads dist/esm-node for any project with "type": "module", so a corrupt loader takes the whole project down at startup:

SyntaxError: Unexpected token '}'
    at compileSourceTextModule (node:internal/modules/esm/utils)

Evidence

Windows CI had been red since Aug 13. Every failing fixture was "type": "module"; every passing one was CommonJS — including tailwind v2/v3 passing in the same suite where v4 failed. Parsing the published ESM build during a failing run named the files:

dist/esm-node/esm/register-esm.mjs   does not parse: Unexpected token '}'
dist/esm-node/esm/ts-node-loader.mjs does not parse: Unexpected token ','
parsed 566 framework .mjs file(s), 2 unparsable

The CJS output emits .js, so nothing collides there — which is why CommonJS projects were never affected.

Fix

Keep the copy only for the CJS output, where it is the sole source of the .mjs loaders register() resolves by name. Removing it entirely breaks CJS; excluding src/esm from the entry breaks CJS too, because dist/cjs/utils/register.js imports ../esm/register-esm.js, which only exists as a bundled entry.

Rebuilding with this change produces a byte-identical dist (diff -rq before/after: 0 differences), so the duplicate write was the only thing removed.

The deploy templates are already excluded from the entry for exactly this reason; src/esm was missed.

Verification

Windows integration tests on this fix (plus #8816 for an unrelated test-side failure): 87 passed | 4 skipped, 0 failedSyntaxError, compileSourceTextModule and ERR_CONNECTION_REFUSED all gone.

Note this is not test-only: these files ship inside the npm package, and a release build runs the same racy config. @modern-js/app-tools@3.8.2 on the registry is currently clean (all 100 esm-node .mjs parse), but a release that loses the race would publish a broken loader and break every "type": "module" user project at startup.

Co-Authored-By: Riff

`src/esm` is matched by the `./src/**` entry, so the bundler emits those
files itself. It also sits in `output.copy`, and in the ESM outputs both land
on the same `.mjs` paths — two writers for one file. When the writes
interleave the file is left truncated, and since `bin/modern.js` loads
`dist/esm-node` for any project with `"type": "module"`, a corrupt loader
takes the whole project down at startup:

    SyntaxError: Unexpected token '}'
        at compileSourceTextModule (node:internal/modules/esm/utils)

Windows CI hit exactly that, with dist/esm-node/esm/register-esm.mjs and
ts-node-loader.mjs unparsable while the CommonJS fixtures were unaffected —
the CJS output emits `.js`, so nothing collides there.

Keep the copy only for the CJS output, which is where it is the sole source
of the `.mjs` loaders `register()` resolves by name. Rebuilding with this
change produces a byte-identical dist, so the duplicate write was the only
thing removed.

The deploy templates are already excluded from the entry for the same reason.

Co-Authored-By: Riff
@netlify

netlify Bot commented Aug 24, 2026

Copy link
Copy Markdown

Deploy Preview for modernjs-byted ready!

Name Link
🔨 Latest commit 4556fdb
🔍 Latest deploy log https://app.netlify.com/projects/modernjs-byted/deploys/6a8c870e2fc4e70007a99ffa
😎 Deploy Preview https://deploy-preview-8819--modernjs-byted.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 99 (🟢 up 3 from production)
Accessibility: 100 (no change from production)
Best Practices: 100 (no change from production)
SEO: 100 (no change from production)
PWA: -
View the detailed breakdown and full score reports
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@changeset-bot

changeset-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4556fdb

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

This PR includes changesets to release 119 packages
Name Type
@modern-js/app-tools Patch
@modern-js/adapter-rstest Patch
@modern-js/plugin-bff Patch
@modern-js/plugin-ssg Patch
@modern-js/plugin-styled-components Patch
@modern-js/plugin-i18n Patch
@modern-js/image Patch
@modern-js/runtime Patch
@modern-js/plugin-polyfill Patch
@integration-test/alias-set Patch
app-document Patch
async-entry-test Patch
tmp Patch
bff-api-app Patch
bff-client-app Patch
bff-indep-client-app Patch
bff-hono Patch
integration-clean-dist-path Patch
integration-compatibility Patch
integration-custom-dist-path Patch
custom-file-system-entry Patch
integration-custom-template Patch
deploy Patch
deploy-server Patch
dev-server Patch
integration-disable-html Patch
entries-app-builder Patch
app-custom-entries Patch
app-custom-routes-runtime Patch
app-custom Patch
app-entry Patch
app-route Patch
app-entry-server Patch
i18n-app-csr-html-lang Patch
i18n-app Patch
i18n-app-ssr-html-lang Patch
i18n-app-ssr Patch
i18n-custom-i18n-wrapper Patch
i18n-mf-app-provider Patch
i18n-mf-component-provider Patch
i18n-mf-consumer Patch
i18n-routes Patch
i18n-routes-ssr Patch
@integration-test/image-component Patch
main-entry-name Patch
nonce Patch
pure-esm-project Patch
react-compiler-test Patch
routes-match Patch
routes Patch
app-rsbuild-hooks Patch
rsc-csr-app Patch
rsc-csr-routes Patch
rsc-ssr-app Patch
rsc-ssr-routes Patch
basic-app-rstest-browser Patch
basic-app-rstest Patch
runtime-custom-plugin Patch
runtime-custom-config-plugin Patch
select-mul-entry-test Patch
select-one-entry-test Patch
server-config Patch
server-esm-tsx Patch
server-json-script Patch
server-monitors Patch
server-prod Patch
server-routes Patch
@source-code-build/app Patch
ssg-fixtures-mega-list-routes Patch
ssg-fixtures-nested-routes Patch
ssg-fixtures-simple Patch
ssg-fixtures-web-server Patch
ssr-base-async-entry-test Patch
ssr-base-async-pre-entry-test Patch
ssr-base-json-test Patch
ssr-base-test Patch
ssr-base-fallback-test Patch
init Patch
ssr-base-loadable Patch
ssr-partial-test Patch
rsc-closing-tags-test Patch
ssr-script-loading Patch
ssr-useid-test Patch
ssr-streaming-inline-test Patch
ssr-streaming-lazy-test Patch
ssr-streaming-test Patch
styled-components-stream Patch
styled-components-string Patch
integration-tailwindcss-v2 Patch
integration-tailwindcss-v3 Patch
integration-tailwindcss-v4-tools Patch
integration-tailwindcss-v4 Patch
tmp-dir Patch
write-to-dist Patch
@modern-js/bundle-diff-benchmark Patch
@modern-js/main-doc Patch
@modern-js/tsconfig Patch
@modern-js/builder Patch
@modern-js/plugin-data-loader Patch
@modern-js/render Patch
@modern-js/bff-core Patch
@modern-js/bff-runtime Patch
@modern-js/server-core Patch
@modern-js/create-request Patch
@modern-js/prod-server Patch
@modern-js/server-runtime Patch
@modern-js/server Patch
@modern-js/server-utils Patch
@modern-js/create Patch
@modern-js/i18n-utils Patch
@modern-js/plugin Patch
@modern-js/runtime-utils Patch
@modern-js/sandpack-react Patch
@modern-js/types Patch
@modern-js/utils Patch
@modern-js/rslib Patch
@scripts/prebundle Patch
@scripts/rstest-config Patch
@scripts/release-node 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

@github-actions

Copy link
Copy Markdown
Contributor

Rsdoctor Bundle Diff Analysis

📊 Quick Summary
Project Total Size Change
bundle-diff 472.5 KB 0

Generated by Rsdoctor GitHub Action

@keepview
keepview merged commit f4bc5ee into main Aug 25, 2026
10 of 11 checks passed
@keepview
keepview deleted the fix/app-tools-esm-loader-copy-race branch August 25, 2026 07:25
@caohuilin caohuilin mentioned this pull request Aug 26, 2026
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.

2 participants

Sponsor
SponsoredKunjungi sekarang
Promo