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

threadpeace

v0.1.1

Published

Move third-party scripts and heavy computations off the main thread with minimal code changes

Readme

npm npm downloads bundle size license docs


Why threadpeace?

Third-party analytics scripts (GTM, GA, Amplitude, Pixel) and CPU-heavy frontend logic both compete for the main thread — causing jank, high Total Blocking Time, and poor Core Web Vitals. threadpeace solves both:

  • Script offloading — change type on a <script> tag, the rest is automatic
  • Function offloading — wrap a function with offload(), call it exactly the same way
  • Task events — real-time progress, completion, and error events
  • Worker pool — automatic pooling with configurable concurrency and strategies
  • Debug overlay — live in-browser panel for worker/task monitoring
npm install threadpeace

Quick start

Script offloading — one attribute change

<!-- Before -->
<script src="https://www.googletagmanager.com/gtag/js?id=G-XXXX"></script>

<!-- After -->
<script type="threadpeace" src="https://www.googletagmanager.com/gtag/js?id=G-XXXX"></script>

Add the bootstrap snippet to <head> before your scripts:

import { injectSnippet } from 'threadpeace/snippet';
injectSnippet({ forward: ['dataLayer', 'gtag', 'fbq'] });

Function offloading

import { init, offload } from 'threadpeace';

init({ pool: { min: 1, max: 4 } });

const processRows = offload((rows: number[]): number => {
  return rows.reduce((acc, n) => acc + n * n, 0);
});

const result = await processRows(myLargeArray); // runs in a worker

Task with progress + cancellation

import { task } from 'threadpeace';

const handle = task(
  (count: number) => {
    for (let i = 0; i < count; i++) {
      heavyWork(i);
      report(i / count); // built-in — no import needed
    }
    return { total: count };
  },
  [10_000],
);

handle
  .on('progress', (pct) => progressBar.set(pct))
  .on('complete', (result) => showDashboard(result))
  .on('error', (err) => handleError(err));

handle.cancel(); // safe to call at any time

// Or just await:
const result = await handle;

How it compares

| Feature | 🧵 threadpeace | Partytown | Comlink | workerize | workerpool | |---|:---:|:---:|:---:|:---:|:---:| | Script offloading (third-party) | ✅ | ✅ | — | — | — | | Function offloading | ✅ | — | ✅ | ✅ | ✅ | | Worker pool (min/max/strategies) | ✅ | — | — | — | ✅ | | Progress events | ✅ | — | — | — | ✅ | | Cancellation | ✅ | — | — | — | ✅ | | Module proxy | ✅ | — | ✅ | — | ✅ | | DOM proxy (window/document) | ✅ | ✅ | — | — | — | | Debug overlay | ✅ | — | — | — | — | | TypeScript-first | ✅ | partial | ✅ | ✅ | ✅ | | Zero runtime dependencies | ✅ | — | ✅ | ✅ | — | | Bundle size (gzipped) | ~15 KB | ~17 KB | ~2 KB | ~1 KB | ~14 KB |

Partytown solves script offloading only. Comlink is a lightweight RPC bridge with no pool or events. workerize requires Webpack and has no pool. workerpool is Node.js-first with no script offloading or debug tooling.


Third-party script compatibility

| Script | Status | Notes | |---|---|---| | Google Tag Manager | ✅ Works | Add dataLayer to forward[] | | Google Analytics (GA4) | ✅ Works | — | | Amplitude | ✅ Works | — | | TikTok Pixel | ✅ Works | — | | Twitter/X Pixel | ✅ Works | — | | Chartbeat | ✅ Works | Enable noCookies mode | | Facebook Pixel | ⚠️ Needs proxy | Requires a CORS reverse proxy — see docs | | Sovrn / Ad-tech | 🧪 Experimental | Start with loadOnMainThread: [/sovrn/] |


Next.js

npm install threadpeace
// next.config.js
const { withThreadPeace } = require('threadpeace/next');
module.exports = withThreadPeace({}, { forward: ['dataLayer', 'gtag', 'fbq'] });
// app/layout.tsx
import { ThreadPeaceScript } from 'threadpeace/next';

export default function RootLayout({ children }) {
  return (
    <html>
      <head>
        <ThreadPeaceScript forward={['dataLayer', 'gtag', 'fbq']} />
        <script type="threadpeace" src="https://www.googletagmanager.com/gtag/js?id=G-XXXX" />
      </head>
      <body>{children}</body>
    </html>
  );
}

Package exports

| Import | Contents | |---|---| | threadpeace | init, offload, task, module, debugBus, getPoolStats, mountDebugOverlay | | threadpeace/next | withThreadPeace, ThreadPeaceScript, useThreadPeace | | threadpeace/snippet | getSnippet, injectSnippet |


Documentation

Full docs at threadpeace.amanagarwal.xyz


License

MIT © Aman Agarwal