Skip to content

Add bundle.external configuration option for marking modules as external during bundling#12883

Closed
dario-piotrowicz wants to merge 3 commits intomainfrom
dario/bundling_external
Closed

Add bundle.external configuration option for marking modules as external during bundling#12883
dario-piotrowicz wants to merge 3 commits intomainfrom
dario/bundling_external

Conversation

@dario-piotrowicz
Copy link
Member

@dario-piotrowicz dario-piotrowicz commented Mar 13, 2026

Fixes #7095

This PR adds a bundle.external wrangler option to make packages as external. It also improves the esbuild error message to mention this new option or alias as a way to fix imports that failed to be resolved.

Error message before Error message after
Screenshot of error message before changes Screenshot of error message after changes

(Note: the screenshot is slightly outdated, bundling_external has been updated to bundle.external)


  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:
  • Public documentation
    • Cloudflare docs PR(s): TODO
    • Documentation not necessary because:

A picture of a cute animal (not mandatory, but encouraged)


Open with Devin

@changeset-bot
Copy link

changeset-bot bot commented Mar 13, 2026

🦋 Changeset detected

Latest commit: cee4718

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

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
Contributor

github-actions bot commented Mar 13, 2026

✅ All changesets look good

ask-bonk[bot]

This comment was marked as outdated.

@ask-bonk

This comment was marked as outdated.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 13, 2026

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@12883

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@12883

miniflare

npm i https://pkg.pr.new/miniflare@12883

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@12883

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@12883

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@12883

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@12883

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@12883

wrangler

npm i https://pkg.pr.new/wrangler@12883

commit: cee4718

@dario-piotrowicz dario-piotrowicz force-pushed the dario/bundling_external branch from 1e73e66 to 633a474 Compare March 13, 2026 19:46
@dario-piotrowicz dario-piotrowicz marked this pull request as ready for review March 16, 2026 12:14
@dario-piotrowicz dario-piotrowicz requested a review from a team as a code owner March 16, 2026 12:14
@workers-devprod
Copy link
Contributor

workers-devprod commented Mar 16, 2026

Codeowners approval required for this PR:

  • @cloudflare/wrangler
Show detailed file reviewers
  • packages/workers-utils/src/config/config.ts: [@cloudflare/wrangler]
  • packages/workers-utils/src/config/environment.ts: [@cloudflare/wrangler]
  • packages/workers-utils/src/config/validation.ts: [@cloudflare/wrangler]
  • packages/workers-utils/tests/config/validation/normalize-and-validate-config.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/api/startDevWorker/BundleController.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/api/startDevWorker/ConfigController.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/deploy/build.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/api/startDevWorker/BundlerController.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/api/startDevWorker/ConfigController.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/api/startDevWorker/types.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/deploy/deploy.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/deployment-bundle/build-failures.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/deployment-bundle/bundle.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/dev/use-esbuild.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/versions/upload.ts: [@cloudflare/wrangler]

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

"wrangler": minor
---

Add `bundling_external` configuration option for marking modules as external during bundling
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the bike-shedding, but I wonder if external_imports might be a bit clearer here? It may make it more obvious what the array contains. 😄

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mh... I would really keep bundling in the name though... no? just to make it extra clear that this is related to bundling 🤔

I was also thinking... what if we added a bundling config object and in it the only field (for now at least) would be external_imports?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me. In that case, I wonder if bundle.external would be a better fit, since it would read as a more explicit counterpart to no_bundle.

Then, if this area grows over time, we could potentially add things like bundle.minify and gradually move some of the current top-level config there and then deprecate the old names . Definitely not something this PR needs to solve, just thinking out loud about how this config might evolve.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah that sounds like a potentially good plan to me 🙂

shall I just then turn bundling_external to bundle.external? 🙂

@dario-piotrowicz dario-piotrowicz changed the title Add bundling_external configuration option for marking modules as external during bundling Add bundle.external configuration option for marking modules as external during bundling Mar 16, 2026
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 new potential issues.

View 6 additional findings in Devin Review.

Open in Devin Review

