update-notifier-cjs pulls 46 packages into superstatic's dependency tree to check
whether a newer version has been published. That is 46 packages to resolve, audit and
trust, in service of one request to the registry and a box drawn on stderr. It is also
a fork that exists only because upstream update-notifier went ESM-only, and its last
release was January 2025.
I would like to propose replacing it with nano-update-notifier, which implements the
same public API — same options, same notifier.update shape, same suppression rules —
on Node.js built-ins alone, with no runtime dependencies. It ships both ESM and CommonJS
entry points, so the existing require keeps working.
The change is two lines: the manifest entry, and
-const updateNotifier = require("update-notifier-cjs");
+const updateNotifier = require("nano-update-notifier");
in src/bin/server.ts.
Measured
Against nano-update-notifier@1.1.0 at superstatic 4bd82b9, on Node 22.14.0 and
npm 10.9.2. Every row is a real run — npm ci on a clean checkout, then the two-line
change, then npm install:
|
|
| Dependency delta |
added 1 package, and removed 46 packages — npm's own words. 536 installed entries down to 491 |
npm run build |
clean, exit 0 |
npm run lint |
994 problems, 0 errors — identical to the same run before the change |
npm run test-unit |
181 passing, 10 pending, 19 failing — identical to the run before the change, and the set of failing test titles diffs empty against it |
Those 46 entries are 39 distinct package names. Five of them — camelcase,
graceful-fs, semver, strip-json-comments and type-fest — are nested copies whose
name survives elsewhere in the tree, and ini goes from three paths at once. I lead
with 46 because that is what npm install prints; the 39 below is the list of names.
The 19 failures are pre-existing on my machine, all trailing slash cases, which look
like Windows path handling rather than anything related to this change. What matters is
that the swap does not move them.
The 39 names: @pnpm/config.env-replace, @pnpm/network.ca-file, @pnpm/npm-conf,
ansi-align, boxen, ci-info, cli-boxes, config-chain, configstore,
crypto-random-string, deep-extend, dot-prop, escape-goat, global-dirs,
has-yarn, import-lazy, ini, is-ci, is-installed-globally, is-npm, is-obj,
is-yarn-global, isomorphic-fetch, minimist, node-fetch, proto-list, pupa,
rc, registry-auth-token, registry-url, semver-diff, tr46, unique-string,
update-notifier-cjs, webidl-conversions, whatwg-fetch, whatwg-url,
widest-line, xdg-basedir.
The rendered notification is not byte-identical, and here is exactly how
I rendered the notification through superstatic's own call — updateCheckInterval of
one week, shouldNotifyInNpmScript: true — under both libraries and diffed the output.
Eight lines on each side. Lines 2 through 7, the borders, the padding and both text
lines, are byte-identical. Lines 1 and 8 are the blank margin lines, and they differ:
update-notifier-cjs renders through boxen 5, which emits a yellow-open escape
immediately followed by a yellow-close on those lines.
nano-update-notifier replicates boxen 7, which emits nothing.
Each of those two lines is 10 bytes under update-notifier-cjs — the escape pair
ESC[33m ESC[39m with nothing between them — and 0 bytes here, so the whole output
differs by 20 bytes and nothing else. On the run I measured that was 601 bytes against
581. Both render as a blank line in any terminal, and stripping ANSI makes the two
byte-equal. I would rather state that than claim an equality I cannot support.
How compatibility is held
Differential test suites run update-notifier, boxen, wrap-ansi, semver and
string-width as oracles: the full box option matrix, notification rendering with
colour enabled, ANSI-aware wrapping, and fuzzed version comparison. 300 tests, green on
Ubuntu, Windows and macOS across Node 18, 22 and 24. The package is published from a
GitHub Actions release through npm trusted publishing, with SLSA provenance attached.
Not verified
test-integration, and any run on Linux or macOS — I measured on Windows.
Two things worth raising
Disclosure: I wrote nano-update-notifier. That is why this is an issue rather than
a pull request. CONTRIBUTING asks for discussion before a larger contribution, and a
proposal to adopt my own package deserves that more than most. If this is not something
you want to take on, saying so costs you nothing and I will not push it.
I understand the Google CLA is needed before anything can merge, and I am happy to sign
it. CONTRIBUTING notes it is not required until after review, so I am raising the idea
first rather than signing speculatively.
update-notifier-cjspulls 46 packages into superstatic's dependency tree to checkwhether a newer version has been published. That is 46 packages to resolve, audit and
trust, in service of one request to the registry and a box drawn on stderr. It is also
a fork that exists only because upstream
update-notifierwent ESM-only, and its lastrelease was January 2025.
I would like to propose replacing it with
nano-update-notifier, which implements thesame public API — same options, same
notifier.updateshape, same suppression rules —on Node.js built-ins alone, with no runtime dependencies. It ships both ESM and CommonJS
entry points, so the existing
requirekeeps working.The change is two lines: the manifest entry, and
in
src/bin/server.ts.Measured
Against
nano-update-notifier@1.1.0at superstatic4bd82b9, on Node 22.14.0 andnpm 10.9.2. Every row is a real run —
npm cion a clean checkout, then the two-linechange, then
npm install:added 1 package, and removed 46 packages— npm's own words. 536 installed entries down to 491npm run buildnpm run lintnpm run test-unitThose 46 entries are 39 distinct package names. Five of them —
camelcase,graceful-fs,semver,strip-json-commentsandtype-fest— are nested copies whosename survives elsewhere in the tree, and
inigoes from three paths at once. I leadwith 46 because that is what
npm installprints; the 39 below is the list of names.The 19 failures are pre-existing on my machine, all
trailing slashcases, which looklike Windows path handling rather than anything related to this change. What matters is
that the swap does not move them.
The 39 names:
@pnpm/config.env-replace,@pnpm/network.ca-file,@pnpm/npm-conf,ansi-align,boxen,ci-info,cli-boxes,config-chain,configstore,crypto-random-string,deep-extend,dot-prop,escape-goat,global-dirs,has-yarn,import-lazy,ini,is-ci,is-installed-globally,is-npm,is-obj,is-yarn-global,isomorphic-fetch,minimist,node-fetch,proto-list,pupa,rc,registry-auth-token,registry-url,semver-diff,tr46,unique-string,update-notifier-cjs,webidl-conversions,whatwg-fetch,whatwg-url,widest-line,xdg-basedir.The rendered notification is not byte-identical, and here is exactly how
I rendered the notification through superstatic's own call —
updateCheckIntervalofone week,
shouldNotifyInNpmScript: true— under both libraries and diffed the output.Eight lines on each side. Lines 2 through 7, the borders, the padding and both text
lines, are byte-identical. Lines 1 and 8 are the blank margin lines, and they differ:
update-notifier-cjsrenders through boxen 5, which emits a yellow-open escapeimmediately followed by a yellow-close on those lines.
nano-update-notifierreplicates boxen 7, which emits nothing.Each of those two lines is 10 bytes under
update-notifier-cjs— the escape pairESC[33mESC[39mwith nothing between them — and 0 bytes here, so the whole outputdiffers by 20 bytes and nothing else. On the run I measured that was 601 bytes against
581. Both render as a blank line in any terminal, and stripping ANSI makes the two
byte-equal. I would rather state that than claim an equality I cannot support.
How compatibility is held
Differential test suites run
update-notifier,boxen,wrap-ansi,semverandstring-widthas oracles: the full box option matrix, notification rendering withcolour enabled, ANSI-aware wrapping, and fuzzed version comparison. 300 tests, green on
Ubuntu, Windows and macOS across Node 18, 22 and 24. The package is published from a
GitHub Actions release through npm trusted publishing, with SLSA provenance attached.
Not verified
test-integration, and any run on Linux or macOS — I measured on Windows.Two things worth raising
Disclosure: I wrote
nano-update-notifier. That is why this is an issue rather thana pull request. CONTRIBUTING asks for discussion before a larger contribution, and a
proposal to adopt my own package deserves that more than most. If this is not something
you want to take on, saying so costs you nothing and I will not push it.
I understand the Google CLA is needed before anything can merge, and I am happy to sign
it. CONTRIBUTING notes it is not required until after review, so I am raising the idea
first rather than signing speculatively.