webpack-bundle-tracker
A webpack plugin that writes a JSON stats file mapping entry names to their hashed output assets, so backends like Django can resolve bundle filenames after every build.
Repository Health
Technical Analysis
webpack-bundle-tracker is a small webpack plugin, maintained under the django-webpack organization, that solves one specific problem: webpack renames output files with content hashes on every build (app-0828904584990b611fb8.js), but a server-rendered backend needs a stable way to know which hashed filename corresponds to which entry point right now. The plugin hooks into webpack’s compile, emit, and done lifecycle events and writes a webpack-stats.json file describing the current build status, the chunks produced for each entry, and the resolved asset paths and public URLs for each output file.
It’s the foundation of the django-webpack-loader integration pattern: Django templates read the stats file at request time to emit the correct <script>/<link> tags for whatever webpack most recently produced, without the backend needing to parse webpack’s own manifest format or hardcode filenames. The same status-file approach also makes the plugin useful outside Django specifically, for any server that needs to react to “is webpack still compiling” versus “the build just finished” versus “the build just failed.”
Options cover the practical concerns of that use case: relativePath and publicPath for how asset URLs are expressed, integrity and integrityHashes for emitting Subresource Integrity hashes per asset, logTime for build timing, and indent for human-readable output. The plugin supports both Webpack 4 and Webpack 5 (tested against both in CI) and ships its own TypeScript type definitions.
What You Get
- A
webpack-stats.jsonfile (or any filename you choose) updated on everycompile/emit/donecycle, reflectingcompile,done, orerrorstatus - Per-entry chunk-to-asset-file mappings, so a template can resolve
appto its current hashed.jsfile - Resolved asset paths and public URLs per output file, with optional
relativePathoutput relative to the stats file’s own directory - Optional Subresource Integrity hashes (
sha256/sha384/sha512, configurable) computed per asset via theintegrityoption - Structured error output (
status: "error"plus the failing file, error name, and message) when a compilation fails, instead of a stale or missing stats file - First-class TypeScript typings (
typings.d.ts) for the plugin constructor and itsOptions/Contentsshapes
Common Use Cases
- Django + webpack integration - pairing with
django-webpack-loaderso Django templates can render<script>tags for whatever hashed bundle webpack most recently built, in dev and production alike - Any server-rendered backend needing hashed asset resolution - Rails, Flask, or a custom Node server reading the same stats file to avoid hardcoding webpack’s content-hashed filenames
- Build status polling - a dev server or CI step reading the
statusfield to detect whether webpack is still compiling, finished, or failed, without shelling out to webpack’s own CLI output - Subresource Integrity (SRI) rollout - generating per-asset integrity hashes at build time so a template layer can attach
integrityattributes to script/link tags - Multi-target builds with
compression-webpack-plugin- tracking.br/.gzcompressed variants alongside the original asset so a backend can pick the best available encoding
Under The Hood
Architecture
The entire plugin lives in a single class, BundleTrackerPlugin in lib/index.js, that registers itself with webpack’s compiler via apply(compiler) and taps the compile, emit, and done lifecycle hooks. State (this.contents, this.assets) is held on the instance and mutated across those callbacks: _handleCompile marks the file as mid-build, _handleEmit walks compilation.assets to record each output file’s path (and, if requested, its integrity hash), and _handleDone reads webpack’s Stats object to either report the first compilation error (recursing into child compilations) or the final chunk-to-file mapping. Every write flows through _writeOutput, which merges new data into the existing tracked contents and re-sorts keys before serializing, so partial rebuilds don’t thrash the output file. The one piece of separated concern is ANSI-stripping, pulled into its own lib/utils/stripAnsi.js module. Because the plugin’s contract with consumers is entirely the shape of the emitted JSON file, any change to how _writeOutput structures status/chunks/assets would be a breaking change for every downstream reader (most notably django-webpack-loader).
Tech Stack
It’s plain, dependency-free JavaScript targeting Node 16+, using only Node’s built-in path, fs, and crypto modules at runtime — there’s no bundling step for the library itself, lib/ ships as-is. Webpack itself is an implicit peer dependency (not declared in package.json), with the test suite exercising both webpack@4 and webpack5 (aliased via npm) to guarantee cross-version compatibility. Hand-maintained TypeScript typings in typings.d.ts are checked post-test via tsc rather than compiled from source. Dev tooling includes Jest with jest-extended for assertions, ESLint and Prettier for style enforcement (run as a pretest gate), and standard-version/commitizen for release and commit conventions.
Code Quality
The project has substantial test coverage for its size — two large suites (tests/base.test.js and tests/webpack5.test.js, together nearly 1,900 lines) exercise the plugin against real webpack compilations under both major webpack versions, backed by fixture projects. CI runs this suite via GitHub Actions across multiple Node versions on every push and PR, gated by a pretest Prettier check and a posttest TypeScript check. Error handling is explicit rather than swallowed: the constructor throws a descriptive error for a misconfigured filename containing a path separator, and compilation failures are walked recursively across child compilations so the first real error surfaces in the stats file instead of being silently dropped. Naming is consistent (a leading underscore marks internal/private methods), and JSDoc type annotations give the plain-JS source a lightweight static-typing layer even without a build step.
API Design
The public surface is intentionally narrow: instantiate new BundleTrackerPlugin(options) and add it to webpack’s plugins array, with every option carrying a sensible default (output path falls back to webpack’s own output.path, filename defaults to webpack-stats.json). Its distinguishing design choice is the SRI integrity option — computing per-asset sha256/sha384/sha512 hashes at build time is a capability comparable output-manifest plugins in this space don’t universally offer, and it’s exposed as a single boolean plus a configurable hash-algorithm list. The tradeoff for that simplicity is an undocumented, implicit peer dependency on webpack itself, and consumers only discover the exact JSON shape through the README’s example output rather than a hard schema.