Comment on lines +583 to +587
if (config.bundle) {
logger.warn(
"`bundle` and `--no-bundle` can't be used together. Please choose the one that is most appropriate for your use case."
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 config.bundle is always truthy, causing spurious warning when using --no-bundle

In deploy.ts:583, the check if (config.bundle) is always truthy because the default value for config.bundle is {} (set in packages/workers-utils/src/config/config.ts:384 and as the default in packages/workers-utils/src/config/validation.ts:1925). An empty object {} is truthy in JavaScript, so whenever --no-bundle is used, the warning "bundle and --no-bundle can't be used together" will always fire, even when the user has not configured any bundle.external entries. The check should be config.bundle?.external?.length (similar to the check in versions/upload.ts:506) to only warn when external modules are actually configured.

Suggested change
if (config.bundle) {
logger.warn(
"`bundle` and `--no-bundle` can't be used together. Please choose the one that is most appropriate for your use case."
);
}
if (config.bundle?.external?.length) {
logger.warn(
"`bundle` and `--no-bundle` can't be used together. Please choose the one that is most appropriate for your use case."
);
}
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +500 to +510
if (props.noBundle && minify) {
logger.warn(
"`--minify` and `--no-bundle` can't be used together. If you want to minify your Worker and disable Wrangler's bundling, please minify as part of your own bundling process."
);
}

if (props.noBundle && config.bundle?.external?.length) {
logger.warn(
"`bundle.external` and `--no-bundle` can't be used together. If you want to exclude modules from your bundle and disable Wrangler's bundling, please handle external modules as part of your own bundling process."
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Redundant props.noBundle && checks inside already-guarded if (props.noBundle) block

In versions/upload.ts:500 and versions/upload.ts:506, the conditions props.noBundle && minify and props.noBundle && config.bundle?.external?.length redundantly re-check props.noBundle despite already being inside an if (props.noBundle) block. This is inconsistent with the equivalent code in deploy.ts:576-588 which does not have the redundant checks. While not a runtime bug (the logic is still correct), this is a copy-paste error that adds unnecessary noise.

Suggested change
if (props.noBundle && minify) {
logger.warn(
"`--minify` and `--no-bundle` can't be used together. If you want to minify your Worker and disable Wrangler's bundling, please minify as part of your own bundling process."
);
}
if (props.noBundle && config.bundle?.external?.length) {
logger.warn(
"`bundle.external` and `--no-bundle` can't be used together. If you want to exclude modules from your bundle and disable Wrangler's bundling, please handle external modules as part of your own bundling process."
);
}
if (minify) {
logger.warn(
"`--minify` and `--no-bundle` can't be used together. If you want to minify your Worker and disable Wrangler's bundling, please minify as part of your own bundling process."
);
}
if (config.bundle?.external?.length) {
logger.warn(
"`bundle.external` and `--no-bundle` can't be used together. If you want to exclude modules from your bundle and disable Wrangler's bundling, please handle external modules as part of your own bundling process."
);
}
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +583 to +587
if (config.bundle) {
logger.warn(
"`bundle` and `--no-bundle` can't be used together. Please choose the one that is most appropriate for your use case."
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Inconsistent no-bundle + bundle.external warning messages between deploy.ts and versions/upload.ts

In deploy.ts:584-586, the warning when --no-bundle and bundle are used together says "bundle and --no-bundle can't be used together" with a generic message. In versions/upload.ts:507-508, the equivalent warning says "bundle.external and --no-bundle can't be used together" with a more specific message about handling external modules. The deploy.ts version checks config.bundle (which is always truthy as noted in BUG-0001) while versions/upload.ts correctly checks config.bundle?.external?.length. The behavior is inconsistent between the two code paths for the same feature.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@dario-piotrowicz
Copy link
Member Author

Closing in favor of #12931, thanks a bunch @edmundhung for reviewing the PR anyways 🙏

@github-project-automation github-project-automation bot moved this from Untriaged to Done in workers-sdk Mar 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

🐛 BUG: You can mark the path <pathname> as external is not an actionable error message

3 participants