From c3d573c01cba8191b2c9eeae0f27452e9207fc5d Mon Sep 17 00:00:00 2001 From: shulaoda <165626830+shulaoda@users.noreply.github.com> Date: Thu, 2 Apr 2026 22:56:04 +0800 Subject: [PATCH] fix: normalize island CSS paths for Windows compatibility --- packages/react/src/plugin-islands.ts | 8 ++++---- packages/solid/src/plugin-islands.ts | 8 ++++---- packages/svelte/src/plugin-islands.ts | 8 ++++---- packages/void/src/pages/islands-plugin.ts | 9 +++++---- packages/vue/src/plugin-islands.ts | 8 ++++---- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/packages/react/src/plugin-islands.ts b/packages/react/src/plugin-islands.ts index d01ceab21..1c7fe440c 100644 --- a/packages/react/src/plugin-islands.ts +++ b/packages/react/src/plugin-islands.ts @@ -90,7 +90,7 @@ export function islandsPlugin(pagesDir: string): Plugin[] { for (const page of pageScan.pages) { if (!page.island) continue; if (/\.(tsx|jsx)$/.test(page.componentPath)) { - islandCssFiles.add(resolve(pagesDir, page.componentPath)); + islandCssFiles.add(normalizePath(resolve(pagesDir, page.componentPath))); } const layoutChain = resolveEffectiveLayoutChain( page, @@ -98,7 +98,7 @@ export function islandsPlugin(pagesDir: string): Plugin[] { pageScan.namedLayouts, ); for (const layout of layoutChain) { - islandCssFiles.add(resolve(pagesDir, layout.filePath)); + islandCssFiles.add(normalizePath(resolve(pagesDir, layout.filePath))); } } @@ -116,10 +116,10 @@ export function islandsPlugin(pagesDir: string): Plugin[] { // Virtual island CSS modules — no \0 prefix so Vite CSS pipeline processes them. // Return absolute path so CSS @import resolution uses the correct directory. if (source.endsWith(".css")) { - const srcPath = source.slice(0, -4); + const srcPath = normalizePath(source.slice(0, -4)); if (islandCssFiles.has(srcPath)) return srcPath + ".css"; if (srcPath.startsWith("/")) { - const absPath = resolve(viteRoot, srcPath.slice(1)); + const absPath = normalizePath(resolve(viteRoot, srcPath.slice(1))); if (islandCssFiles.has(absPath)) return absPath + ".css"; } } diff --git a/packages/solid/src/plugin-islands.ts b/packages/solid/src/plugin-islands.ts index 28e6e34b4..c601aae7b 100644 --- a/packages/solid/src/plugin-islands.ts +++ b/packages/solid/src/plugin-islands.ts @@ -109,7 +109,7 @@ export function islandsPlugin(pagesDir: string): Plugin[] { for (const page of pageScan.pages) { if (!page.island) continue; if (/\.(tsx|jsx)$/.test(page.componentPath)) { - islandCssFiles.add(resolve(pagesDir, page.componentPath)); + islandCssFiles.add(normalizePath(resolve(pagesDir, page.componentPath))); } const layoutChain = resolveEffectiveLayoutChain( page, @@ -117,7 +117,7 @@ export function islandsPlugin(pagesDir: string): Plugin[] { pageScan.namedLayouts, ); for (const layout of layoutChain) { - islandCssFiles.add(resolve(pagesDir, layout.filePath)); + islandCssFiles.add(normalizePath(resolve(pagesDir, layout.filePath))); } } @@ -142,10 +142,10 @@ export function islandsPlugin(pagesDir: string): Plugin[] { // Virtual island CSS modules — no \0 prefix so Vite CSS pipeline processes them. // Return absolute path so CSS @import resolution uses the correct directory. if (source.endsWith(".css")) { - const srcPath = source.slice(0, -4); + const srcPath = normalizePath(source.slice(0, -4)); if (islandCssFiles.has(srcPath)) return srcPath + ".css"; if (srcPath.startsWith("/")) { - const absPath = resolve(viteRoot, srcPath.slice(1)); + const absPath = normalizePath(resolve(viteRoot, srcPath.slice(1))); if (islandCssFiles.has(absPath)) return absPath + ".css"; } } diff --git a/packages/svelte/src/plugin-islands.ts b/packages/svelte/src/plugin-islands.ts index 195a6dbcb..382e8c30e 100644 --- a/packages/svelte/src/plugin-islands.ts +++ b/packages/svelte/src/plugin-islands.ts @@ -99,7 +99,7 @@ export function islandsPlugin(pagesDir: string): Plugin[] { for (const page of pageScan.pages) { if (!page.island) continue; if (page.componentPath.endsWith(".svelte")) { - islandCssFiles.add(resolve(pagesDir, page.componentPath)); + islandCssFiles.add(normalizePath(resolve(pagesDir, page.componentPath))); } const layoutChain = resolveEffectiveLayoutChain( page, @@ -107,7 +107,7 @@ export function islandsPlugin(pagesDir: string): Plugin[] { pageScan.namedLayouts, ); for (const layout of layoutChain) { - islandCssFiles.add(resolve(pagesDir, layout.filePath)); + islandCssFiles.add(normalizePath(resolve(pagesDir, layout.filePath))); } } @@ -132,10 +132,10 @@ export function islandsPlugin(pagesDir: string): Plugin[] { // Virtual island CSS modules — no \0 prefix so Vite CSS pipeline processes them. // Return absolute path so CSS @import resolution uses the correct directory. if (source.endsWith(".css")) { - const srcPath = source.slice(0, -4); + const srcPath = normalizePath(source.slice(0, -4)); if (islandCssFiles.has(srcPath)) return srcPath + ".css"; if (srcPath.startsWith("/")) { - const absPath = resolve(viteRoot, srcPath.slice(1)); + const absPath = normalizePath(resolve(viteRoot, srcPath.slice(1))); if (islandCssFiles.has(absPath)) return absPath + ".css"; } } diff --git a/packages/void/src/pages/islands-plugin.ts b/packages/void/src/pages/islands-plugin.ts index 6d8483e5f..67ea683fa 100644 --- a/packages/void/src/pages/islands-plugin.ts +++ b/packages/void/src/pages/islands-plugin.ts @@ -1,4 +1,4 @@ -import type { ViteDevServer } from "vite"; +import { normalizePath, type ViteDevServer } from "vite"; import { existsSync, readFileSync, readdirSync } from "node:fs"; import { resolve } from "node:path"; import { resolveEffectiveLayoutChain } from "./scan"; @@ -175,13 +175,14 @@ export function configureIslandCssServer( rebuildCssMap: () => void, ): void { server.watcher.on("change", (path) => { - if (!islandCssFiles.has(path)) return; + const normalizedPath = normalizePath(path); + if (!islandCssFiles.has(normalizedPath)) return; rebuildCssMap(); for (const env of Object.values(server.environments)) { const mod = env.moduleGraph.getModuleById("\0" + ISLANDS_RENDERER_ID); if (mod) env.moduleGraph.invalidateModule(mod); } - const cssMod = server.environments.client?.moduleGraph.getModuleById(path + ".css"); + const cssMod = server.environments.client?.moduleGraph.getModuleById(normalizedPath + ".css"); if (cssMod) server.environments.client.moduleGraph.invalidateModule(cssMod); }); @@ -189,7 +190,7 @@ export function configureIslandCssServer( if (!req.url) return next(); const url = req.url.split("?")[0]; if (!url.endsWith(".css")) return next(); - const srcPath = resolve(viteRoot, url.slice(1, -4)); + const srcPath = normalizePath(resolve(viteRoot, url.slice(1, -4))); if (!islandCssFiles.has(srcPath)) return next(); try { const result = await server.environments.client.transformRequest(url); diff --git a/packages/vue/src/plugin-islands.ts b/packages/vue/src/plugin-islands.ts index 7ae20b15c..4fa53de03 100644 --- a/packages/vue/src/plugin-islands.ts +++ b/packages/vue/src/plugin-islands.ts @@ -128,7 +128,7 @@ export function islandsPlugin(pagesDir: string): Plugin[] { for (const page of pageScan.pages) { if (!page.island) continue; if (page.componentPath.endsWith(".vue")) { - islandCssFiles.add(resolve(pagesDir, page.componentPath)); + islandCssFiles.add(normalizePath(resolve(pagesDir, page.componentPath))); } const layoutChain = resolveEffectiveLayoutChain( page, @@ -136,7 +136,7 @@ export function islandsPlugin(pagesDir: string): Plugin[] { pageScan.namedLayouts, ); for (const layout of layoutChain) { - islandCssFiles.add(resolve(pagesDir, layout.filePath)); + islandCssFiles.add(normalizePath(resolve(pagesDir, layout.filePath))); } } @@ -154,10 +154,10 @@ export function islandsPlugin(pagesDir: string): Plugin[] { // Virtual island CSS modules — no \0 prefix so Vite CSS pipeline processes them. // Return absolute path so CSS @import resolution uses the correct directory. if (source.endsWith(".css")) { - const srcPath = source.slice(0, -4); + const srcPath = normalizePath(source.slice(0, -4)); if (islandCssFiles.has(srcPath)) return srcPath + ".css"; if (srcPath.startsWith("/")) { - const absPath = resolve(viteRoot, srcPath.slice(1)); + const absPath = normalizePath(resolve(viteRoot, srcPath.slice(1))); if (islandCssFiles.has(absPath)) return absPath + ".css"; } }