Prepare the compiler once
Install the pinned toolchain and build the release WASM compiler. Vite loads this Node-targeted artifact only in its configuration process.
pnpm install
pnpm build:wasmAdd the graph plugin
The plugin snapshots source files below sourceRoot, asks the graph compiler for an exact-or-external result, and serves the emitted modules through Vite's virtual-module convention.
import { createRequire } from "node:module";
import { resolve } from "node:path";
import { preactLoom } from "./integrations/vite-plugin.mjs";
const require = createRequire(import.meta.url);
const { compile_module_graph: compileModuleGraph } = require(
resolve("target/wasm-node/compiler.js")
);
export default {
plugins: [
preactLoom({
compileModuleGraph,
entry: "src/App.tsx",
runtimePath: "runtime/runtime.js",
reportPath: ".preact-loom/eligibility.json"
})
]
};Mount the virtual application
Author normal Preact-shaped TSX, then import the stable virtual entry from the browser bootstrap.
import { useState } from "preact/hooks";
export function App() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Compiled clicks: {count}
</button>
);
}import { createApp } from "virtual:preact-loom/app";
createApp(document).render(
document.querySelector("#app")
);pnpm exec vite --config examples/vite/vite.config.mjsMake eligibility visible
Every build can persist a stable report instead of asking developers to infer compilation from bundle output. It records direct modules, fallback selections, reasons, template-node counts, binding counts, and dependency boundaries.
{
"schemaVersion": 1,
"summary": {
"modules": 1,
"directModules": 1,
"fallbackModules": 0,
"directPercent": 100
},
"modules": [{
"inputPath": "src/App.tsx",
"selection": "direct",
"templateNodes": 2,
"bindings": 2
}]
}