Skip to content
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

WIP for version 0.9.0 #924

Merged
merged 27 commits into from
Mar 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b5dfd7b
remove the deprecated "avoid TDZ" option
evanw Mar 6, 2021
038ebd5
remove unused "SpinnerBusy" and "SpinnerIdle"
evanw Mar 6, 2021
a25e962
single-line to multi-line build calls
evanw Mar 6, 2021
6744ddf
remove "--summary", always print summary instead
evanw Mar 6, 2021
3bda8ce
remove the "startService" API
evanw Mar 6, 2021
c3b32de
types: consolidate the "ImportKind" type
evanw Mar 6, 2021
533c707
enforce that "transform" input is a string
evanw Mar 6, 2021
05e2c57
add node unref tests to common tests
evanw Mar 6, 2021
4eff8be
remove "startService" in unref tests
evanw Mar 6, 2021
976fb87
fix typescript type error
evanw Mar 6, 2021
6838d04
avoid run time in summary for yarn 1
evanw Mar 6, 2021
6192e33
remove "startService" from uglify and terser tests
evanw Mar 6, 2021
edcc021
make banner and footer also work for css
evanw Mar 6, 2021
d417110
".mjs" and ".cjs" are no longer implied
evanw Mar 7, 2021
28c7353
avoid printing the summary in certain cases
evanw Mar 7, 2021
b94b754
move package.json code to separate file
evanw Mar 7, 2021
0680f07
implement the package.json "exports" field
evanw Mar 7, 2021
34ccad7
implement conditions for the "exports" field
evanw Mar 8, 2021
8da00f2
some more "exports" tests
evanw Mar 8, 2021
db00d17
update readme for the "exports" feature
evanw Mar 8, 2021
cfbe7e9
implement custom conditions for "exports"
evanw Mar 8, 2021
d4858db
fix "try.html"
evanw Mar 8, 2021
95bfc23
remove "metafile" from "outputFiles"
evanw Mar 8, 2021
d440ca4
data loaders from plugins are not side-effect free
evanw Mar 9, 2021
ba90d1b
rename "error limit" to "log limit"
evanw Mar 9, 2021
07cceea
fix js target affecting css
evanw Mar 9, 2021
ee1260f
have the js API write to stdout by default
evanw Mar 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,115 @@
# Changelog

## Breaking changes

* Remove the deprecated `--avoid-tdz` option

This option is now always enabled and cannot be disabled, so it is being removed from the API. The existing API parameter no longer does anything so this removal has no effect the generated output.

* Remove `SpinnerBusy` and `SpinnerIdle` from the Go API

These options were part of an experiment with the CLI that didn't work out. Watch mode no longer uses a spinner because it turns out people want to be able to interleave esbuild's stderr pipe with other tools and were getting tripped up by the spinner animation. These options no longer do anything and have been removed.

