Vite 8 replaced esbuild with Oxc for JS transforms. Oxc does not lower TC39 decorators (@customElement, @route, @bindable, etc.), so a Babel transform step is required.
Use a Vite-native plugin (not @rolldown/plugin-babel) — Rolldown’s native pipeline does not coordinate with the Aurelia plugin’s Vite transform hook, leaving @customElement (injected by @aurelia/vite-plugin) untranspiled:
import { transformSync } from "@babel/core";
import type { Plugin } from "vite";
function babelDecoratorsPlugin(): Plugin {
return {
name: "babel-decorators",
enforce: "post",
transform(code, id) {
if (!/\.[jt]s$/.test(id)) return;
if (!code.includes("@")) return;
if (id.includes("node_modules")) return;
try {
const result = transformSync(code, {
filename: id,
plugins: [["@babel/plugin-proposal-decorators", { version: "2023-11" }]],
});
if (result?.code) return { code: result.code, map: result.map };
} catch { return null; }
},
};
}
Key:enforce: "post" ensures Babel runs after@aurelia/vite-plugin (which uses enforce: "pre" to inject @customElement), so all decorators are transpiled.
Other Vite 8 config migrations:esbuild → oxc, rollupOptions → rolldownOptions, remove manualChunks object form (removed in Vite 8).
it’s already been discussed in this issue that I’ve opened a while ago
it also includes a patch, that was provided couple months ago, and is confirmed to work. It’s basically a patch until OXC officially brings support for the new decorator and they haven’t provided any date or roadmap for that (they just said they’ll wait until it’s a stable feature)