Skip to content

Commit

Permalink
feat(server): add warmupRequest api (#14787)
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy committed Nov 1, 2023
1 parent 6229485 commit 8690581
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 63 deletions.
21 changes: 2 additions & 19 deletions packages/vite/src/node/plugins/importAnalysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,8 @@ import type { ResolvedConfig } from '../config'
import type { Plugin } from '../plugin'
import { shouldExternalizeForSSR } from '../ssr/ssrExternal'
import { getDepsOptimizer, optimizedDepNeedsInterop } from '../optimizer'
import { ERR_CLOSED_SERVER } from '../server/pluginContainer'
import { checkPublicFile, urlRE } from './asset'
import {
ERR_OUTDATED_OPTIMIZED_DEP,
throwOutdatedRequest,
} from './optimizedDeps'
import { throwOutdatedRequest } from './optimizedDeps'
import { isCSSRequest, isDirectCSSRequest } from './css'
import { browserExternalId } from './resolve'
import { serializeDefine } from './define'
Expand Down Expand Up @@ -625,20 +621,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
// These requests will also be registered in transformRequest to be awaited
// by the deps optimizer
const url = removeImportQuery(hmrUrl)
server.transformRequest(url, { ssr }).catch((e) => {
if (
e?.code === ERR_OUTDATED_OPTIMIZED_DEP ||
e?.code === ERR_CLOSED_SERVER
) {
// these are expected errors
return
}
// Unexpected error, log the issue but avoid an unhandled exception
config.logger.error(`Pre-transform error: ${e.message}`, {
error: e,
timestamp: true,
})
})
server.warmupRequest(url, { ssr })
}
} else if (!importer.startsWith(withTrailingSlash(clientDir))) {
if (!isInNodeModules(importer)) {
Expand Down
25 changes: 24 additions & 1 deletion packages/vite/src/node/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
import { ssrLoadModule } from '../ssr/ssrModuleLoader'
import { ssrFixStacktrace, ssrRewriteStacktrace } from '../ssr/ssrStacktrace'
import { ssrTransform } from '../ssr/ssrTransform'
import { ERR_OUTDATED_OPTIMIZED_DEP } from '../plugins/optimizedDeps'
import {
getDepsOptimizer,
initDepsOptimizer,
Expand All @@ -47,7 +48,7 @@ import type { Logger } from '../logger'
import { printServerUrls } from '../logger'
import { createNoopWatcher, resolveChokidarOptions } from '../watch'
import type { PluginContainer } from './pluginContainer'
import { createPluginContainer } from './pluginContainer'
import { ERR_CLOSED_SERVER, createPluginContainer } from './pluginContainer'
import type { WebSocketServer } from './ws'
import { createWebSocketServer } from './ws'
import { baseMiddleware } from './middlewares/base'
Expand Down Expand Up @@ -231,6 +232,12 @@ export interface ViteDevServer {
url: string,
options?: TransformOptions,
): Promise<TransformResult | null>
/**
* Same as `transformRequest` but only warm up the URLs so the next request
* will already be cached. The function will never throw as it handles and
* reports errors internally.
*/
warmupRequest(url: string, options?: TransformOptions): Promise<void>
/**
* Apply vite built-in HTML transforms and any plugin HTML transforms.
*/
Expand Down Expand Up @@ -403,6 +410,22 @@ export async function _createServer(
transformRequest(url, options) {
return transformRequest(url, server, options)
},
async warmupRequest(url, options) {
await transformRequest(url, server, options).catch((e) => {
if (
e?.code === ERR_OUTDATED_OPTIMIZED_DEP ||
e?.code === ERR_CLOSED_SERVER
) {
// these are expected errors
return
}
// Unexpected error, log the issue but avoid an unhandled exception
server.config.logger.error(`Pre-transform error: ${e.message}`, {
error: e,
timestamp: true,
})
})
},
transformIndexHtml: null!, // to be immediately set
async ssrLoadModule(url, opts?: { fixStacktrace?: boolean }) {
if (isDepsOptimizerEnabled(config, true)) {
Expand Down
20 changes: 2 additions & 18 deletions packages/vite/src/node/server/middlewares/indexHtml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ import {
unwrapId,
wrapId,
} from '../../utils'
import { ERR_CLOSED_SERVER } from '../pluginContainer'
import { ERR_OUTDATED_OPTIMIZED_DEP } from '../../plugins/optimizedDeps'
import { isCSSRequest } from '../../plugins/css'
import { checkPublicFile } from '../../plugins/asset'
import { getCodeWithSourcemap, injectSourcesContent } from '../sourcemap'
Expand Down Expand Up @@ -422,21 +420,7 @@ export function indexHtmlMiddleware(
function preTransformRequest(server: ViteDevServer, url: string, base: string) {
if (!server.config.server.preTransformRequests) return

url = unwrapId(stripBase(url, base))

// transform all url as non-ssr as html includes client-side assets only
server.transformRequest(url).catch((e) => {
if (
e?.code === ERR_OUTDATED_OPTIMIZED_DEP ||
e?.code === ERR_CLOSED_SERVER
) {
// these are expected errors
return
}
// Unexpected error, log the issue but avoid an unhandled exception
server.config.logger.error(`Pre-transform error: ${e.message}`, {
error: e,
timestamp: true,
})
})
url = unwrapId(stripBase(url, base))
server.warmupRequest(url)
}
17 changes: 9 additions & 8 deletions packages/vite/src/node/server/transformRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,7 @@ async function doTransform(
// returns a boolean true is successful, or false if no handling is needed
const softInvalidatedTransformResult =
module &&
(await handleModuleSoftInvalidation(
module,
ssr,
timestamp,
server.config.base,
))
(await handleModuleSoftInvalidation(module, ssr, timestamp, server))
if (softInvalidatedTransformResult) {
debugCache?.(`[memory-hmr] ${prettyUrl}`)
return softInvalidatedTransformResult
Expand Down Expand Up @@ -384,7 +379,7 @@ async function handleModuleSoftInvalidation(
mod: ModuleNode,
ssr: boolean,
timestamp: number,
base: string,
server: ViteDevServer,
) {
const transformResult = ssr ? mod.ssrInvalidationState : mod.invalidationState

Expand Down Expand Up @@ -425,7 +420,7 @@ async function handleModuleSoftInvalidation(
const urlWithoutTimestamp = removeTimestampQuery(rawUrl)
// hmrUrl must be derived the same way as importAnalysis
const hmrUrl = unwrapId(
stripBase(removeImportQuery(urlWithoutTimestamp), base),
stripBase(removeImportQuery(urlWithoutTimestamp), server.config.base),
)
for (const importedMod of mod.clientImportedModules) {
if (importedMod.url !== hmrUrl) continue
Expand All @@ -438,6 +433,12 @@ async function handleModuleSoftInvalidation(
const end = hasQuotes ? imp.e - 1 : imp.e
s.overwrite(start, end, replacedUrl)
}

if (imp.d === -1 && server.config.server.preTransformRequests) {
// pre-transform known direct imports
server.warmupRequest(hmrUrl, { ssr })
}

break
}
}
Expand Down
38 changes: 21 additions & 17 deletions packages/vite/src/node/server/warmup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,31 @@ export function warmupFiles(server: ViteDevServer): void {
}

async function warmupFile(server: ViteDevServer, file: string, ssr: boolean) {
try {
// transform html with the `transformIndexHtml` hook as Vite internals would
// pre-transform the imported JS modules linked. this may cause `transformIndexHtml`
// plugins to be executed twice, but that's probably fine.
if (file.endsWith('.html')) {
const url = htmlFileToUrl(file, server.config.root)
if (url) {
// transform html with the `transformIndexHtml` hook as Vite internals would
// pre-transform the imported JS modules linked. this may cause `transformIndexHtml`
// plugins to be executed twice, but that's probably fine.
if (file.endsWith('.html')) {
const url = htmlFileToUrl(file, server.config.root)
if (url) {
try {
const html = await fs.readFile(file, 'utf-8')
await server.transformIndexHtml(url, html)
} catch (e) {
// Unexpected error, log the issue but avoid an unhandled exception
server.config.logger.error(
`Pre-transform error (${colors.cyan(file)}): ${e.message}`,
{
error: e,
timestamp: true,
},
)
}
}
// for other files, pass it through `transformRequest`. this is what Vite uses
// for it's `server.preTransformRequests` option.
else {
const url = fileToUrl(file, server.config.root)
await server.transformRequest(url, { ssr })
}
} catch (e) {
server.config.logger.error(
colors.red(`Failed to warm up ${colors.cyan(file)}:\n`) + e.message,
)
}
// for other files, pass it through `transformRequest` with warmup
else {
const url = fileToUrl(file, server.config.root)
await server.warmupRequest(url, { ssr })
}
}

Expand Down

0 comments on commit 8690581

Please sign in to comment.