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

nitfixer

v0.4.0

Published

Tags React, Vue and Svelte components with stable ids and emits a source manifest so nitfixer can trace feedback back to source on production builds.

Downloads

459

Readme

nitfixer

Vite plugin for nitfixer. It tags your React components with stable ids at build time and emits a source manifest, so feedback pinned on a production build can be traced back to the exact file and line.

Install

pnpm add -D nitfixer

Use

// vite.config.ts
import react from '@vitejs/plugin-react';
import { nitfixer } from 'nitfixer/vite';
import { defineConfig } from 'vite';

export default defineConfig({
    plugins: [react(), nitfixer()],
});

A build writes .nitfixer/build/nitfixer-manifest.json, and vite dev keeps .nitfixer/manifest.json up to date. Add .nitfixer/ to your .gitignore.

Both paths sit outside your build output on purpose. The manifest lists your component names and source file paths, so anything inside dist/ would be served publicly by your host. CI reads it straight from the checkout after vite build — the nitfixer Action finds .nitfixer/build/nitfixer-manifest.json with no manifest: input to set — and authenticates with GitHub OIDC, so there is no secret to store either.

If your app also runs an SSR build, that environment writes nitfixer-manifest.ssr.json next to the client manifest rather than overwriting it. Only the client manifest has components in it, and that is the one CI uploads.

Vue and Svelte

The same plugin handles Vue 3 and Svelte 5 single-file components. Their components compile away at runtime, so instead of a property on a component function every element in a component's template is stamped with data-nitfixer="<component id>", and the browser extension rebuilds the component chain by walking DOM ancestors. Child components, <template> wrappers, <slot> outlets and <svelte:element> are left alone, so each component contributes exactly one id.

Install vue or svelte next to the plugin (they are optional peer dependencies, loaded only when a .vue or .svelte file is transformed) and register nitfixer() before the framework plugin:

// vite.config.ts
import vue from '@vitejs/plugin-vue';
import { nitfixer } from 'nitfixer/vite';

export default defineConfig({
    plugins: [nitfixer(), vue()],
});
// vite.config.ts
import { svelte } from '@sveltejs/vite-plugin-svelte';
import { nitfixer } from 'nitfixer/vite';

export default defineConfig({
    plugins: [nitfixer(), svelte()],
});

The manifest lists one entry per component, named after the file (pricing-card.svelte becomes PricingCard), with the line of the first element in its template. The build id import lands inside the component's script block (one is added when the file has none).

Caching

Vite's output is content-hashed, which is what makes it safe to serve with Cache-Control: public, max-age=31536000, immutable. This plugin writes window.__NITFIXER_BUILD_ID__ into that output, so it owes you the same guarantee, and from 0.3.0 it keeps it:

Two builds with different build ids never produce byte-identical assets under the same file names. The build id is substituted before the bundler computes each chunk's content hash, not after, so a chunk carrying a build id is renamed whenever that id changes.

Expect that rename to spread. A chunk's hash covers the names of the chunks it imports, so everything that (transitively) imports the chunk holding the build id is renamed too. With the default inject: 'modules' the id lands in a chunk shared by your tagged components, which in a typical app means most of the JavaScript graph gets new names on every new build id — the cost of an id you can actually trust. If you would rather confine it, inject: 'entry' puts the assignment in the entry chunks, which nothing imports, so only those are renamed.

It follows that you must not serve the build id from a path whose name doesn't change with it:

  • index.html (and any inject: 'html' script tag inside it) is not content-hash-named, so it must not be cached immutably. Standard Vite guidance already says this; scope your immutable rule to the hashed assets directory, e.g. /build/assets/*.
  • emitToBundle: true writes nitfixer-manifest.json to a fixed, unhashed file name, and its contents change every build. Another reason to leave that option off; if you do use it, serve that file with a short cache lifetime.

If you deployed 0.1.0 or 0.2.0 behind a CDN, assets already pinned under an old name still carry that build's id. Purge the CDN cache for your assets directory once after upgrading — after that, renames do the work.

Options

| Option | Default | What it does | | --------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | | inject | 'modules' | How window.__NITFIXER_BUILD_ID__ reaches the page: 'modules', 'html', 'entry' or 'none'. | | manifestPath | '.nitfixer/build/nitfixer-manifest.json' | Where a build writes the manifest — absolute, or relative to the Vite root. Keep it out of your build output. | | emitToBundle | false | Also emit the manifest as a build asset. This publicly exposes your component names and source paths. | | devManifest | '.nitfixer/manifest.json' | Where the dev server writes its manifest, relative to the Vite root. false turns it off. | | manifestFileName (deprecated) | 'nitfixer-manifest.json' | File name of the build manifest inside the default .nitfixer/build/ directory. Use manifestPath instead. |

0.4.0

Adds Vue 3 and Svelte 5 support (see above). Nothing changes for React projects; vue and svelte are optional peer dependencies, only loaded when a .vue or .svelte file is transformed.

Upgrading from 0.2.0

0.2.0 and earlier substituted the real build id in Rollup's generateBundle hook — after content hashes had been computed. A chunk whose other content was unchanged between two builds therefore kept the same file name while carrying a different build id, so a CDN or a warm browser cache went on serving the first build's copy. Pages reported a stale build id, and feedback captured on them matched no source mapping (or the wrong one) and never resolved to a file and line. 0.3.0 substitutes the id before hashing instead — see Caching. To upgrade:

  • Bump the dependency. There are no API or option changes.
  • Purge your CDN cache for the assets directory once, so clients stop being served assets pinned under a name from an older build id.
  • If you pin NITFIXER_BUILD_ID in CI (recommended — it makes the id identical wherever the assets are built), nothing else changes: that id is now baked straight into the module graph rather than patched in afterwards.

Upgrading from 0.1.0

0.1.0 emitted the manifest as a build asset, so it shipped inside dist/ and was served publicly. 0.2.0 writes it to .nitfixer/build/nitfixer-manifest.json instead. To upgrade:

  • Add .nitfixer/ to .gitignore if it isn't there already.
  • Drop the manifest: input from the nitfixer Action (v1.1.0 or newer resolves the new path itself), or point it at .nitfixer/build/nitfixer-manifest.json.
  • Delete any nitfixer-manifest.json already deployed with an older build — 0.2.0 stops producing it but does not remove what is already on your host.

With inject: 'none', wire the build id up yourself:

import 'virtual:nitfixer-build-id/global';

License

MIT