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

@shadow-js/vite

v1.0.4

Published

A Vite plugin that compiles your JSX, builds for server rendering and sets up Vitest

Readme

@shadow-js/vite

The Vite plugin for ShadowJS. It runs @shadow-js/compiler on every .jsx and .tsx file before Vite's own JSX handling, so the code Vite sees contains no JSX. In an SSR build it emits the server target. It also points Vite's dependency scanning at the ShadowJS JSX runtime types, de-duplicates @shadow-js/core and @shadow-js/web, and configures Vitest for DOM tests. Vite is the only supported host in 1.0.0; this is a plain Vite plugin, not an unplugin.

Install

npm install -D @shadow-js/vite vite

Requires Vite 7 or 8 (vite is an optional peer dependency, ^7.0.0 || ^8.0.0). @shadow-js/compiler is installed as a dependency.

Example

Add the plugin to vite.config.ts. The named export shadow and the default export are the same function.

import shadow from "@shadow-js/vite";
import { defineConfig } from "vite";

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

The plugin is an ordinary Vite plugin object, so its behavior can be checked without starting a server: call its config and transform hooks the way Vite does. In a production build a .tsx file comes back compiled, files the plugin does not handle come back as null, and an SSR transform imports from @shadow-js/web/server.

import shadow from "@shadow-js/vite";

type Config = (config: object, env: { command: string; mode: string }) => unknown;
type Transform = (
  this: { error(message: string): never },
  code: string,
  id: string,
  options?: { ssr?: boolean },
) => { code: string } | null;

const plugin = shadow();
const config = plugin.config as Config;
const transform = plugin.transform as Transform;
const context = {
  error(message: string): never {
    throw new Error(message);
  },
};

config({}, { command: "build", mode: "production" });

const source = "export const App = () => <button>hi</button>;";
const compiled = transform.call(context, source, "/app/app.tsx");
const server = transform.call(context, source, "/app/app.tsx", { ssr: true });

console.log(plugin.name, plugin.enforce);
console.log(`compiled: ${compiled?.code.includes("template(") === true}`);
console.log(`plain ts: ${transform.call(context, "export const n = 1;", "/app/n.ts")}`);
console.log(`ssr: ${server?.code.includes("@shadow-js/web/server") === true}`);

Testing with Vitest

Tests need the compiler too. Use the same plugin in vitest.config.ts. When the test environment is happy-dom or jsdom the plugin selects the browser build of ShadowJS and inlines it; with a node environment it keeps the server build. Set domTests explicitly if you pick the environment per file; tests that call renderToString want domTests: false.

import shadow from "@shadow-js/vite";
import { defineConfig } from "vitest/config";

export default defineConfig({
  plugins: [shadow()],
  test: { environment: "happy-dom" },
});

With Vitest projects the environment is set per project, and a plugin in the root plugins cannot see it. Give the DOM project its own plugin with domTests: true (it then also inlines @shadow-js/* for that project only); a node project keeps the server build:

import shadow from "@shadow-js/vite";
import { defineConfig } from "vitest/config";

export default defineConfig({
  plugins: [shadow()],
  test: {
    projects: [
      { extends: true, test: { name: "node", environment: "node", include: ["src/**/*.test.ts"] } },
      {
        extends: true,
        plugins: [shadow({ domTests: true })],
        test: { name: "dom", environment: "happy-dom", include: ["src/**/*.dom.test.tsx"] },
      },
    ],
  },
});

Options

shadow(options?) takes a ShadowPluginOptions object.

| Option | Default | Description | | --- | --- | --- | | include | /\.[cm]?[jt]sx$/ | Files to compile. A g or y flag is ignored. | | exclude | node_modules | Files to skip. | | moduleName | @shadow-js/web | Module the compiled code imports runtime helpers from. | | autoReactive | true | Keep constants computed from reactive reads live without a function (forgiving reactivity). | | hmr | true | Hot-update components in place during vite dev. | | dev | Vite dev mode | Force development output (component names, extra checks). | | domTests | detected | Run the browser build under Vitest. On by default for happy-dom and jsdom. | | compiler | "auto" | Which compiler implementation runs: "auto" (the fastest available), "native" (the Rust or WebAssembly build; throws when only the TypeScript one is available) or "javascript" (the TypeScript implementation only). | | plugins | none | Compiler plugins (CompilerPlugin from @shadow-js/compiler) that run in the build on every compiled module. Validated when shadow() is called; errors fail the build with the plugin's name and the position, warnings go to Vite's log. |

Hot updates

The plugin turns on the compiler's hmr option in vite dev (never in a build, for SSR transforms or under a test runner). The compiled module registers its top-level components with @shadow-js/web/hmr, so an edit re-renders the instances of the edited component while parents and siblings keep their state; a module that exports only components accepts its own update. This is covered by the unit tests of the compiler and of the plugin ([HMR-01] to [HMR-06], [VIT-04]). The browser test tier also exercises hot updates in a real browser.

MDX

@shadow-js/vite/mdx compiles .mdx files into components. Install @mdx-js/mdx (an optional peer) and list shadowMdx() next to shadow():

import shadow from "@shadow-js/vite";
import { shadowMdx } from "@shadow-js/vite/mdx";

export default { plugins: [shadowMdx(), shadow()] };

shadowMdx(options?) takes include (default .mdx), exclude, remarkPlugins, rehypePlugins, recmaPlugins, remarkRehypeOptions, providerImportSource, elements ("overridable" looks up each Markdown element in the components prop; "static" renders them from the template), mdx (the compiler's module name or your own function), plugins and moduleName. The MDX guide covers components, frontmatter and content collections. For types, add /// <reference types="@shadow-js/vite/mdx-env" /> to a .d.ts file.

API

Entry @shadow-js/vite. The exports are:

| Export | Description | | --- | --- | | shadow | Returns the Vite plugin: name shadowjs, enforce: "pre", with config and transform hooks. | | default | The same function as shadow. | | ShadowPluginOptions | The options type. |

Entry @shadow-js/vite/mdx:

| Export | Description | | --- | --- | | shadowMdx | Returns the MDX plugin: name shadowjs-mdx, enforce: "pre". | | ShadowMdxOptions, MdxCompile | The options type and the shape of the mdx function. |

@shadow-js/vite/mdx-env holds types only (*.mdx and *.md modules).

Links

Dependencies

  • Runtime @shadow-js/compiler 1.0.4: compiles component sources in the Vite plugin (src/index.ts).
  • Optional peers: vite ^7.0.0 || ^8.0.0: the host for the plugin and the Plugin type (src/index.ts, src/mdx.ts); @mdx-js/mdx ^3.0.0: compiles MDX (src/mdx.ts).

Types

  • Names from the root: ShadowPluginOptions. Names from @shadow-js/vite/mdx: ShadowMdxOptions, MdxCompile.

Support

  • Node.js >=22.12.0. ESM only: use import; require is not supported.
  • Browsers: not applicable; the package has no browser target.
  • Versioning: every @shadow-js/* package releases together at one version. Upgrade them as one set.
  • Documentation: ShadowJS documentation.