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

@madenowhere/phaze-vite

v0.0.5

Published

Vite/Rollup helpers for Phaze: HMR that re-mounts the changed component instead of reloading the page, plus `phazeChunks` for `manualChunks`. Use alongside @madenowhere/phaze-compile (which handles JSX → DOM compilation).

Downloads

393

Readme

@madenowhere/phaze-vite

Vite plugin for Phaze. HMR for components without a full page reload.

When you edit a .tsx file, Vite normally walks up the import chain looking for a module that accepts its own update. Phaze components don't accept updates by default — so any edit triggers a full page reload, losing all in-page state.

This plugin appends an import.meta.hot.accept(…) callback to every user .tsx / .jsx file. When the file changes, the new module's default export replaces the old one in any active mount, in place. No page reload, no scroll position lost, no module-scope state cleared.

Install

pnpm add -D @madenowhere/phaze-vite
// vite.config.ts (plain Phaze + Vite)
import { defineConfig } from 'vite'
import phazeVite from '@madenowhere/phaze-vite'

export default defineConfig({
  plugins: [phazeVite()],
})
// astro.config.mjs (Astro + Phaze)
import { defineConfig } from 'astro/config'
import phaze from '@madenowhere/phaze-astro'
import phazeVite from '@madenowhere/phaze-vite'

export default defineConfig({
  integrations: [phaze()],
  vite: { plugins: [phazeVite()] },
})

How it works

The plugin runs in dev only (apply: 'serve') and enforce: 'post' so it sees source after @madenowhere/phaze-compile's JSX transform. For each .tsx / .jsx file under your source tree (anything outside node_modules), it appends:

if (import.meta.hot) {
  const __phaze_url__ = import.meta.url
  import.meta.hot.accept((m) => {
    const r = globalThis.__PHAZE_HMR_REPLACE__
    if (r && m && typeof m.default === 'function') r(__phaze_url__, m.default)
  })
}

The handler at globalThis.__PHAZE_HMR_REPLACE__ is set by:

  • @madenowhere/phaze-astro — when you use the Astro renderer, its client.ts installs an astro-island-aware handler. Mounts are tracked by the component-url attribute on each <astro-island>.
  • @madenowhere/phaze-vite/runtime — for plain Phaze apps that don't use Astro. Import once at app entry; provides track() / replace() and installs the global handler.

If neither is present, the boilerplate is a silent no-op and Vite falls back to its default behavior (look up the import chain for an accept, otherwise full reload).

Direct (non-Astro) usage

// src/main.ts
import { hydrate } from 'phaze'
import { track } from '@madenowhere/phaze-vite/runtime'
import App from './App.tsx'

const root = document.getElementById('app')!
track(import.meta.url, root, hydrate, App, {})

When App.tsx is edited, the plugin's emitted code calls replace(url, NewApp), which re-mounts at the same root with the new component. Component-local signals reset; module-scope signals (defined outside the component) survive because Vite's HMR re-evaluates only the changed module — anything imported from a separate file keeps its old instance until that file changes.

What survives an edit (today, Tier 1)

| state | survives a .tsx edit? | |---|---| | Module-scope signals (in a separate state.ts) | yes | | Module-scope signals in the edited file itself | no — module re-evaluates, fresh signals | | Component-local signal() defined inside the component body | no — fresh signals on remount | | Scroll position | yes | | Other islands on the page (their state, focus, signals) | yes | | <input> focus inside the edited component | no — DOM re-mounted |

Tier 2 (transferring component-local signal values when only the template changed) is on the roadmap. Tier 1 is already a substantial dev-loop improvement over full-page reloads.

Test

test/runtime.test.ts covers the registry — track(), replace(), multiple mounts of the same URL, dispose semantics, and the globalThis.__PHAZE_HMR_REPLACE__ install.

Trade-off summary

What you get: dev edits update the page in place instead of reloading. What it costs: ~120 bytes of boilerplate appended per dev-served .tsx file. Stripped from production builds (apply: 'serve'). What you don't get yet: in-component signal-state preservation. The component re-mounts cleanly; everything inside resets.