perf: precache map injection in module graph

This commit is contained in:
patak 2023-12-11 23:48:13 +01:00
parent 921ca419d8
commit 6552ad2ab9
4 changed files with 66 additions and 39 deletions

View File

@ -205,12 +205,15 @@ export function transformMiddleware(
const type = isDirectCSSRequest(url) ? 'css' : 'js'
const isDep =
DEP_VERSION_RE.test(url) || depsOptimizer?.isOptimizedDepUrl(url)
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,
// result.code already contains the result.map injected, to avoid computing
// the injection on every request
injectSourceMapReference: false,
})
}
}

View File

@ -3,17 +3,9 @@ import type {
OutgoingHttpHeaders,
ServerResponse,
} from 'node:http'
import path from 'node:path'
import convertSourceMap from 'convert-source-map'
import getEtag from 'etag'
import type { SourceMap } from 'rollup'
import MagicString from 'magic-string'
import { createDebugger, removeTimestampQuery } from '../utils'
import { getCodeWithSourcemap } from './sourcemap'
const debug = createDebugger('vite:send', {
onlyWhenFocused: true,
})
import { withInjectedSourceMapReference } from './sourcemap'
const alias: Record<string, string | undefined> = {
js: 'application/javascript',
@ -27,6 +19,7 @@ export interface SendOptions {
cacheControl?: string
headers?: OutgoingHttpHeaders
map?: SourceMap | { mappings: '' } | null
injectSourceMapReference?: boolean
}
export function send(
@ -39,6 +32,7 @@ export function send(
const {
etag = getEtag(content, { weak: true }),
cacheControl = 'no-cache',
injectSourceMapReference = true,
headers,
map,
} = options
@ -63,32 +57,8 @@ export function send(
}
}
// inject source map reference
if (map && 'version' in map && map.mappings) {
if (type === 'js' || type === 'css') {
content = getCodeWithSourcemap(type, content.toString(), map)
}
}
// inject fallback sourcemap for js for improved debugging
// https://github.com/vitejs/vite/pull/13514#issuecomment-1592431496
else if (type === 'js' && (!map || map.mappings !== '')) {
const code = content.toString()
// if the code has existing inline sourcemap, assume it's correct and skip
if (convertSourceMap.mapFileCommentRegex.test(code)) {
debug?.(`Skipped injecting fallback sourcemap for ${req.url}`)
} 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,
}),
)
}
if (injectSourceMapReference) {
content = withInjectedSourceMapReference(content, type, req.url!, map)
}
res.statusCode = 200

View File

@ -1,8 +1,10 @@
import path from 'node:path'
import fsp from 'node:fs/promises'
import convertSourceMap from 'convert-source-map'
import type { ExistingRawSourceMap, SourceMap } from 'rollup'
import MagicString from 'magic-string'
import type { Logger } from '../logger'
import { createDebugger } from '../utils'
import { createDebugger, removeTimestampQuery } from '../utils'
const debug = createDebugger('vite:sourcemap', {
onlyWhenFocused: true,
@ -143,3 +145,39 @@ export function applySourcemapIgnoreList(
if (!map.x_google_ignoreList) map.x_google_ignoreList = x_google_ignoreList
}
}
export function withInjectedSourceMapReference(
content: string | Buffer,
type: string,
url: string,
map?: SourceMap | { mappings: '' } | null,
): string | Buffer {
// inject source map reference
if (map && 'version' in map && map.mappings) {
if (type === 'js' || type === 'css') {
return getCodeWithSourcemap(type, content.toString(), map)
}
}
// inject fallback sourcemap for js for improved debugging
// https://github.com/vitejs/vite/pull/13514#issuecomment-1592431496
else if (type === 'js' && (!map || map.mappings !== '')) {
const code = content.toString()
// if the code has existing inline sourcemap, assume it's correct and skip
if (convertSourceMap.mapFileCommentRegex.test(code)) {
debug?.(`Skipped injecting fallback sourcemap for ${url}`)
} else {
const urlWithoutTimestamp = removeTimestampQuery(url)
const ms = new MagicString(code)
return getCodeWithSourcemap(
type,
code,
ms.generateMap({
source: path.basename(urlWithoutTimestamp),
hires: 'boundary',
includeContent: true,
}),
)
}
}
return content
}

View File

@ -24,7 +24,12 @@ import {
} from '../utils'
import { checkPublicFile } from '../publicDir'
import { getDepsOptimizer } from '../optimizer'
import { applySourcemapIgnoreList, injectSourcesContent } from './sourcemap'
import { isDirectCSSRequest } from '../plugins/css'
import {
applySourcemapIgnoreList,
injectSourcesContent,
withInjectedSourceMapReference,
} from './sourcemap'
import { isFileServingAllowed } from './middlewares/static'
import { throwClosedServerError } from './pluginContainer'
@ -358,7 +363,18 @@ async function loadAndTransform(
// being processed, so it is re-processed next time if it is stale
if (timestamp > mod.lastInvalidationTimestamp) {
if (ssr) mod.ssrTransformResult = result
else mod.transformResult = result
else {
if (result) {
const type = isDirectCSSRequest(url) ? 'css' : 'js'
result.code = withInjectedSourceMapReference(
result.code,
type,
url,
result.map,
) as string
}
mod.transformResult = result
}
}
return result