Skip to content

Commit

Permalink
remove "metafile" from "outputFiles"
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Mar 9, 2021
1 parent 13ac32c commit ac70415
Show file tree
Hide file tree
Showing 16 changed files with 253 additions and 197 deletions.
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@

Previously doing this was supported and caused the file to become a CommonJS module with the ESM exports becoming CommonJS exports. However, now that ESM code is no longer allowed inside a CommonJS wrapper, doing this is no longer supported. When you try to do this the ESM exports will win and references to the CommonJS `exports` and `module` variables will be passed through unmodified just like any other global variable reference. In addition, the TypeScript-specific `export =` syntax is not allowed in an ESM file. This is an alias for `module.exports =` and is already forbidden by the TypeScript compiler in an ESM file.

* Add support for node's `exports` field in `package.json` files
* 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.
Expand Down Expand Up @@ -109,6 +109,19 @@

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)
```

## 0.8.57

* Fix overlapping chunk names when code splitting is active ([#928](https://github.com/evanw/esbuild/issues/928))
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ test-common: test-go vet-go no-filepath verify-source-map end-to-end-tests js-ap

# 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
3 changes: 3 additions & 0 deletions cmd/esbuild/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,9 @@ func (service *serviceType) handleBuildRequest(id uint32, request map[string]int
if options.Watch != nil {
response["watchID"] = watchID
}
if options.Metafile {
response["metafile"] = result.Metafile
}
return response
}

Expand Down
74 changes: 36 additions & 38 deletions internal/bundler/bundler.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type file struct {
// If "AbsMetadataFile" is present, this will be filled out with information
// about this file in JSON format. This is a partial JSON file that will be
// fully assembled later.
jsonMetadataChunk []byte
jsonMetadataChunk string

// The path of this entry point relative to the lowest common ancestor
// directory containing all entry points. Note: this must have OS-independent
Expand Down Expand Up @@ -330,17 +330,17 @@ func parseFile(args parseArgs) {
result.ok = true

// Optionally add metadata about the file
var jsonMetadataChunk []byte
if args.options.AbsMetadataFile != "" {
var jsonMetadataChunk string
if args.options.NeedsMetafile {
inputs := fmt.Sprintf("{\n %s: {\n \"bytesInOutput\": %d\n }\n }",
js_printer.QuoteForJSON(source.PrettyPath, args.options.ASCIIOnly),
len(source.Contents),
)
jsonMetadataChunk = []byte(fmt.Sprintf(
jsonMetadataChunk = fmt.Sprintf(
"{\n \"imports\": [],\n \"exports\": [],\n \"inputs\": %s,\n \"bytes\": %d\n }",
inputs,
len(source.Contents),
))
)
}

// Copy the file using an additional file payload to make sure we only copy
Expand Down Expand Up @@ -1296,13 +1296,13 @@ func (s *scanner) processScannedFiles() []file {
continue
}

j := js_printer.Joiner{}
sb := strings.Builder{}
isFirstImport := true

// Begin the metadata chunk
if s.options.AbsMetadataFile != "" {
j.AddBytes(js_printer.QuoteForJSON(result.file.source.PrettyPath, s.options.ASCIIOnly))
j.AddString(fmt.Sprintf(": {\n \"bytes\": %d,\n \"imports\": [", len(result.file.source.Contents)))
if s.options.NeedsMetafile {
sb.Write(js_printer.QuoteForJSON(result.file.source.PrettyPath, s.options.ASCIIOnly))
sb.WriteString(fmt.Sprintf(": {\n \"bytes\": %d,\n \"imports\": [", len(result.file.source.Contents)))
}

// Don't try to resolve paths if we're not bundling
Expand Down Expand Up @@ -1337,14 +1337,14 @@ func (s *scanner) processScannedFiles() []file {
}

// Generate metadata about each import
if s.options.AbsMetadataFile != "" {
if s.options.NeedsMetafile {
if isFirstImport {
isFirstImport = false
j.AddString("\n ")
sb.WriteString("\n ")
} else {
j.AddString(",\n ")
sb.WriteString(",\n ")
}
j.AddString(fmt.Sprintf("{\n \"path\": %s,\n \"kind\": %s\n }",
sb.WriteString(fmt.Sprintf("{\n \"path\": %s,\n \"kind\": %s\n }",
js_printer.QuoteForJSON(s.results[record.SourceIndex.GetIndex()].file.source.PrettyPath, s.options.ASCIIOnly),
js_printer.QuoteForJSON(record.Kind.StringForMetafile(), s.options.ASCIIOnly)))
}
Expand Down Expand Up @@ -1465,14 +1465,14 @@ func (s *scanner) processScannedFiles() []file {
}

// End the metadata chunk
if s.options.AbsMetadataFile != "" {
if s.options.NeedsMetafile {
if !isFirstImport {
j.AddString("\n ")
sb.WriteString("\n ")
}
j.AddString("]\n }")
sb.WriteString("]\n }")
}

s.results[i].file.jsonMetadataChunk = j.Done()
s.results[i].file.jsonMetadataChunk = sb.String()
}

// The linker operates on an array of files, so construct that now. This
Expand Down Expand Up @@ -1508,7 +1508,7 @@ type OutputFile struct {
// If "AbsMetadataFile" is present, this will be filled out with information
// about this file in JSON format. This is a partial JSON file that will be
// fully assembled later.
jsonMetadataChunk []byte
jsonMetadataChunk string

IsExecutable bool
}
Expand Down Expand Up @@ -1539,7 +1539,7 @@ func applyOptionDefaults(options *config.Options) {
}
}

func (b *Bundle) Compile(log logger.Log, options config.Options) []OutputFile {
func (b *Bundle) Compile(log logger.Log, options config.Options) ([]OutputFile, string) {
applyOptionDefaults(&options)

// The format can't be "preserve" while bundling
Expand Down Expand Up @@ -1585,11 +1585,9 @@ func (b *Bundle) Compile(log logger.Log, options config.Options) []OutputFile {
}

// Also generate the metadata file if necessary
if options.AbsMetadataFile != "" {
outputFiles = append(outputFiles, OutputFile{
AbsPath: options.AbsMetadataFile,
Contents: b.generateMetadataJSON(outputFiles, allReachableFiles, options.ASCIIOnly),
})
var metafileJSON string
if options.NeedsMetafile {
metafileJSON = b.generateMetadataJSON(outputFiles, allReachableFiles, options.ASCIIOnly)
}

if !options.WriteToStdout {
Expand Down Expand Up @@ -1644,7 +1642,7 @@ func (b *Bundle) Compile(log logger.Log, options config.Options) []OutputFile {
outputFiles = outputFiles[:end]
}

return outputFiles
return outputFiles, metafileJSON
}

// This is done in parallel with linking because linking is a mostly serial
Expand Down Expand Up @@ -1784,9 +1782,9 @@ func (b *Bundle) lowestCommonAncestorDirectory(codeSplitting bool, allReachableF
return lowestAbsDir
}

func (b *Bundle) generateMetadataJSON(results []OutputFile, allReachableFiles []uint32, asciiOnly bool) []byte {
j := js_printer.Joiner{}
j.AddString("{\n \"inputs\": {")
func (b *Bundle) generateMetadataJSON(results []OutputFile, allReachableFiles []uint32, asciiOnly bool) string {
sb := strings.Builder{}
sb.WriteString("{\n \"inputs\": {")

// Write inputs
isFirst := true
Expand All @@ -1797,15 +1795,15 @@ func (b *Bundle) generateMetadataJSON(results []OutputFile, allReachableFiles []
if file := &b.files[sourceIndex]; len(file.jsonMetadataChunk) > 0 {
if isFirst {
isFirst = false
j.AddString("\n ")
sb.WriteString("\n ")
} else {
j.AddString(",\n ")
sb.WriteString(",\n ")
}
j.AddBytes(file.jsonMetadataChunk)
sb.WriteString(file.jsonMetadataChunk)
}
}

j.AddString("\n },\n \"outputs\": {")
sb.WriteString("\n },\n \"outputs\": {")

// Write outputs
isFirst = true
Expand All @@ -1819,18 +1817,18 @@ func (b *Bundle) generateMetadataJSON(results []OutputFile, allReachableFiles []
}
if isFirst {
isFirst = false
j.AddString("\n ")
sb.WriteString("\n ")
} else {
j.AddString(",\n ")
sb.WriteString(",\n ")
}
paths[path] = true
j.AddString(fmt.Sprintf("%s: ", js_printer.QuoteForJSON(path, asciiOnly)))
j.AddBytes(result.jsonMetadataChunk)
sb.WriteString(fmt.Sprintf("%s: ", js_printer.QuoteForJSON(path, asciiOnly)))
sb.WriteString(result.jsonMetadataChunk)
}
}

j.AddString("\n }\n}\n")
return j.Done()
sb.WriteString("\n }\n}\n")
return sb.String()
}

type runtimeCacheKey struct {
Expand Down
2 changes: 1 addition & 1 deletion internal/bundler/bundler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (s *suite) expectBundled(t *testing.T, args bundled) {

log = logger.NewDeferLog()
args.options.OmitRuntimeForTests = true
results := bundle.Compile(log, args.options)
results, _ := bundle.Compile(log, args.options)
msgs = log.Done()
assertLog(t, msgs, args.expectedCompileLog)

Expand Down
Loading

0 comments on commit ac70415

Please sign in to comment.