mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-05 08:02:18 +00:00
fix(cli): keep svelte component styles in the raw-app bundle (#10838)
* fix(cli): keep svelte component styles in the raw-app bundle Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test: fold svelte style guard into the plugin test file Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs: record the editor-parity constraint on the svelte css option Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(cli): pin esbuild's service cwd before any test file chdirs esbuild's node API captures process.cwd() when its module is first imported and spawns its service with that cwd on every (re)start. createBundle stops the service after each bundle, so the cwd is reused across the whole run. Several test files chdir into a temp dir and delete it afterwards. The first one to bundle therefore pinned the service to a directory that stopped existing, and the next test to reach esbuild died with The service was stopped: ENOENT: no such file or directory, posix_spawn '.../@esbuild/linux-x64/bin/esbuild' The binary is present; ENOENT is posix_spawn rejecting the missing cwd. Which file tripped it depended on bun's readdir order, so renaming an unrelated test file was enough to surface it. Importing esbuild from the preload pins the service to a cwd that outlives the run, independent of file ordering. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G88YF3sZFnJZUvTLVjqhZc --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
This commit is contained in:
co-authored by
Claude Opus 5
Ruben Fiszel
parent
ffdf17ef8d
commit
b8bf539c3f
@@ -191,7 +191,14 @@ function createSveltePlugin(appDir: string): any {
|
||||
|
||||
// Convert Svelte syntax to JavaScript
|
||||
try {
|
||||
const { js, warnings } = svelte.compile(source, { filename });
|
||||
// The raw-app editor's in-browser bundler compiles with
|
||||
// `css: "injected"`, so this must too, or the same app renders
|
||||
// styled there and unstyled once the CLI builds it: Svelte's default
|
||||
// ("external") hands the <style> back on a `css` field nothing emits.
|
||||
const { js, warnings } = svelte.compile(source, {
|
||||
filename,
|
||||
css: "injected",
|
||||
});
|
||||
const contents = js.code + `//# sourceMappingURL=` + js.map.toUrl();
|
||||
return { contents, warnings: warnings.map(convertMessage) };
|
||||
} catch (e: any) {
|
||||
|
||||
+40
-4
@@ -1,8 +1,5 @@
|
||||
/**
|
||||
* `lib.svelte.ts` / `lib.svelte.js` modules are plain modules that may use
|
||||
* runes. They need `svelte.compileModule`; without it esbuild happily bundles
|
||||
* `$state(...)` as an ordinary call and the app dies at runtime with
|
||||
* "ReferenceError: $state is not defined".
|
||||
* The svelte esbuild plugin, driven through `createBundle`.
|
||||
*/
|
||||
|
||||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||
@@ -59,6 +56,12 @@ afterAll(() => {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
/**
|
||||
* `lib.svelte.ts` / `lib.svelte.js` modules are plain modules that may use
|
||||
* runes. They need `svelte.compileModule`; without it esbuild happily bundles
|
||||
* `$state(...)` as an ordinary call and the app dies at runtime with
|
||||
* "ReferenceError: $state is not defined".
|
||||
*/
|
||||
describe("svelte plugin: .svelte.ts modules", () => {
|
||||
test("compiles runes in a TypeScript rune module and the bundle runs", async () => {
|
||||
writeApp({
|
||||
@@ -116,3 +119,36 @@ bump();
|
||||
expect((globalThis as any).__counterResult).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Svelte's default `css: "external"` hands a component's <style> back on a
|
||||
* field the plugin never emits, so the markup keeps its `svelte-<hash>` class
|
||||
* while the rule matching it disappears — no build error, just an app that
|
||||
* renders unstyled from the CLI and styled in the editor.
|
||||
*/
|
||||
describe("svelte plugin: component styles", () => {
|
||||
test("a <style> block reaches the bundle under the class its markup carries", async () => {
|
||||
writeApp({
|
||||
"Styled.svelte": `<main>
|
||||
<h1>Hello</h1>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
</style>
|
||||
`,
|
||||
"styles_entry.ts": `import Styled from './Styled.svelte';
|
||||
export default Styled;
|
||||
`,
|
||||
});
|
||||
|
||||
const js = await bundle("styles_entry.ts");
|
||||
|
||||
const scopeClass = js.match(/<h1 class="(svelte-[a-z0-9]+)"/)?.[1];
|
||||
expect(scopeClass).toBeDefined();
|
||||
expect(js).toContain(`h1.${scopeClass}`);
|
||||
expect(js).toContain("font-size");
|
||||
});
|
||||
});
|
||||
@@ -10,6 +10,12 @@
|
||||
* bear the startup cost inside their per-test timeout window.
|
||||
*/
|
||||
|
||||
// esbuild's node API pins the cwd it spawns its service with to process.cwd() at
|
||||
// module import, and test files chdir into temp dirs they later delete. Import it
|
||||
// here, from a cwd that outlives the run, or the first file to bundle pins the
|
||||
// service to a directory that stops existing and every later build fails ENOENT.
|
||||
import "esbuild";
|
||||
|
||||
if (process.env["UNIT_ONLY"]) {
|
||||
// Nothing to do — unit tests don't need backend setup
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user