# Data flow — evanw/esbuild

> Canonical page: https://codevetter.com/unpack/esbuild/data-flow

# Data flow — evanw/esbuild

Scanned commit f6058f8364fe7ab91ca57a83e02577ed74c9cae4 (2026-08-09). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

CLI arguments and JS option objects become config.Options and entry points. ScanBundle walks the graph in parallel: resolve, onLoad, parse, then enqueue imports. Cached ASTs must stay immutable. Compile clones the linker graph, tree-shakes, splits chunks, prints, and optionally writes files. Transform skips the real filesystem and feeds stdin bytes through the same two phases. The dev server serves the latest in-memory output instead of those files.
- CLI runImpl reads NODE_PATH (colon-separated, semicolon on Windows) into BuildOptions.NodePaths, and if there are no entry points it reads all of stdin into Stdin.Contents with ResolveDir set from os.Getwd. — [pkg/cli/cli_impl.go#L1198-L1249](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/pkg/cli/cli_impl.go#L1198-L1249)
- A JS build request is a length-prefixed packet whose BuildRequest carries entries, flags, write, stdin bytes, absWorkingDir, nodePaths, plugins, and mangleCache. The Go side parses flags with cli.ParseBuildOptions and calls api.Build. — [lib/shared/stdio_protocol.ts#L1-L21](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/lib/shared/stdio_protocol.ts#L1-L21) [cmd/esbuild/service.go#L597-L604](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/cmd/esbuild/service.go#L597-L604) [cmd/esbuild/service.go#L789](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/cmd/esbuild/service.go#L789)
- contextImpl builds a real FS from AbsWorkingDir, runs loadPlugins once, validates options, and stores a rebuildArgs including caches and onEnd callbacks. Later rebuilds do not re-run plugin setup. — [pkg/api/api_impl.go#L901-L975](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/pkg/api/api_impl.go#L901-L975)
- rebuildImpl calls bundler.ScanBundle(config.BuildCall, ...) then, if the log has no errors, bundle.Compile(..., linker.Link). Each output file is hashed with xxhash into an 8-byte base64 hash stored on OutputFile and in latestHashes. — [pkg/api/api_impl.go#L1515-L1554](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/pkg/api/api_impl.go#L1515-L1554) [pkg/api/api_impl.go#L1488-L1516](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/pkg/api/api_impl.go#L1488-L1516)
- ScanBundle always parses the runtime as source index 0 via globalRuntimeCache.parseRuntime before entry points. The runtime text lives in internal/runtime/runtime.go and is tree-shaken if unused. SourceIndex is the constant 0. — [internal/bundler/bundler.go#L1424-L1441](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/bundler/bundler.go#L1424-L1441) [internal/runtime/runtime.go#L13-L16](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/runtime/runtime.go#L13-L16) [internal/runtime/runtime.go#L63-L67](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/runtime/runtime.go#L63-L67)
- maybeParseFile dedupes by canonical path, copies tsconfig JSX and module-type data (.mjs/.mts vs .cjs/.cts vs package.json type), then starts parseFile on a goroutine. scanAllDependencies reads resultChannel until remaining hits zero and resolves each import record. — [internal/bundler/bundler.go#L1540-L1654](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/bundler/bundler.go#L1540-L1654) [internal/bundler/bundler.go#L2176-L2224](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/bundler/bundler.go#L2176-L2224)
- parseFile runs onLoad plugins unless the input is stdin, maps LoaderDefault through ExtensionToLoader, then dispatches: JS/JSX/TS/TSX to caches.JSCache.Parse, CSS/global-css/local-css to CSSCache.Parse, and JSON to JSONCache.Parse plus LazyExportAST. Import attributes type json, bytes, and text retarget the loader. — [internal/bundler/bundler.go#L124-L186](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/bundler/bundler.go#L124-L186) [internal/bundler/bundler.go#L197-L218](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/bundler/bundler.go#L197-L218) [internal/bundler/bundler.go#L267-L324](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/bundler/bundler.go#L267-L324)
- JSCache.Parse reuses an AST only when source.KeyPath hits and both source contents and js_parser.Options.Equal match. The cache comment forbids mutating cached ASTs and forbids baking in data from other files. — [internal/cache/cache.go#L10-L38](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/cache/cache.go#L10-L38) [internal/cache/cache_ast.go#L152-L188](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/cache/cache_ast.go#L152-L188)
- js_parser.Parse lexes on the fly, parses statements with parseStmtsUpTo, then a second pass splits top-level statements into parts via appendPart, which calls visitStmtsAndPrependTempRefs for binding, lowering, and mangling. — [docs/architecture.md#L70-L78](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/docs/architecture.md#L70-L78) [internal/js_parser/js_parser.go#L17850-L17855](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/js_parser/js_parser.go#L17850-L17855) [internal/js_parser/js_parser.go#L18023-L18034](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/js_parser/js_parser.go#L18023-L18034) [internal/js_parser/js_parser.go#L17682-L17687](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/js_parser/js_parser.go#L17682-L17687)
- Compile either links all entry points together (code splitting, or a single entry) or forks one linker goroutine per entry point. linker.Link clones the graph, calls scanImportsAndExports, treeShakingAndCodeSplitting, computeChunks, mangles props under ExclusiveMangleCacheUpdate, then generateChunksInParallel. Metafile JSON is generated only when NeedsMetafile is set. — [internal/bundler/bundler.go#L3050-L3130](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/bundler/bundler.go#L3050-L3130) [internal/linker/linker.go#L243-L349](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/linker/linker.go#L243-L349)
- When write is true and not stdout, rebuildImpl deletes paths present in oldHashes but not newHashes, skips writes whose on-disk bytes already match, and otherwise MkdirAll 0755 plus WriteFile 0666 or 0777 for executables. OnEnd callbacks run after writes. Errors suppress writing (issue 3643 is cited in code). — [pkg/api/api_impl.go#L1558-L1647](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/pkg/api/api_impl.go#L1558-L1647)
- Transform builds options with Stdin.Contents set to the input string, uses fs.MockFS, and calls ScanBundle(config.TransformCall) then Compile. Results are split into code, a .map file, and a .LEGAL.txt file by path suffix. — [pkg/api/api_impl.go#L1782-L1833](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/pkg/api/api_impl.go#L1782-L1833) [pkg/api/api_impl.go#L1844-L1859](https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/pkg/api/api_impl.go#L1844-L1859)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
