Tool to quickly inspect effective changes between versions
Diff two npm package versions entirely in the browser. Built as a static site
(no server, no backend) on top of Vuetify0.
The original manual workflow this replaces:
# download + extract two tarballs, then:
diff -r --exclude="*.map" --exclude="*.d.ts" \
./vuetify-4.1.0/package/lib \
./@vuetify__nightly-4.1.0-master.../package/lib
…now happens with two inputs and a button. The default comparison is the user’s
real use-case: vuetify@latest vs @vuetify/nightly@latest.
Everything heavy runs in a Web Worker so the main thread stays responsive:
registry.npmjs.org (sendsAccess-Control-Allow-Origin: *, so no proxy needed) and turn a version orlatest into a concrete tarball URL..tgz, storing bytes in the Cache StorageDecompressionStream('gzip') (no WASMprefix long names, PAX (x) and GNU (L) headers. The leading package/similar crate)lib / dist / other), a virtualized file@pierre/trees) with A/M/D status, and a@pierre/diffs).The sidebar uses @pierre/trees and the content pane uses @pierre/diffs — both
via their framework-agnostic vanilla cores (no React), wrapped in thin Vue
components (PierreTree.vue, PierreFileDiff.vue) that render into a container
element and clean up on unmount.
Crucially, @pierre/diffs renders from a unified patch, not the full file:
we prepend ---/+++ headers to the WASM patch and hand it to processFile(),
so a multi-MB minified dist file with a small change is still a tiny render.
It also virtualizes long diffs. Highlighting is off (forcePlainText, i.e. no
Shiki highlighter is loaded) — Pierre keeps its gutters/line-numbers/±backgrounds
but downloads no language grammars. Theming maps --v0-* → Pierre’s
--diffs-*-override / --trees-theme-* custom properties.
Note: importing
@pierre/diffsstatically bundles Shiki, sodist/emits many
lazy per-language grammar chunks. They are never fetched at runtime in
plain-text mode, but they do inflate the build output.
wasm/ Rust crate → public/diff.wasm (C-ABI, no wasm-bindgen)
public/diff.wasm prebuilt module, served statically
src/lib/
registry.ts npm packument resolution + version listing
fetch-tarball.ts Cache-Storage-backed tarball fetch
tar.ts DecompressionStream gunzip + tar parser
wasm-diff.ts loads diff.wasm, marshals strings in/out of memory
diff-engine.ts tree diff orchestration (pure, runs in worker)
types.ts shared, structured-clone-safe types
src/worker/diff.worker.ts the pipeline, off the main thread
src/composables/useDiff.ts main-thread reactive handle for the worker
src/components/ DiffApp (Vuetify0 + UnoCSS) + PierreTree / PierreFileDiff wrappers
scripts/verify.mjs Node end-to-end check against real npm packages
pnpm install
pnpm dev
pnpm build:wasm # only needed when wasm/ changes — output is committed
pnpm build # type-check + vite build → dist/ (deploy anywhere static)
pnpm preview # serve dist/ locally
dist/ is a fully static bundle: index.html, hashed JS/CSS, the worker chunk,
and diff.wasm (served with application/wasm). Drop it on any static host.
Requires the Rust toolchain and the wasm target:
rustup target add wasm32-unknown-unknown
pnpm build:wasm
Runs the real fetch → gunzip → untar → WASM-diff path in Node against live npm:
node scripts/verify.mjs # vuetify vs @vuetify/nightly
node scripts/verify.mjs vue 3.5.0 vue 3.5.13 # any two name@version pairs