diff --git a/packages/vite/src/node/server/middlewares/transform.ts b/packages/vite/src/node/server/middlewares/transform.ts index 22cb736909dc6b..5c7ec55bd8fb55 100644 --- a/packages/vite/src/node/server/middlewares/transform.ts +++ b/packages/vite/src/node/server/middlewares/transform.ts @@ -20,7 +20,7 @@ import { } from '../../utils' import { send } from '../send' import { ERR_LOAD_URL, transformRequest } from '../transformRequest' -import { applySourcemapIgnoreList } from '../sourcemap' +import { applySourcemapIgnoreList, getOriginalContent } from '../sourcemap' import { isHTMLProxy } from '../../plugins/html' import { DEP_VERSION_RE, @@ -205,12 +205,21 @@ export function transformMiddleware( const type = isDirectCSSRequest(url) ? 'css' : 'js' const isDep = DEP_VERSION_RE.test(url) || depsOptimizer?.isOptimizedDepUrl(url) + let originalContent: string | undefined + if (type === 'js' && result.map == null) { + const filepath = ( + await server.moduleGraph.getModuleByUrl(url, false) + )?.file + originalContent = + filepath != null ? await getOriginalContent(filepath) : undefined + } return send(req, res, result.code, type, { etag: result.etag, // allow browser to cache npm deps! cacheControl: isDep ? 'max-age=31536000,immutable' : 'no-cache', headers: server.config.server.headers, map: result.map, + originalContent, }) } } diff --git a/packages/vite/src/node/server/send.ts b/packages/vite/src/node/server/send.ts index 033b9f317a60d3..414fa4fe998175 100644 --- a/packages/vite/src/node/server/send.ts +++ b/packages/vite/src/node/server/send.ts @@ -27,6 +27,8 @@ export interface SendOptions { cacheControl?: string headers?: OutgoingHttpHeaders map?: SourceMap | { mappings: '' } | null + /** only used when type === 'js' && map == null (when the fallback sourcemap is used) */ + originalContent?: string } export function send( @@ -71,7 +73,9 @@ export function send( } // inject fallback sourcemap for js for improved debugging // https://github.com/vitejs/vite/pull/13514#issuecomment-1592431496 - else if (type === 'js' && (!map || map.mappings !== '')) { + // for { mappings: "" }, we don't inject fallback sourcemap + // because it indicates generating a sourcemap is meaningless + else if (type === 'js' && map == null) { const code = content.toString() // if the code has existing inline sourcemap, assume it's correct and skip if (convertSourceMap.mapFileCommentRegex.test(code)) { @@ -79,15 +83,15 @@ export function send( } else { const urlWithoutTimestamp = removeTimestampQuery(req.url!) const ms = new MagicString(code) - content = getCodeWithSourcemap( - type, - code, - ms.generateMap({ - source: path.basename(urlWithoutTimestamp), - hires: 'boundary', - includeContent: true, - }), - ) + const map = ms.generateMap({ + source: path.basename(urlWithoutTimestamp), + hires: 'boundary', + includeContent: !options.originalContent, + }) + if (options.originalContent != null) { + map.sourcesContent = [options.originalContent] + } + content = getCodeWithSourcemap(type, code, map) } } diff --git a/packages/vite/src/node/server/sourcemap.ts b/packages/vite/src/node/server/sourcemap.ts index c8f2c8d88fdacd..650d380a7ffc44 100644 --- a/packages/vite/src/node/server/sourcemap.ts +++ b/packages/vite/src/node/server/sourcemap.ts @@ -65,6 +65,13 @@ export async function injectSourcesContent( } } +export async function getOriginalContent( + filepath: string, +): Promise { + if (virtualSourceRE.test(filepath)) return undefined + return await fsp.readFile(filepath, 'utf-8').catch(() => undefined) +} + export function genSourceMapUrl(map: SourceMap | string): string { if (typeof map !== 'string') { map = JSON.stringify(map)