npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@marianmeres/version-monitor

v1.1.0

Published

[![NPM version](https://img.shields.io/npm/v/@marianmeres/version-monitor.svg)](https://www.npmjs.com/package/@marianmeres/version-monitor) [![JSR version](https://jsr.io/badges/@marianmeres/version-monitor)](https://jsr.io/@marianmeres/version-monitor) [

Readme

@marianmeres/version-monitor

NPM version JSR version License: MIT

Detect, in a running client, that the deployed app has changed underneath it — and react (prompt + reload, or reload silently). Framework-agnostic and browser-safe.

It covers two complementary vectors:

  1. ProactivecreateVersionMonitor polls a version manifest (/version.json by default) and compares it to the build's baked version.
  2. ReactiveguardChunkErrors / lazyImport catch the stale-chunk error from a lazy import() whose hashed chunk a deploy has removed, and reload once.

The version source of truth is the version field of package.json / deno.json (deliberately not a git SHA — Docker images don't ship .git).

Install

deno add jsr:@marianmeres/version-monitor
npm install @marianmeres/version-monitor

Usage

Poll + prompt

import { createVersionMonitor, fromJson } from "@marianmeres/version-monitor";

const vm = createVersionMonitor({
	current: window.APP_CONFIG?.APP_VERSION, // your baked build version
	url: "/version.json",
	extract: fromJson("version"),
	interval: 60_000,
	onUpdateAvailable: ({ latest }) => {
		if (confirm(`New version ${latest} available. Reload now?`)) {
			location.reload();
		}
	},
}).start();

Reactive status (Svelte-store compatible)

<script>
	import { createVersionMonitor } from "@marianmeres/version-monitor";
	import { onMount } from "svelte";

	const vm = createVersionMonitor({ url: "/version.json" });
	onMount(() => {
		vm.setCurrent(window.APP_CONFIG.APP_VERSION);
		vm.start();
		return () => vm.destroy();
	});
</script>

{#if $vm.updateAvailable}
	<button onclick={() => location.reload()}>Update to {$vm.latest}</button>
{/if}

Stale-chunk guard

Install this alongside the monitor — it's the safety net for a user who dismisses the update prompt and keeps the tab open (the monitor prompts once, then stays out of the way until the next navigation).

import { guardChunkErrors, lazyImport } from "@marianmeres/version-monitor";

guardChunkErrors(); // global net: reload-once on a stale-chunk error
const Heavy = await lazyImport(() => import("./Heavy.js")); // targeted: retry + reload-once

Authenticated endpoint

createVersionMonitor({
	current: window.APP_CONFIG?.APP_VERSION,
	url: "/health",
	extract: fromHeader("x-version"),
	credentials: "include",
	headers: () => ({ authorization: `Bearer ${getToken()}` }), // getter ⇒ fresh per check
});

Reuse an existing poll (no second request)

The monitor compares two inputs — current (your build) and latest (what's deployed) — each of which you can set manually or let the built-in poll fill. So if you already run a periodic signal whose endpoint can carry the version (e.g. an x-version header on the /ping of @marianmeres/connection-monitor), feed it with setLatest() instead of polling a second time — and don't call start():

import { createConnectionMonitor } from "@marianmeres/connection-monitor";
import { createVersionMonitor } from "@marianmeres/version-monitor";

const vm = createVersionMonitor({
	current: window.APP_CONFIG?.APP_VERSION,
	onUpdateAvailable: ({ latest }) =>
		confirm(`Update to ${latest}?`) && location.reload(),
}); // no .start() — fed externally

createConnectionMonitor({
	url: "/ping",
	fetcher: async (input, init) => {
		const res = await fetch(input, init);
		const v = res.headers.get("x-version");
		if (v) vm.setLatest(v); // reuse the probe as the version signal
		return res; // connection-monitor only times it
	},
}).start();

Read the header synchronously — don't await res.text(), it would consume the body and skew connection-monitor's latency measurement. The latch dedups repeated probes, so you're notified once. The same pattern works for any push source (SSE, WebSocket, a <meta> refresh).

The version contract

This package consumes a manifest; it does not produce one. You own both ends:

  • Serve a manifest (/version.json, an x-version header, or version.txt) from your release flow, built from the single version field.
  • Supply current yourself (recommended: window.APP_CONFIG.APP_VERSION; a bundler define / import.meta.env / <meta> tag work equally well). The library never reads it on its own.
  • Bump the version on every deploy you want announced. The proactive poll fires only when the version field changes; a redeploy at the same version is invisible to vector 1 (vector 2 still catches it reactively).

API

See API.md for complete API documentation.

License

MIT