Skip to content

Commit 196dcad

Browse files
committed
fix #1874: node defaults to --packages=external
1 parent 3f57db8 commit 196dcad

File tree

8 files changed

+68
-9
lines changed

8 files changed

+68
-9
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
## Unreleased
44

5+
* Omit packages from bundle by default when targeting node ([#1874](https://github.com/evanw/esbuild/issues/1874), [#2830](https://github.com/evanw/esbuild/issues/2830), [#2846](https://github.com/evanw/esbuild/issues/2846), [#2915](https://github.com/evanw/esbuild/issues/2915), [#3145](https://github.com/evanw/esbuild/issues/3145), [#3294](https://github.com/evanw/esbuild/issues/3294), [#3323](https://github.com/evanw/esbuild/issues/3323), [#3582](https://github.com/evanw/esbuild/issues/3582), [#3809](https://github.com/evanw/esbuild/issues/3809), [#3815](https://github.com/evanw/esbuild/issues/3815))
6+
7+
This breaking change is an experiment. People are commonly confused when using esbuild to bundle code for node (i.e. for `--platform=node`) because some packages may not be intended for bundlers, and may use node-specific features that don't work with a bundler. Even though esbuild's "getting started" instructions say to use `--packages=external` to work around this problem, many people don't read the documentation and don't do this, and are then confused when it doesn't work. So arguably this is a bad default behavior for esbuild to have if people keep tripping over this.
8+
9+
With this release, esbuild will now omit packages from the bundle by default when the platform is `node` (i.e. the previous behavior of `--packages=external` is now the default in this case). If you don't want this behavior, you can do `--packages=bundle` to allow packages to be included in the bundle (i.e. the previous default behavior). Note that `--packages=bundle` doesn't mean all packages are bundled, just that packages are allowed to be bundled. You can still exclude individual packages from the bundle using `--external:` even when `--packages=bundle` is present.
10+
11+
The `--packages=` setting considers all import paths that "look like" package imports in the original source code to be packages. Specifically packages that don't start with a path segment of `/` or `.` or `..` are considered to be package imports. The only two exceptions to this rule are [subpath imports](https://nodejs.org/api/packages.html#subpath-imports) (which start with a `#` character) and TypeScript path remappings via `path` and/or `baseUrl` in `tsconfig.json` (which are applied first).
12+
513
* Drop support for older platforms ([#3802](https://github.com/evanw/esbuild/issues/3802))
614

715
This release drops support for the following operating systems:

Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ test-tsc: esbuild | github/tsc
753753
cp -r github/tsc/src github/tsc/scripts demo/tsc
754754
cp github/tsc/lib/*.d.ts demo/tsc/built/local
755755
cd demo/tsc && node scripts/processDiagnosticMessages.mjs src/compiler/diagnosticMessages.json
756-
./esbuild --bundle demo/tsc/src/tsc/tsc.ts --outfile=demo/tsc/built/local/tsc.js --platform=node --target=es2018 --packages=external
756+
./esbuild --bundle demo/tsc/src/tsc/tsc.ts --outfile=demo/tsc/built/local/tsc.js --platform=node --target=es2018
757757
echo '{"dependencies":{"@types/node":"20.2.5","@types/microsoft__typescript-etw":"0.1.1","@types/source-map-support":"0.5.6"}}' > demo/tsc/package.json
758758
cd demo/tsc && npm i --silent && echo 'Type checking tsc using tsc...' && time -p node ./built/local/tsc.js -p src/compiler
759759

@@ -769,6 +769,7 @@ TEST_ROLLUP_REPLACE += "paths": { "package.json": [".\/package.json"] },
769769
TEST_ROLLUP_FLAGS += --bundle
770770
TEST_ROLLUP_FLAGS += --external:fsevents
771771
TEST_ROLLUP_FLAGS += --outfile=dist/rollup.js
772+
TEST_ROLLUP_FLAGS += --packages=bundle
772773
TEST_ROLLUP_FLAGS += --platform=node
773774
TEST_ROLLUP_FLAGS += --target=es6
774775
TEST_ROLLUP_FLAGS += src/node-entry.ts

lib/shared/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export interface BuildOptions extends CommonOptions {
125125
/** Documentation: https://esbuild.github.io/api/#external */
126126
external?: string[]
127127
/** Documentation: https://esbuild.github.io/api/#packages */
128-
packages?: 'external'
128+
packages?: 'bundle' | 'external'
129129
/** Documentation: https://esbuild.github.io/api/#alias */
130130
alias?: Record<string, string>
131131
/** Documentation: https://esbuild.github.io/api/#loader */

pkg/api/api.go

+1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ type Packages uint8
180180

181181
const (
182182
PackagesDefault Packages = iota
183+
PackagesBundle
183184
PackagesExternal
184185
)
185186

pkg/api/api_impl.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,19 @@ func validateASCIIOnly(value Charset) bool {
216216
}
217217
}
218218

219+
func validateExternalPackages(value Packages, platform Platform) bool {
220+
switch value {
221+
case PackagesDefault:
222+
return platform == PlatformNode
223+
case PackagesBundle:
224+
return false
225+
case PackagesExternal:
226+
return true
227+
default:
228+
panic("Invalid packages")
229+
}
230+
}
231+
219232
func validateTreeShaking(value TreeShaking, bundle bool, format Format) bool {
220233
switch value {
221234
case TreeShakingDefault:
@@ -1267,7 +1280,7 @@ func validateBuildOptions(
12671280
ExtensionToLoader: validateLoaders(log, buildOpts.Loader),
12681281
ExtensionOrder: validateResolveExtensions(log, buildOpts.ResolveExtensions),
12691282
ExternalSettings: validateExternals(log, realFS, buildOpts.External),
1270-
ExternalPackages: buildOpts.Packages == PackagesExternal,
1283+
ExternalPackages: validateExternalPackages(buildOpts.Packages, buildOpts.Platform),
12711284
PackageAliases: validateAlias(log, realFS, buildOpts.Alias),
12721285
TSConfigPath: validatePath(log, realFS, buildOpts.Tsconfig, "tsconfig path"),
12731286
TSConfigRaw: buildOpts.TsconfigRaw,

pkg/cli/cli_impl.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -613,12 +613,15 @@ func parseOptionsImpl(
613613
case strings.HasPrefix(arg, "--packages=") && buildOpts != nil:
614614
value := arg[len("--packages="):]
615615
var packages api.Packages
616-
if value == "external" {
616+
switch value {
617+
case "bundle":
618+
packages = api.PackagesBundle
619+
case "external":
617620
packages = api.PackagesExternal
618-
} else {
621+
default:
619622
return parseOptionsExtras{}, cli_helpers.MakeErrorWithNote(
620623
fmt.Sprintf("Invalid value %q in %q", value, arg),
621-
"The only valid value is \"external\".",
624+
"Valid values are \"bundle\" or \"external\".",
622625
)
623626
}
624627
buildOpts.Packages = packages

scripts/end-to-end-tests.js

+33-1
Original file line numberDiff line numberDiff line change
@@ -8069,7 +8069,7 @@ for (const flags of [[], ['--bundle']]) {
80698069
}
80708070
}`,
80718071
}),
8072-
test(['in.js', '--outfile=node.js', '--bundle', '--platform=node'].concat(flags), {
8072+
test(['in.js', '--outfile=node.js', '--bundle', '--platform=node', '--packages=bundle'].concat(flags), {
80738073
'in.js': `import abc from 'pkg'; if (abc !== 'module') throw 'fail'`,
80748074
'node_modules/pkg/default.js': `module.exports = 'default'`,
80758075
'node_modules/pkg/module.js': `export default 'module'`,
@@ -8109,6 +8109,38 @@ for (const flags of [[], ['--bundle']]) {
81098109
}`,
81108110
}),
81118111

8112+
// Check the default behavior of "--platform=node"
8113+
test(['in.js', '--outfile=node.js', '--bundle', '--platform=node', '--format=esm'].concat(flags), {
8114+
'in.js': `import abc from 'pkg'; if (abc !== 'import') throw 'fail'`,
8115+
'node_modules/pkg/fail.js': `TEST FAILED`, // This package should not be bundled
8116+
'node_modules/pkg/require.cjs': `module.exports = 'require'`,
8117+
'node_modules/pkg/import.mjs': `export default 'import'`,
8118+
'node_modules/pkg/package.json': `{
8119+
"exports": {
8120+
".": {
8121+
"module": "./fail.js",
8122+
"import": "./import.mjs",
8123+
"require": "./require.cjs"
8124+
}
8125+
}
8126+
}`,
8127+
}),
8128+
test(['in.js', '--outfile=node.js', '--bundle', '--platform=node', '--format=cjs'].concat(flags), {
8129+
'in.js': `import abc from 'pkg'; if (abc !== 'require') throw 'fail'`,
8130+
'node_modules/pkg/fail.js': `TEST FAILED`, // This package should not be bundled
8131+
'node_modules/pkg/require.cjs': `module.exports = 'require'`,
8132+
'node_modules/pkg/import.mjs': `export default 'import'`,
8133+
'node_modules/pkg/package.json': `{
8134+
"exports": {
8135+
".": {
8136+
"module": "./fail.js",
8137+
"import": "./import.mjs",
8138+
"require": "./require.cjs"
8139+
}
8140+
}
8141+
}`,
8142+
}),
8143+
81128144
// This is an edge case for extensionless files. The file should be treated
81138145
// as CommonJS even though package.json says "type": "module" because that
81148146
// only applies to ".js" files in node, not to all JavaScript files.

scripts/test-yarnpnp.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,20 @@ function runTests() {
6666
'in.mjs',
6767
'--bundle',
6868
'--log-level=debug',
69+
'--packages=bundle',
6970
'--platform=node',
7071
'--outfile=out-native.js',
7172
], { cwd: rootDir, stdio: 'inherit' })
7273
run('node out-native.js')
7374

7475
// Test the WebAssembly build
7576
esbuild.buildWasmLib(ESBUILD_BINARY_PATH)
76-
run('node ../../npm/esbuild-wasm/bin/esbuild in.mjs --bundle --log-level=debug --platform=node --outfile=out-wasm.js')
77+
run('node ../../npm/esbuild-wasm/bin/esbuild in.mjs --bundle --log-level=debug --packages=bundle --platform=node --outfile=out-wasm.js')
7778
run('node out-wasm.js')
7879

7980
// Test the WebAssembly build when run through Yarn's file system shim
8081
esbuild.buildWasmLib(ESBUILD_BINARY_PATH)
81-
run('yarn node ../../npm/esbuild-wasm/bin/esbuild in.mjs --bundle --log-level=debug --platform=node --outfile=out-wasm-yarn.js')
82+
run('yarn node ../../npm/esbuild-wasm/bin/esbuild in.mjs --bundle --log-level=debug --packages=bundle --platform=node --outfile=out-wasm-yarn.js')
8283
run('node out-wasm-yarn.js')
8384
}
8485

0 commit comments

Comments
 (0)