Morphos & Kosmesis are here.Explore
PraxisJS

Vite Plugin

@praxisjs/vite-plugin — configures Vite for PraxisJS with decorator support, JSX transform, TypeScript, and optional HMR.

Vite Plugin

The Vite plugin handles everything needed to run PraxisJS: decorator support, the JSX transform to @praxisjs/jsx, and optional component-level HMR. It's required for all PraxisJS projects.

npm install -D @praxisjs/vite-plugin
pnpm add -D @praxisjs/vite-plugin
yarn add -D @praxisjs/vite-plugin
bun add -d @praxisjs/vite-plugin

Setup

// vite.config.ts
import { defineConfig } from 'vite'
import { praxisjs } from '@praxisjs/vite-plugin'

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

Options

praxisjs({
  hmr: true,         // component-level hot reload (default: false)
  autoImport: true,  // auto-import common decorators (default: false)
})
OptionTypeDefaultDescription
hmrbooleanfalseEnables component-level hot module replacement. The component re-mounts in place without a full page reload when its source file changes.
autoImportbooleanfalseAuto-imports @Component, @State, @Prop, and other commonly used decorators so you don't have to import them in every file.

What the plugin does

  • Decorator support — sets Vite's oxc transform target to ES2022, and lowers TC39 decorators with the TypeScript compiler since oxc doesn't support that natively yet
  • JSX transform — configures Vite to use @praxisjs/jsx as the JSX import source (equivalent to jsxImportSource in tsconfig)
  • HMR — when enabled, patches component classes on save so the instance re-mounts with new logic while preserving existing state where possible

Using decorators in Vitest

Vitest runs test files through Node directly — it doesn't go through Vite's dev/build pipeline unless you wire a plugin into vitest.config.ts. Since decorated classes need the same TC39-to-runtime lowering praxisjs() applies in the browser, import the standalone decoratorLoweringPlugin() export and register it as a Vitest plugin:

// vitest.config.ts
import { defineConfig } from 'vitest/config'
import { decoratorLoweringPlugin } from '@praxisjs/vite-plugin'

export default defineConfig({
  plugins: [decoratorLoweringPlugin()],
  test: {
    environment: 'node', // or 'jsdom' for tests touching the DOM
  },
})

This is the same plugin praxisjs() includes internally — it only lowers files that contain real decorator syntax, so it's safe to add without also pulling in the JSX transform or HMR pieces, which test files don't need.


Static site generation

For prerendering routes to static HTML at build time (with real client-side hydration), add ssgPlugin() from @praxisjs/ssg alongside praxisjs():

// vite.config.ts
import { praxisjs } from '@praxisjs/vite-plugin'
import { ssgPlugin } from '@praxisjs/ssg'

export default defineConfig({
  plugins: [praxisjs(), ssgPlugin({ root: './src/app.tsx' })],
})

See the SSG guide for route enumeration, dynamic routes, and how hydration works.


TypeScript configuration

The plugin handles the Vite/oxc side, but TypeScript still needs its own configuration:

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "jsx": "react-jsx",
    "jsxImportSource": "@praxisjs/jsx",
    "useDefineForClassFields": true,
    "strict": true,
    "noEmit": true
  }
}

On this page