* Remove the `--summary` flag and instead just always print a summary ([#704](https://github.com/evanw/esbuild/issues/704))

The summary can be disabled if you don't want it by passing `--log-level=warning` instead. And it can be enabled in the API by setting `logLevel: 'info'`. I'm going to try this because I believe it will improve the UX. People have this problem with esbuild when they first try it where it runs so quickly that they think it must be broken, only to later discover that it actually worked fine. While this is funny, it seems like a good indication that the UX could be improved. So I'm going to try automatically printing a summary to see how that goes. Note that the summary is not printed if incremental builds are active (this includes the watch and serve modes).

* Remove the `esbuild.startService()` API

Due to [#656](https://github.com/evanw/esbuild/issues/656), Calling `service.stop()` no longer does anything, so there is no longer a strong reason for keeping the `esbuild.startService()` API around. The primary thing it currently does is just make the API more complicated and harder to use. You can now just call `esbuild.build()` and `esbuild.transform()` directly instead of calling `esbuild.startService().then(service => service.build())` or `esbuild.startService().then(service => service.transform())`.

If you are using esbuild in the browser, you now need to call `esbuild.initialize({ wasmURL })` and wait for the returned promise before calling `esbuild.transform()`. It takes the same options that `esbuild.startService()` used to take. Note that the `esbuild.buildSync()` and `esbuild.transformSync()` APIs still exist when using esbuild in node. Nothing has changed about the synchronous esbuild APIs.

* The banner and footer options are now language-specific ([#712](https://github.com/evanw/esbuild/issues/712))

The `--banner=` and `--footer=` options now require you to pass the file type:

* CLI:

```
esbuild --banner:js=//banner --footer:js=//footer
esbuild --banner:css=/*banner*/ --footer:css=/*footer*/
```

* JavaScript

```js
esbuild.build({
banner: { js: '//banner', css: '/*banner*/' },
footer: { js: '//footer', css: '/*footer*/' },
})
```

* Go

```go
api.Build(api.BuildOptions{
Banner: map[string]string{"js": "//banner"},
Footer: map[string]string{"js": "//footer"},
})
api.Build(api.BuildOptions{
Banner: map[string]string{"css": "/*banner*/"},
Footer: map[string]string{"css": "/*footer*/"},
})
```

This was changed because the feature was originally added in a JavaScript-specific manner, which was an oversight. CSS banners and footers must be separate from JavaScript banners and footers to avoid injecting JavaScript syntax into your CSS files.

* The extensions `.mjs` and `.cjs` are no longer implicit

Previously the "resolve extensions" setting included `.mjs` and `.cjs` but this is no longer the case. This wasn't a good default because it doesn't match node's behavior and could break some packages. You now have to either explicitly specify these extensions or configure the "resolve extensions" setting yourself.

* Add support for node's `exports` field in `package.json` files ([#187](https://github.com/evanw/esbuild/issues/187))

This feature was recently added to node. It allows you to rewrite what import paths inside your package map to as well as to prevent people from importing certain files in your package. Adding support for this to esbuild is a breaking change (i.e. code that was working fine before can easily stop working) so adding support for it has been delayed until this breaking change release.

One way to use this feature is to remap import paths for your package. For example, this would remap an import of `your-pkg/esm/lib.js` (the "public" import path) to `your-pkg/dist/esm/lib.js` (the "private" file system path):

```json
{
"name": "your-pkg",
"exports": {
"./esm/*": "./dist/esm/*",
"./cjs/*": "./dist/cjs/*"
}
}
```

Another way to use this feature is to have conditional imports where the same import path can mean different things in different situations. For example, this would remap `require('your-pkg')` to `your-pkg/required.cjs` and `import 'your-pkg'` to `your-pkg/imported.mjs`:

```json
{
"name": "your-pkg",
"exports": {
"import": "./imported.mjs",
"require": "./required.cjs"
}
}
```

There is built-in support for the `import` and `require` conditions depending on the kind of import and the `browser` and `node` conditions depending on the current platform. In addition, the `default` condition always applies regardless of the current configuration settings and can be used as a catch-all fallback condition.

Note that when you use conditions, _your package may end up in the bundle multiple times!_ This is a subtle issue that can cause bugs due to duplicate copies of your code's state in addition to bloating the resulting bundle. This is commonly known as the [dual package hazard](https://nodejs.org/docs/latest/api/packages.html#packages_dual_package_hazard). The primary way of avoiding this is to put all of your code in the `require` condition and have the `import` condition just be a light wrapper that calls `require` on your package and re-exports the package using ESM syntax.

There is also support for custom conditions with the `--conditions=` flag. The meaning of these is entirely up to package authors. For example, you could imagine a package that requires you to configure `--conditions=test,en-US`. Node has currently only endorsed the `development` and `production` custom conditions for recommended use.

* Remove the `metafile` from `outputFiles` (#633)

Previously using `metafile` with the API is unnecessarily cumbersome because you have to extract the JSON metadata from the output file yourself instead of it just being provided to you as a return value. This is especially a bummer if you are using `write: false` because then you need to use a for loop over the output files and do string comparisons with the file paths to try to find the one corresponding to the `metafile`. Returning the metadata directly is an important UX improvement for the API. It means you can now do this:

```js
const result = await esbuild.build({
entryPoints: ['entry.js'],
bundle: true,
metafile: true,
})
console.log(metafile.outputs)
```

* Rename `--error-limit=` to `--log-limit=`

This parameter has been renamed because it now applies to both warnings and errors, not just to errors. Previously setting the error limit did not apply any limits to the number of warnings printed, which could sometimes result in a deluge of warnings that are problematic for Windows Command Prompt, which is very slow to print to and has very limited scrollback. Now the log limit applies to the total number of log messages including both errors and warnings, so no more than that number of messages will be printed. The log usually prints log messages immediately but it will now intentionally hold back warnings when approaching the limit to make room for possible future errors during a build. So if a build fails you should be guaranteed to see an error message (i.e. warnings can't use up the entire log limit and then prevent errors from being printed).

## 0.8.57

* Fix overlapping chunk names when code splitting is active ([#928](https://github.com/evanw/esbuild/issues/928))
Expand Down
18 changes: 10 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ test:
make -j6 test-common

# These tests are for development
test-common: test-go vet-go no-filepath verify-source-map end-to-end-tests js-api-tests plugin-tests register-test
test-common: test-go vet-go no-filepath verify-source-map end-to-end-tests js-api-tests plugin-tests register-test node-unref-tests

# These tests are for release (the extra tests are not included in "test" because they are pretty slow)
test-all:
make -j6 test-common ts-type-tests test-wasm-node test-wasm-browser
make -j6 test-common ts-type-tests test-wasm-node test-wasm-browser lib-typecheck

# This includes tests of some 3rd-party libraries, which can be very slow
test-prepublish: check-go-version test-all test-preact-splitting test-sucrase bench-rome-esbuild test-esprima test-rollup
Expand Down Expand Up @@ -67,6 +67,9 @@ plugin-tests: cmd/esbuild/version.go | scripts/node_modules
ts-type-tests: | scripts/node_modules
node scripts/ts-type-tests.js

node-unref-tests:
node scripts/node-unref-tests.js

lib-typecheck: | lib/node_modules
cd lib && node_modules/.bin/tsc -noEmit -p .

Expand Down Expand Up @@ -471,13 +474,13 @@ demo-three: demo-three-esbuild demo-three-rollup demo-three-webpack demo-three-w

demo-three-esbuild: esbuild | demo/three
rm -fr demo/three/esbuild
time -p ./esbuild --bundle --summary --global-name=THREE --sourcemap --minify demo/three/src/Three.js --outfile=demo/three/esbuild/Three.esbuild.js
time -p ./esbuild --bundle --global-name=THREE --sourcemap --minify demo/three/src/Three.js --outfile=demo/three/esbuild/Three.esbuild.js
du -h demo/three/esbuild/Three.esbuild.js*
shasum demo/three/esbuild/Three.esbuild.js*

demo-three-eswasm: platform-wasm | demo/three
rm -fr demo/three/eswasm
time -p ./npm/esbuild-wasm/bin/esbuild --bundle --summary --global-name=THREE \
time -p ./npm/esbuild-wasm/bin/esbuild --bundle --global-name=THREE \
--sourcemap --minify demo/three/src/Three.js --outfile=demo/three/eswasm/Three.eswasm.js
du -h demo/three/eswasm/Three.eswasm.js*
shasum demo/three/eswasm/Three.eswasm.js*
Expand Down Expand Up @@ -560,13 +563,13 @@ bench-three: bench-three-esbuild bench-three-rollup bench-three-webpack bench-th

bench-three-esbuild: esbuild | bench/three
rm -fr bench/three/esbuild
time -p ./esbuild --bundle --summary --global-name=THREE --sourcemap --minify bench/three/src/entry.js --outfile=bench/three/esbuild/entry.esbuild.js
time -p ./esbuild --bundle --global-name=THREE --sourcemap --minify bench/three/src/entry.js --outfile=bench/three/esbuild/entry.esbuild.js
du -h bench/three/esbuild/entry.esbuild.js*
shasum bench/three/esbuild/entry.esbuild.js*

bench-three-eswasm: platform-wasm | bench/three
rm -fr bench/three/eswasm
time -p ./npm/esbuild-wasm/bin/esbuild --bundle --summary --global-name=THREE \
time -p ./npm/esbuild-wasm/bin/esbuild --bundle --global-name=THREE \
--sourcemap --minify bench/three/src/entry.js --outfile=bench/three/eswasm/entry.eswasm.js
du -h bench/three/eswasm/entry.eswasm.js*
shasum bench/three/eswasm/entry.eswasm.js*
Expand Down Expand Up @@ -669,7 +672,7 @@ bench-rome: bench-rome-esbuild bench-rome-webpack bench-rome-webpack5 bench-rome

bench-rome-esbuild: esbuild | bench/rome bench/rome-verify
rm -fr bench/rome/esbuild
time -p ./esbuild --bundle --summary --sourcemap --minify bench/rome/src/entry.ts --outfile=bench/rome/esbuild/rome.esbuild.js --platform=node
time -p ./esbuild --bundle --sourcemap --minify bench/rome/src/entry.ts --outfile=bench/rome/esbuild/rome.esbuild.js --platform=node
du -h bench/rome/esbuild/rome.esbuild.js*
shasum bench/rome/esbuild/rome.esbuild.js*
cd bench/rome-verify && rm -fr esbuild && ROME_CACHE=0 node ../rome/esbuild/rome.esbuild.js bundle packages/rome esbuild
Expand Down Expand Up @@ -810,7 +813,6 @@ READMIN_ESBUILD_FLAGS += --define:process.env.NODE_ENV='"production"'
READMIN_ESBUILD_FLAGS += --loader:.js=jsx
READMIN_ESBUILD_FLAGS += --minify
READMIN_ESBUILD_FLAGS += --sourcemap
READMIN_ESBUILD_FLAGS += --summary

bench-readmin-esbuild: esbuild | bench/readmin
rm -fr bench/readmin/esbuild
Expand Down
11 changes: 6 additions & 5 deletions cmd/esbuild/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,18 @@ var helpText = func(colors logger.Colors) string {
--serve=... Start a local HTTP server on this host:port for outputs
--sourcemap Emit a source map
--splitting Enable code splitting (currently only for esm)
--summary Print some helpful information at the end of a build
--target=... Environment target (e.g. es2017, chrome58, firefox57,
safari11, edge16, node10, default esnext)
--watch Watch mode: rebuild on file system changes

` + colors.Bold + `Advanced options:` + colors.Default + `
--banner=... Text to be prepended to each output file
--banner:T=... Text to be prepended to each output file of type T
where T is one of: css | js
--charset=utf8 Do not escape UTF-8 code points
--color=... Force use of color terminal escapes (true | false)
--error-limit=... Maximum error count or 0 to disable (default 10)
--footer=... Text to be appended to each output file
--log-limit=... Maximum message count or 0 to disable (default 10)
--footer:T=... Text to be appended to each output file of type T
where T is one of: css | js
--global-name=... The name of the global for the IIFE format
--inject:F Import the file F into all input files and
automatically replace matching globals with imports
Expand All @@ -73,7 +74,7 @@ var helpText = func(colors logger.Colors) string {
--public-path=... Set the base URL for the "file" loader
--pure:N Mark the name N as a pure function for tree shaking
--resolve-extensions=... A comma-separated list of implicit extensions
(default ".tsx,.ts,.jsx,.mjs,.cjs,.js,.css,.json")
(default ".tsx,.ts,.jsx,.js,.css,.json")
--servedir=... What to serve in addition to generated output files
--sourcefile=... Set the source file for the source map (for stdin)
--sourcemap=external Do not link to the source map with a comment
Expand Down
22 changes: 12 additions & 10 deletions cmd/esbuild/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,15 +356,9 @@ func (service *serviceType) handleBuildRequest(id uint32, request map[string]int
// Normally when "write" is true and there is no output file/directory then
// the output is written to stdout instead. However, we're currently using
// stdout as a communication channel and writing the build output to stdout
// would corrupt our protocol.
//
// While we could channel this back to the host process and write it to
// stdout there, the public Go API we're about to call doesn't have an option
// for "write to stdout but don't actually write" and I don't think it should.
// For now let's just forbid this case because it's not even that useful.
if err == nil && !isServe && write && options.Outfile == "" && options.Outdir == "" {
err = errors.New("Either provide \"outfile\" or set \"write\" to false")
}
// would corrupt our protocol. Special-case this to channel this back to the
// host process and write it to stdout there.
writeToStdout := err == nil && !isServe && write && options.Outfile == "" && options.Outdir == ""

if err != nil {
return outgoingPacket{bytes: encodeErrorPacket(id, err)}
Expand Down Expand Up @@ -417,6 +411,12 @@ func (service *serviceType) handleBuildRequest(id uint32, request map[string]int
if options.Watch != nil {
response["watchID"] = watchID
}
if options.Metafile {
response["metafile"] = result.Metafile
}
if writeToStdout && len(result.OutputFiles) == 1 {
response["writeToStdout"] = result.OutputFiles[0].Contents
}
return response
}

Expand All @@ -430,7 +430,9 @@ func (service *serviceType) handleBuildRequest(id uint32, request map[string]int
}
}

options.Write = write
if !writeToStdout {
options.Write = write
}
options.Incremental = incremental
result := api.Build(options)
response := resultToResponse(result)
Expand Down
Loading