Preact
The React bindings run on Preact through preact/compat — the SDK imports only react (no react-dom, no JSX runtime), so one alias covers it. Requires Preact ≥ 10.11 (preact/compat gained useSyncExternalStore there). Every binding runs through this alias in the SDK's own CI.
Vite
@preact/preset-vite sets up the JSX transform and the react → preact/compat aliases in one step:
// vite.config.ts
import preact from "@preact/preset-vite";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [preact()],
});Without the preset, alias manually and point the JSX transform at Preact:
// vite.config.ts
import { defineConfig } from "vite";
export default defineConfig({
resolve: {
alias: {
react: "preact/compat",
"react-dom": "preact/compat",
},
},
esbuild: {
jsxImportSource: "preact",
},
});For TypeScript, mirror the alias so the bindings' React types resolve:
// tsconfig.json
{
"compilerOptions": {
"jsxImportSource": "preact",
"paths": {
"react": ["./node_modules/preact/compat"],
"react-dom": ["./node_modules/preact/compat"],
},
},
}Usage
Identical to React — same imports, same components:
import { Feature, GatesProvider } from "@lucerna-dev/gates-browser/react";
import { gates } from "./lib/gates";
export function App() {
return (
<GatesProvider client={gates}>
<Feature name="new_billing" fallback={<OldBilling />}>
<NewBilling />
</Feature>
</GatesProvider>
);
}Peer dependency note
The SDK declares an optional peer on react >=18. With the alias in place Preact satisfies it at runtime; if your package manager warns about the missing peer it's safe to ignore (or silence it — e.g. pnpm's peerDependencyRules.ignoreMissing).