fix(bun-plugin-svelte): handle "svelte" export conditions (#18150)

This commit is contained in:
Don Isaac
2025-03-13 12:40:22 -07:00
committed by GitHub
parent 7d69ac03ec
commit b0b6c979ee
5 changed files with 42 additions and 73 deletions

View File

@@ -24,7 +24,8 @@
},
"devDependencies": {
"bun-types": "canary",
"svelte": "^5.20.4"
"svelte": "^5.20.4",
"@threlte/core": "8.0.1"
},
"peerDependencies": {
"svelte": "^5"

View File

@@ -29,6 +29,20 @@ function SveltePlugin(options: SvelteOptions = kEmptyObject as SvelteOptions): B
return {
name: "bun-plugin-svelte",
setup(builder) {
// resolve "svelte" export conditions
//
// FIXME: the dev server does not currently respect bundler configs; it
// just passes a fake one to plugins and then never uses it. we need to to
// update it to ~not~ do this.
if (builder?.config) {
var conditions = builder.config.conditions ?? [];
if (typeof conditions === "string") {
conditions = [conditions];
}
conditions.push("svelte");
builder.config.conditions = conditions;
}
const { config = kEmptyObject as Partial<BuildConfig> } = builder;
const baseCompileOptions = getBaseCompileOptions(options ?? (kEmptyObject as Partial<SvelteOptions>), config);
const baseModuleCompileOptions = getBaseModuleCompileOptions(

View File

@@ -1,72 +0,0 @@
import { basename } from "node:path";
import type { BuildConfig, Transpiler } from "bun";
import { getBaseCompileOptions, getBaseModuleCompileOptions, hash, type SvelteOptions } from "./options";
import { compile, type CompileOptions, type CompileResult, type ModuleCompileOptions } from "svelte/compiler";
const virtualNamespace = "bun-svelte";
export class SveltePluginService {
private compileOptions: CompileOptions;
private compileModuleOptions: ModuleCompileOptions;
private ts: Transpiler;
/** Virtual CSS modules created by Svelte components. Keys are import specifiers. */
private css: Map<string, VirtualCSSModule>;
constructor(options: SvelteOptions, config: Partial<BuildConfig>) {
this.compileOptions = getBaseCompileOptions(options, config);
this.compileModuleOptions = getBaseModuleCompileOptions(options, config);
this.ts = new Bun.Transpiler({ loader: "ts" });
this.css = new Map();
}
public compileComponent(source: string, filename: string, hmr: boolean, side?: "client" | "server"): CompileResult {
const generate = this.compileOptions.generate ?? side;
const result = compile(source, {
...this.compileOptions,
generate,
filename,
hmr,
});
var { js, css } = result;
if (css?.code && generate != "server") {
const uid = `${basename(filename)}-${hash(filename)}-style`.replaceAll(`"`, `'`);
const virtualName = virtualNamespace + ":" + uid + ".css";
this.css.set(virtualName, { sourcePath: filename, source: css.code });
js.code += `\nimport "${virtualName}";`;
}
return result;
}
public async compileModule(source: string, filename: string, side?: "client" | "server"): Promise<CompileResult> {
const generate = this.compileModuleOptions.generate ?? side;
if (filename.endsWith("ts")) {
source = await this.ts.transform(source);
}
// NOTE: we assume js/ts modules won't have CSS blocks in them, so no
// virtual modules get created.
return compile(source, {
...this.compileModuleOptions,
generate,
filename,
});
}
public takeVirtualCSSModule(path: string): VirtualCSSModule {
const mod = this.css.get(path);
if (!mod) throw new Error("Virtual CSS module not found: " + path);
this.css.delete(path);
return mod;
}
}
type VirtualCSSModule = {
/** Path to the svelte file whose css this is for */
sourcePath: string;
/** Source code */
source: string;
};

View File

@@ -0,0 +1,17 @@
<script>
import { Canvas } from "@threlte/core";
let name = "Bun";
</script>
<main class="app">
<h1>Cookin up apps with {name}</h1>
<Canvas />
</main>
<style>
h1 {
color: #ff3e00;
text-align: center;
font-size: 2em;
}
</style>

View File

@@ -47,6 +47,15 @@ describe("when importing `.svelte.ts` files with ESM", () => {
it("builds successfully", () => {
expect(res.success).toBeTrue();
});
it(`handles "svelte" export condition`, async () => {
const res = await Bun.build({
entrypoints: [fixturePath("svelte-export-condition.svelte")],
outdir,
plugins: [SveltePlugin()],
});
expect(res.success).toBeTrue();
});
});
describe("when importing `.svelte.ts` files with CJS", () => {