From 9e4a3687d188391c9fbb19fdafde14f68ac4ced2 Mon Sep 17 00:00:00 2001 From: Hajime-san <41257923+Hajime-san@users.noreply.github.com> Date: Sun, 31 May 2026 00:41:02 +0900 Subject: [PATCH 1/7] merge config --- packages/plugin-vite/tests/build_test.ts | 10 +++++++--- packages/plugin-vite/tests/test_utils.ts | 22 +++++++--------------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/packages/plugin-vite/tests/build_test.ts b/packages/plugin-vite/tests/build_test.ts index e4d8354e059..62ce2933e81 100644 --- a/packages/plugin-vite/tests/build_test.ts +++ b/packages/plugin-vite/tests/build_test.ts @@ -592,9 +592,13 @@ integrationTest( "vite build - custom rollup entryFileNames in server.js", async () => { await using res = await buildVite(DEMO_DIR, { - rollupOutput: { - entryFileNames: "[hash].mjs", - chunkFileNames: "[hash].mjs", + build: { + rollupOptions: { + output: { + entryFileNames: "[hash].mjs", + chunkFileNames: "[hash].mjs", + }, + }, }, }); diff --git a/packages/plugin-vite/tests/test_utils.ts b/packages/plugin-vite/tests/test_utils.ts index 2d7a4d5c6b6..27a8385c002 100644 --- a/packages/plugin-vite/tests/test_utils.ts +++ b/packages/plugin-vite/tests/test_utils.ts @@ -1,4 +1,4 @@ -import { createBuilder } from "vite"; +import { createBuilder, mergeConfig } from "vite"; import * as path from "@std/path"; import { walk } from "@std/fs/walk"; import { integrationTest, withTmpDir } from "../../fresh/src/test_utils.ts"; @@ -135,24 +135,16 @@ export async function withDevServer( export async function buildVite( fixtureDir: string, - options?: { - base?: string; - rollupOutput?: { - entryFileNames?: string; - chunkFileNames?: string; - assetFileNames?: string; - }; - }, + config?: Parameters[0], ) { const tmp = await withTmpDir({ dir: path.join(import.meta.dirname!, ".."), prefix: "tmp_vite_", }); - const builder = await createBuilder({ + const defaults = { logLevel: "error", root: fixtureDir, - base: options?.base, build: { emptyOutDir: true, }, @@ -160,9 +152,6 @@ export async function buildVite( ssr: { build: { outDir: path.join(tmp.dir, "_fresh", "server"), - rollupOptions: options?.rollupOutput - ? { output: options.rollupOutput } - : undefined, }, }, client: { @@ -171,7 +160,10 @@ export async function buildVite( }, }, }, - }); + } satisfies Parameters[0]; + const builder = await createBuilder( + mergeConfig(defaults, config ?? {}), + ); await builder.buildApp(); return { From 52e5fc4346bd41fe3d4f0f6c03ea03928413ab15 Mon Sep 17 00:00:00 2001 From: Hajime-san <41257923+Hajime-san@users.noreply.github.com> Date: Sun, 31 May 2026 01:17:16 +0900 Subject: [PATCH 2/7] adding test --- packages/plugin-vite/tests/build_test.ts | 74 ++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/packages/plugin-vite/tests/build_test.ts b/packages/plugin-vite/tests/build_test.ts index 62ce2933e81..2a24548f934 100644 --- a/packages/plugin-vite/tests/build_test.ts +++ b/packages/plugin-vite/tests/build_test.ts @@ -1,3 +1,4 @@ +import { createLogger } from "vite"; import { expect } from "@std/expect"; import { walk } from "@std/fs/walk"; import { @@ -832,3 +833,76 @@ integrationTest( ); }, ); + +integrationTest( + "vite build - ssr sourcemap sould be generated collectly", + async () => { + await using tmp = await buildVite(DEMO_DIR, { + environments: { + ssr: { + build: { + sourcemap: true, + }, + }, + }, + }); + + const serverAssetsDir = path.join(tmp.tmp, "_fresh", "server", "assets"); + + for await ( + const entry of walk(serverAssetsDir, { + exts: [".mjs"], + includeDirs: false, + }) + ) { + const js = await Deno.readTextFile(entry.path); + const match = js.match(/\/\/# sourceMappingURL=(.+)$/m); + expect(match).not.toBeNull(); + + const mapPath = path.join(path.dirname(entry.path), match![1]); + const mapText = await Deno.readTextFile(mapPath); + const map = JSON.parse(mapText); + + expect(Array.isArray(map.sources)).toBe(true); + expect(map.sources.length).toBeGreaterThan(0); + expect(typeof map.mappings).toBe("string"); + expect(map.mappings.length).toBeGreaterThan(0); + } + }, +); + +// rollup specific test +// https://rollupjs.org/troubleshooting/#warning-sourcemap-is-likely-to-be-incorrect +integrationTest( + "vite build - ssr sourcemap sould be generated without warings", + async () => { + const warnMsgs = new Set(); + const customLogger = createLogger("error"); + customLogger.warn = (msg) => { + customLogger.hasWarned = true; + warnMsgs.add(msg); + }; + customLogger.warnOnce = (msg) => { + customLogger.hasWarned = true; + warnMsgs.add(msg); + }; + + await using _ = await buildVite(DEMO_DIR, { + logLevel: "warn", + clearScreen: true, + customLogger, + environments: { + ssr: { + build: { + sourcemap: true, + }, + }, + }, + }); + + const sourceMapIncorrectMsg = warnMsgs.has( + "[plugin deno] Sourcemap is likely to be incorrect: a plugin (deno) was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help", + ); + expect(sourceMapIncorrectMsg).not.toBeTruthy(); + }, +); From 4b1c8b8b38f9b5dcffbe94b36b44d1cf46957bc9 Mon Sep 17 00:00:00 2001 From: Hajime-san <41257923+Hajime-san@users.noreply.github.com> Date: Sun, 31 May 2026 06:32:05 +0900 Subject: [PATCH 3/7] fix --- deno.lock | 8 ++++---- packages/plugin-vite/deno.json | 2 +- packages/plugin-vite/src/plugins/deno.ts | 24 ++++++++++++++++++++---- packages/plugin-vite/tests/build_test.ts | 23 ++++++++++++++--------- 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/deno.lock b/deno.lock index 3d5970098a8..0867329d019 100644 --- a/deno.lock +++ b/deno.lock @@ -9,7 +9,7 @@ "jsr:@deno/esbuild-plugin@^1.2.0": "1.2.1", "jsr:@deno/graph@0.86": "0.86.9", "jsr:@deno/graph@~0.82.3": "0.82.3", - "jsr:@deno/loader@0.4": "0.4.0", + "jsr:@deno/loader@0.5": "0.5.0", "jsr:@deno/loader@~0.3.10": "0.3.14", "jsr:@marvinh-test/fresh-island@^0.0.3": "0.0.3", "jsr:@marvinh-test/import-json@^0.0.1": "0.0.1", @@ -191,8 +191,8 @@ "@deno/loader@0.3.14": { "integrity": "97bc63a6cc2d27a60bcdc953f588c5213331d866d44212eebb24cebfb9b011ca" }, - "@deno/loader@0.4.0": { - "integrity": "6c1b18cfa18592740613ce79e15625c24268d60dbfc54bebfb5153bf512c536b" + "@deno/loader@0.5.0": { + "integrity": "a6d94408de5e6bacac404f8f6963c8b8cc278cfd1a878aa2f06b34a083d6bfee" }, "@marvinh-test/fresh-island@0.0.3": { "integrity": "6d06b6009b7dfba9bba28e941e03e6ff652c4ef4f2fbfdf4b78741abd6c6c1c6", @@ -6078,7 +6078,7 @@ }, "packages/plugin-vite": { "dependencies": [ - "jsr:@deno/loader@0.4", + "jsr:@deno/loader@0.5", "jsr:@fresh/core@2", "jsr:@marvinh-test/import-json@^0.0.1", "npm:@babel/core@^7.28.0", diff --git a/packages/plugin-vite/deno.json b/packages/plugin-vite/deno.json index 57af17393e6..b7f5c93940a 100644 --- a/packages/plugin-vite/deno.json +++ b/packages/plugin-vite/deno.json @@ -23,7 +23,7 @@ "imports": { "@babel/core": "npm:@babel/core@^7.28.0", "@babel/preset-react": "npm:@babel/preset-react@^7.27.1", - "@deno/loader": "jsr:@deno/loader@^0.4.0", + "@deno/loader": "jsr:@deno/loader@^0.5.0", "@marvinh-test/import-json": "jsr:@marvinh-test/import-json@^0.0.1", "@remix-run/node-fetch-server": "npm:@remix-run/node-fetch-server@^0.12.0", "@prefresh/vite": "npm:@prefresh/vite@^2.4.8", diff --git a/packages/plugin-vite/src/plugins/deno.ts b/packages/plugin-vite/src/plugins/deno.ts index 6cefed7e463..d46fadc8e53 100644 --- a/packages/plugin-vite/src/plugins/deno.ts +++ b/packages/plugin-vite/src/plugins/deno.ts @@ -2,6 +2,7 @@ import type { Plugin } from "vite"; import { type Loader, MediaType, + type ModuleLoadResponse, RequestedModuleType, ResolutionMode, Workspace, @@ -17,6 +18,8 @@ const { default: babelReact } = await import("@babel/preset-react"); const BUILTINS = new Set(builtinModules); +const decoder = new TextDecoder(); + interface DenoState { type: RequestedModuleType; } @@ -180,7 +183,7 @@ export function deno(): Plugin { return null; } - const code = new TextDecoder().decode(result.code); + const code = decoder.decode(result.code); const maybeJsx = babelTransform({ ssr: this.environment.config.consumer === "server", @@ -188,6 +191,7 @@ export function deno(): Plugin { code, id: specifier, isDev, + inputSourceMap: parseSourceMap(result.sourceMap), }); if (maybeJsx !== null) { return maybeJsx; @@ -224,7 +228,7 @@ export function deno(): Plugin { return null; } - const code = new TextDecoder().decode(result.code); + const code = decoder.decode(result.code); const maybeJsx = babelTransform({ ssr: this.environment.config.consumer === "server", @@ -232,6 +236,7 @@ export function deno(): Plugin { id, code, isDev, + inputSourceMap: parseSourceMap(result.sourceMap), }); if (maybeJsx) { return maybeJsx; @@ -279,10 +284,12 @@ export function deno(): Plugin { return; } - const code = new TextDecoder().decode(result.code); + const code = decoder.decode(result.code); + const map = parseSourceMap(result.sourceMap); return { code, + map, }; }, }, @@ -375,13 +382,14 @@ function babelTransform( code: string; id: string; isDev: boolean; + inputSourceMap: babel.TransformOptions["inputSourceMap"]; }, ) { if (!isJsMediaType(options.media)) { return null; } - const { ssr, code, id, isDev } = options; + const { ssr, code, id, isDev, inputSourceMap } = options; const presets: babel.PluginItem[] = []; if ( @@ -400,6 +408,7 @@ function babelTransform( const result = babel.transformSync(code, { filename: id, babelrc: false, + inputSourceMap, sourceMaps: "both", presets: presets, plugins: [httpAbsolute(url)], @@ -415,3 +424,10 @@ function babelTransform( return null; } + +function parseSourceMap( + sourceMap: ModuleLoadResponse["sourceMap"], +): babel.TransformOptions["inputSourceMap"] { + if (!sourceMap) return undefined; + return JSON.parse(decoder.decode(sourceMap)); +} diff --git a/packages/plugin-vite/tests/build_test.ts b/packages/plugin-vite/tests/build_test.ts index 2a24548f934..ae3d972edbc 100644 --- a/packages/plugin-vite/tests/build_test.ts +++ b/packages/plugin-vite/tests/build_test.ts @@ -1,4 +1,5 @@ import { createLogger } from "vite"; +import type { BabelFileResult } from "@babel/core"; import { expect } from "@std/expect"; import { walk } from "@std/fs/walk"; import { @@ -14,6 +15,7 @@ import { launchProd, usingEnv, } from "./test_utils.ts"; +import { toPosix } from "fresh/internal-dev"; import * as path from "@std/path"; import { FRESH_CSS_PLACEHOLDER } from "../src/plugins/server_snapshot.ts"; @@ -848,7 +850,6 @@ integrationTest( }); const serverAssetsDir = path.join(tmp.tmp, "_fresh", "server", "assets"); - for await ( const entry of walk(serverAssetsDir, { exts: [".mjs"], @@ -857,22 +858,26 @@ integrationTest( ) { const js = await Deno.readTextFile(entry.path); const match = js.match(/\/\/# sourceMappingURL=(.+)$/m); - expect(match).not.toBeNull(); - const mapPath = path.join(path.dirname(entry.path), match![1]); const mapText = await Deno.readTextFile(mapPath); - const map = JSON.parse(mapText); - - expect(Array.isArray(map.sources)).toBe(true); - expect(map.sources.length).toBeGreaterThan(0); - expect(typeof map.mappings).toBe("string"); - expect(map.mappings.length).toBeGreaterThan(0); + const map: NonNullable = JSON.parse(mapText); + + // check a specific sourcemap file which contains + // the reference of original source file + if (entry.name.includes("_fresh-route___tests_feed-")) { + expect( + map.sources.some((source) => + toPosix(source).endsWith("demo/routes/tests/feed.tsx") + ), + ).toBe(true); + } } }, ); // rollup specific test // https://rollupjs.org/troubleshooting/#warning-sourcemap-is-likely-to-be-incorrect +// this test could be broke if it will migrate to rolldown integrationTest( "vite build - ssr sourcemap sould be generated without warings", async () => { From 23ea2fefd8860610f973f940184fd3132374cc49 Mon Sep 17 00:00:00 2001 From: Hajime-san <41257923+Hajime-san@users.noreply.github.com> Date: Sun, 31 May 2026 06:41:31 +0900 Subject: [PATCH 4/7] typo --- packages/plugin-vite/tests/build_test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin-vite/tests/build_test.ts b/packages/plugin-vite/tests/build_test.ts index ae3d972edbc..855c786e526 100644 --- a/packages/plugin-vite/tests/build_test.ts +++ b/packages/plugin-vite/tests/build_test.ts @@ -837,7 +837,7 @@ integrationTest( ); integrationTest( - "vite build - ssr sourcemap sould be generated collectly", + "vite build - ssr sourcemap should be generated collectly", async () => { await using tmp = await buildVite(DEMO_DIR, { environments: { @@ -879,7 +879,7 @@ integrationTest( // https://rollupjs.org/troubleshooting/#warning-sourcemap-is-likely-to-be-incorrect // this test could be broke if it will migrate to rolldown integrationTest( - "vite build - ssr sourcemap sould be generated without warings", + "vite build - ssr sourcemap should be generated without warings", async () => { const warnMsgs = new Set(); const customLogger = createLogger("error"); From c1636771ddc7817c99983019eded744dc6c20f31 Mon Sep 17 00:00:00 2001 From: Hajime-san <41257923+Hajime-san@users.noreply.github.com> Date: Sun, 31 May 2026 13:59:34 +0900 Subject: [PATCH 5/7] fix --- packages/fresh/src/dev/dev_build_cache.ts | 13 ++++++++++++- packages/plugin-vite/src/plugins/server_entry.ts | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/fresh/src/dev/dev_build_cache.ts b/packages/fresh/src/dev/dev_build_cache.ts index 3678d0ffba4..69e9c3e2e47 100644 --- a/packages/fresh/src/dev/dev_build_cache.ts +++ b/packages/fresh/src/dev/dev_build_cache.ts @@ -622,8 +622,19 @@ import { app } from "${serverEntry}"; const root = ${rootPath}; setBuildCache(app, new ProdBuildCache(root, snapshot), "production"); +// In dev, plugins may mutate app-level hooks such as the error interceptor +// after this module loads. Keep the fetch target refreshable so the server +// entry can pick up the latest app.handler() when that happens. +let handler = app.handler(); + +export function refreshHandler() { + handler = app.handler(); +} + export default { - fetch: app.handler() + fetch(req, info) { + return handler(req, info); + } }; `; } diff --git a/packages/plugin-vite/src/plugins/server_entry.ts b/packages/plugin-vite/src/plugins/server_entry.ts index d4b1dec8726..ce2a37a8dd6 100644 --- a/packages/plugin-vite/src/plugins/server_entry.ts +++ b/packages/plugin-vite/src/plugins/server_entry.ts @@ -97,6 +97,7 @@ ${code} export function setErrorInterceptor(fn) { internalErrorIntercept(app, fn); + refreshHandler(); } if (import.meta.hot) import.meta.hot.accept();`; } From 4f4526ef318f13dbe0bf19e801c4ec9fbfae9914 Mon Sep 17 00:00:00 2001 From: Hajime-san <41257923+Hajime-san@users.noreply.github.com> Date: Sun, 31 May 2026 14:18:26 +0900 Subject: [PATCH 6/7] fix vite dev --- packages/plugin-vite/src/plugins/deno.ts | 37 +++++++++++++++++------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/packages/plugin-vite/src/plugins/deno.ts b/packages/plugin-vite/src/plugins/deno.ts index d46fadc8e53..b873dd79e09 100644 --- a/packages/plugin-vite/src/plugins/deno.ts +++ b/packages/plugin-vite/src/plugins/deno.ts @@ -183,7 +183,7 @@ export function deno(): Plugin { return null; } - const code = decoder.decode(result.code); + const { code, map } = decodeLoadResult(result); const maybeJsx = babelTransform({ ssr: this.environment.config.consumer === "server", @@ -191,7 +191,7 @@ export function deno(): Plugin { code, id: specifier, isDev, - inputSourceMap: parseSourceMap(result.sourceMap), + inputSourceMap: map, }); if (maybeJsx !== null) { return maybeJsx; @@ -199,6 +199,7 @@ export function deno(): Plugin { return { code, + map, }; } @@ -228,7 +229,7 @@ export function deno(): Plugin { return null; } - const code = decoder.decode(result.code); + const { code, map } = decodeLoadResult(result); const maybeJsx = babelTransform({ ssr: this.environment.config.consumer === "server", @@ -236,7 +237,7 @@ export function deno(): Plugin { id, code, isDev, - inputSourceMap: parseSourceMap(result.sourceMap), + inputSourceMap: map, }); if (maybeJsx) { return maybeJsx; @@ -244,6 +245,7 @@ export function deno(): Plugin { return { code, + map, }; }, transform: { @@ -284,8 +286,7 @@ export function deno(): Plugin { return; } - const code = decoder.decode(result.code); - const map = parseSourceMap(result.sourceMap); + const { code, map } = decodeLoadResult(result); return { code, @@ -425,9 +426,23 @@ function babelTransform( return null; } -function parseSourceMap( - sourceMap: ModuleLoadResponse["sourceMap"], -): babel.TransformOptions["inputSourceMap"] { - if (!sourceMap) return undefined; - return JSON.parse(decoder.decode(sourceMap)); +function decodeLoadResult( + result: Extract, +): { + code: string; + map: babel.TransformOptions["inputSourceMap"]; +} { + const map = result.sourceMap && JSON.parse(decoder.decode(result.sourceMap)); + // If we pass a separate sourcemap object to Vite, remove the loader's + // inline data URL so the module only has one sourcemap source of truth. + const code = !map + ? decoder.decode(result.code) + : decoder.decode(result.code).replace( + /\r?\n\/\/# sourceMappingURL=data:[^\r\n]+$/, + "", + ); + return { + code, + map, + }; } From ad3fef9ae1fdd016ff0bc564d6b9f4883e8f79ca Mon Sep 17 00:00:00 2001 From: Hajime-san <41257923+Hajime-san@users.noreply.github.com> Date: Sun, 31 May 2026 14:20:09 +0900 Subject: [PATCH 7/7] typo --- packages/plugin-vite/tests/build_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin-vite/tests/build_test.ts b/packages/plugin-vite/tests/build_test.ts index 855c786e526..2163d6e1196 100644 --- a/packages/plugin-vite/tests/build_test.ts +++ b/packages/plugin-vite/tests/build_test.ts @@ -879,7 +879,7 @@ integrationTest( // https://rollupjs.org/troubleshooting/#warning-sourcemap-is-likely-to-be-incorrect // this test could be broke if it will migrate to rolldown integrationTest( - "vite build - ssr sourcemap should be generated without warings", + "vite build - ssr sourcemap should be generated without warnings", async () => { const warnMsgs = new Set(); const customLogger = createLogger("error");