From 14bde2bd17075616db02f23c7e91135930f33051 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Fri, 28 Oct 2022 00:12:42 +0200 Subject: [PATCH 01/58] feat: experimental server persistent caching --- packages/vite/src/node/config.ts | 93 +++++++- packages/vite/src/node/index.ts | 6 + packages/vite/src/node/server/index.ts | 9 +- .../vite/src/node/server/persistentCache.ts | 212 ++++++++++++++++++ .../vite/src/node/server/transformRequest.ts | 88 +++++--- 5 files changed, 373 insertions(+), 35 deletions(-) create mode 100644 packages/vite/src/node/server/persistentCache.ts diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index ea9de372ed5fee..46f809eb7f6ce7 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -60,6 +60,7 @@ import type { PackageCache } from './packages' import { loadEnv, resolveEnvPrefix } from './env' import type { ResolvedSSROptions, SSROptions } from './ssr' import { resolveSSROptions } from './ssr' +import { version } from './publicUtils' const debug = createDebugger('vite:config') @@ -288,6 +289,40 @@ export interface ExperimentalOptions { * @default false */ hmrPartialAccept?: boolean + /** + * Enables persistent cache for the development server. + * + * @experimental + * @default null + */ + serverPersistentCaching?: ServerPersistentCacheOptions | true +} + +export interface ServerPersistentCacheOptions { + /** + * Enable or disable persistent cache. + */ + enabled?: boolean + /** + * Path to the cache directory. + */ + cacheDir?: string + /** + * Paths to files that should be taken into account when determining whether to clear the cache. + * By default will use the vite config file and your package lock file (for npm, yarn or pnpm). + */ + cacheVersionFromFiles?: string[] + /** + * Manual version string that should be taken into account when determining whether to clear the cache. + * Will be added to the result of `cacheVersionFromFiles`. + */ + cacheVersion?: string +} + +export interface ResolvedServerPersistentCacheOptions { + cacheDir: string + cacheVersionFromFiles: string[] + cacheVersion: string } export interface LegacyOptions { @@ -346,6 +381,7 @@ export type ResolvedConfig = Readonly< worker: ResolveWorkerOptions appType: AppType experimental: ExperimentalOptions + resolvedServerPersistentCacheOptions: ResolvedServerPersistentCacheOptions | null } & PluginHookUtils > @@ -612,8 +648,60 @@ export async function resolveConfig( getSortedPluginHooks: undefined! } + const resolvedConfigFile = configFile ? normalizePath(configFile) : undefined + + // [experimental] Server persistent caching + + let resolvedServerPersistentCacheOptions: ResolvedServerPersistentCacheOptions | null + if ( + config.experimental?.serverPersistentCaching !== false || + (typeof config.experimental?.serverPersistentCaching === 'object' && + config.experimental.serverPersistentCaching.enabled !== false) + ) { + const castedToObject = + typeof config.experimental?.serverPersistentCaching === 'object' + ? config.experimental.serverPersistentCaching + : null + const dir = castedToObject?.cacheDir + ? path.resolve(resolvedRoot, castedToObject.cacheDir) + : pkgPath + ? path.join(path.dirname(pkgPath), `node_modules/.vite-server-cache`) + : path.join(resolvedRoot, `.vite-server-cache`) + + const cacheVersionFromFiles: string[] = + castedToObject?.cacheVersionFromFiles ?? [] + + if (resolvedConfigFile) { + cacheVersionFromFiles.push(resolvedConfigFile) + } + + const packageLockFile = lookupFile( + resolvedRoot, + [ + 'package-lock.json', + 'yarn.lock', + 'pnpm-lock.yaml', + 'bun.lockb', + 'npm-shrinkwrap.json' + ], + { pathOnly: true } + ) + if (packageLockFile) { + cacheVersionFromFiles.push(packageLockFile) + } + + resolvedServerPersistentCacheOptions = { + cacheDir: dir, + cacheVersionFromFiles, + cacheVersion: castedToObject?.cacheVersion ?? '' + } + resolvedServerPersistentCacheOptions.cacheVersion += version + } else { + resolvedServerPersistentCacheOptions = null + } + const resolvedConfig: ResolvedConfig = { - configFile: configFile ? normalizePath(configFile) : undefined, + configFile: resolvedConfigFile, configFileDependencies: configFileDependencies.map((name) => normalizePath(path.resolve(name)) ), @@ -662,7 +750,8 @@ export async function resolveConfig( ...config.experimental }, getSortedPlugins: undefined!, - getSortedPluginHooks: undefined! + getSortedPluginHooks: undefined!, + resolvedServerPersistentCacheOptions } const resolved: ResolvedConfig = { ...config, diff --git a/packages/vite/src/node/index.ts b/packages/vite/src/node/index.ts index f0d1276ecbc604..bf4afc87c38fd5 100644 --- a/packages/vite/src/node/index.ts +++ b/packages/vite/src/node/index.ts @@ -95,6 +95,12 @@ export type { TransformResult } from './server/transformRequest' export type { HmrOptions, HmrContext } from './server/hmr' +export type { + PersistentCache, + PersistentCacheEntry, + PersistentCacheManifest, + PersistentCacheResult +} from './server/persistentCache' export type { HMRPayload, diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts index 7ea1d846183bb5..2311da30b2934d 100644 --- a/packages/vite/src/node/server/index.ts +++ b/packages/vite/src/node/server/index.ts @@ -79,6 +79,8 @@ import { openBrowser } from './openBrowser' import type { TransformOptions, TransformResult } from './transformRequest' import { transformRequest } from './transformRequest' import { searchForWorkspaceRoot } from './searchRoot' +import type { PersistentCache } from './persistentCache' +import { createPersistentCache } from './persistentCache' export { searchForWorkspaceRoot } from './searchRoot' @@ -301,6 +303,10 @@ export interface ViteDevServer { * @internal */ _fsDenyGlob: Matcher + /** + * @internal + */ + _persistentCache: PersistentCache | null } export interface ResolvedServerUrls { @@ -452,7 +458,8 @@ export async function createServer( _importGlobMap: new Map(), _forceOptimizeOnRestart: false, _pendingRequests: new Map(), - _fsDenyGlob: picomatch(config.server.fs.deny, { matchBase: true }) + _fsDenyGlob: picomatch(config.server.fs.deny, { matchBase: true }), + _persistentCache: await createPersistentCache(config) } server.transformIndexHtml = createDevHtmlTransformFn(server) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts new file mode 100644 index 00000000000000..16deb7f390754c --- /dev/null +++ b/packages/vite/src/node/server/persistentCache.ts @@ -0,0 +1,212 @@ +import fs from 'node:fs' +import path from 'node:path' +import crypto from 'node:crypto' +import colors from 'picocolors' +import type { ResolvedConfig } from '../config' +import { normalizePath } from '../publicUtils' + +export interface PersistentCache { + manifest: PersistentCacheManifest + getKey: (code: string) => string + read: (key: string) => Promise + write: (key: string, file: string, code: string, map?: any) => Promise +} + +export interface PersistentCacheManifest { + version: string + modules: Record +} + +export interface PersistentCacheEntry { + file: string + fileCode: string + fileMap?: string +} + +export interface PersistentCacheResult { + code: string + map?: any +} + +function hashCode(code: string) { + return crypto.createHash('sha1').update(code).digest('hex') +} + +export async function createPersistentCache( + config: ResolvedConfig +): Promise { + const options = config.resolvedServerPersistentCacheOptions + if (!options) { + return null + } + + const logger = config.logger + + logger.warn( + colors.yellow( + `You have server persistent cache enabled. This is an experimental feature.` + ) + ) + + // Cache directory + + const resolvedCacheDir = normalizePath(path.resolve(options.cacheDir)) + + if (!fs.existsSync(resolvedCacheDir)) { + fs.mkdirSync(resolvedCacheDir, { recursive: true }) + } + + // Cache version + + const cacheVersion = + (await Promise.all( + options.cacheVersionFromFiles.map((file) => { + if (!fs.existsSync(file)) { + throw new Error(`Persistent cache version file not found: ${file}`) + } + return fs.promises.readFile(file, 'utf-8') + }) + ).then((codes) => hashCode(codes.join('')))) + options.cacheVersion + + // Manifest + + const manifestPath = path.join(resolvedCacheDir, 'manifest.json') + let manifest: PersistentCacheManifest | null = null + if (fs.existsSync(manifestPath)) { + try { + manifest = JSON.parse(await fs.promises.readFile(manifestPath, 'utf-8')) + if (manifest && manifest.version !== cacheVersion) { + // Burst cache if version changed + try { + // Empty the directory + const files = await fs.promises.readdir(resolvedCacheDir) + await Promise.all( + files.map((file) => + fs.promises.unlink(path.join(resolvedCacheDir, file)) + ) + ) + } catch (e) { + logger.warn( + colors.yellow( + `Failed to empty persistent cache directory '${resolvedCacheDir}': ${e.message}` + ) + ) + } + manifest = null + } + } catch (e) { + logger.warn( + colors.yellow( + `Failed to load persistent cache manifest '${manifestPath}': ${e.message}` + ) + ) + } + } + const resolvedManifest = manifest ?? { + version: cacheVersion, + modules: {} + } + + // Manifest write queue + + let isManifestWriteQueued = false + let isManifestWriting = false + + function queueManifestWrite() { + if (isManifestWriteQueued) { + return + } + + if (isManifestWriting) { + isManifestWriteQueued = true + return + } + + setTimeout(async () => { + isManifestWriting = true + try { + await fs.promises.writeFile( + manifestPath, + JSON.stringify(resolvedManifest, null, 2) + ) + } catch (e) { + logger.warn( + colors.yellow( + `Failed to write persistent cache manifest '${manifestPath}': ${e.message}` + ) + ) + } + isManifestWriting = false + + if (isManifestWriteQueued) { + isManifestWriteQueued = false + queueManifestWrite() + } + }, 500) + } + + // Methods + + function getKey(code: string) { + return hashCode(code) + } + + async function read(key: string): Promise { + const entry = resolvedManifest.modules[key] + if (!entry) { + return null + } + + try { + const code = await fs.promises.readFile(entry.fileCode, 'utf8') + const map = entry.fileMap + ? JSON.parse(await fs.promises.readFile(entry.fileMap, 'utf8')) + : undefined + + return { + code, + map + } + } catch (e) { + logger.warn( + colors.yellow( + `Failed to read persistent cache entry '${key}' (${entry.file}): ${e.message}` + ) + ) + return null + } + } + + async function write(key: string, file: string, code: string, map?: any) { + try { + const fileCode = path.resolve(resolvedCacheDir, 'c-' + key) + const fileMap = map ? fileCode + '-map' : undefined + + await fs.promises.writeFile(fileCode, code, 'utf8') + if (map && fileMap) { + await fs.promises.writeFile(fileMap, JSON.stringify(map), 'utf8') + } + + resolvedManifest.modules[key] = { + file, + fileCode, + fileMap + } + + queueManifestWrite() + } catch (e) { + logger.warn( + colors.yellow( + `Failed to write persistent cache entry '${key}' (${file}): ${e.message}` + ) + ) + } + } + + return { + manifest: resolvedManifest, + getKey, + read, + write + } +} diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index 8f962c250f22d9..a109748be3916b 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -228,42 +228,66 @@ async function loadAndTransform( const mod = await moduleGraph.ensureEntryFromUrl(url, ssr) ensureWatchedFile(watcher, mod.file, root) - // transform - const transformStart = isDebug ? performance.now() : 0 - const transformResult = await pluginContainer.transform(code, id, { - inMap: map, - ssr - }) - const originalCode = code - if ( - transformResult == null || - (isObject(transformResult) && transformResult.code == null) - ) { - // no transform applied, keep code as-is - isDebug && - debugTransform( - timeFrom(transformStart) + colors.dim(` [skipped] ${prettyUrl}`) - ) - } else { - isDebug && debugTransform(`${timeFrom(transformStart)} ${prettyUrl}`) - code = transformResult.code! - map = transformResult.map - } + let result: TransformResult | null = null - if (map && mod.file) { - map = (typeof map === 'string' ? JSON.parse(map) : map) as SourceMap - if (map.mappings && !map.sourcesContent) { - await injectSourcesContent(map, mod.file, logger) + // persistent cache + + const persistentCacheKey = + (server._persistentCache?.getKey(code) ?? '') + (options.ssr ? '-ssr' : '') + + if (server._persistentCache) { + const cached = await server._persistentCache.read(persistentCacheKey) + if (cached) { + result = { + code: cached.code, + map: cached.map, + etag: getEtag(cached.code, { weak: true }) + } } } - const result = ssr - ? await server.ssrTransform(code, map as SourceMap, url, originalCode) - : ({ - code, - map, - etag: getEtag(code, { weak: true }) - } as TransformResult) + if (!result) { + // transform + const transformStart = isDebug ? performance.now() : 0 + const transformResult = await pluginContainer.transform(code, id, { + inMap: map, + ssr + }) + const originalCode = code + if ( + transformResult == null || + (isObject(transformResult) && transformResult.code == null) + ) { + // no transform applied, keep code as-is + isDebug && + debugTransform( + timeFrom(transformStart) + colors.dim(` [skipped] ${prettyUrl}`) + ) + } else { + isDebug && debugTransform(`${timeFrom(transformStart)} ${prettyUrl}`) + code = transformResult.code! + map = transformResult.map + } + + if (map && mod.file) { + map = (typeof map === 'string' ? JSON.parse(map) : map) as SourceMap + if (map.mappings && !map.sourcesContent) { + await injectSourcesContent(map, mod.file, logger) + } + } + + result = ssr + ? await server.ssrTransform(code, map as SourceMap, url, originalCode) + : ({ + code, + map, + etag: getEtag(code, { weak: true }) + } as TransformResult) + + if (server._persistentCache) { + await server._persistentCache.write(persistentCacheKey, file, code, map) + } + } // Only cache the result if the module wasn't invalidated while it was // being processed, so it is re-processed next time if it is stale From c309eed82751a2bec67005c60a146cab24c8a72e Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Fri, 28 Oct 2022 00:21:44 +0200 Subject: [PATCH 02/58] fix: check if config is nullish --- packages/vite/src/node/config.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index 46f809eb7f6ce7..1e32a499954206 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -654,9 +654,10 @@ export async function resolveConfig( let resolvedServerPersistentCacheOptions: ResolvedServerPersistentCacheOptions | null if ( - config.experimental?.serverPersistentCaching !== false || - (typeof config.experimental?.serverPersistentCaching === 'object' && - config.experimental.serverPersistentCaching.enabled !== false) + config.experimental?.serverPersistentCaching != null && + (config.experimental?.serverPersistentCaching !== false || + (typeof config.experimental?.serverPersistentCaching === 'object' && + config.experimental.serverPersistentCaching.enabled !== false)) ) { const castedToObject = typeof config.experimental?.serverPersistentCaching === 'object' From 57f081d9ee2e2818aecfcafbf9d0159c2f1efb7d Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Fri, 28 Oct 2022 01:00:21 +0200 Subject: [PATCH 03/58] fix: don't cache modules that contains 'import.meta.glob' --- packages/vite/src/node/server/transformRequest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index a109748be3916b..7318f765b092ee 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -235,7 +235,7 @@ async function loadAndTransform( const persistentCacheKey = (server._persistentCache?.getKey(code) ?? '') + (options.ssr ? '-ssr' : '') - if (server._persistentCache) { + if (server._persistentCache && !code.includes('import.meta.glob')) { const cached = await server._persistentCache.read(persistentCacheKey) if (cached) { result = { From ce26960e3f2efea89ac008c77dcb890eeabeaf92 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Fri, 28 Oct 2022 01:43:15 +0200 Subject: [PATCH 04/58] feat: exclude --- packages/vite/src/node/config.ts | 8 +++++++- packages/vite/src/node/server/transformRequest.ts | 13 +++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index 1e32a499954206..8191ef87c084dc 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -317,12 +317,17 @@ export interface ServerPersistentCacheOptions { * Will be added to the result of `cacheVersionFromFiles`. */ cacheVersion?: string + /** + * Exclude requests from being cached. + */ + exclude?: (url: string) => boolean } export interface ResolvedServerPersistentCacheOptions { cacheDir: string cacheVersionFromFiles: string[] cacheVersion: string + exclude?: (url: string) => boolean } export interface LegacyOptions { @@ -694,7 +699,8 @@ export async function resolveConfig( resolvedServerPersistentCacheOptions = { cacheDir: dir, cacheVersionFromFiles, - cacheVersion: castedToObject?.cacheVersion ?? '' + cacheVersion: castedToObject?.cacheVersion ?? '', + exclude: castedToObject?.exclude } resolvedServerPersistentCacheOptions.cacheVersion += version } else { diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index 7318f765b092ee..b4c821e9707523 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -235,7 +235,12 @@ async function loadAndTransform( const persistentCacheKey = (server._persistentCache?.getKey(code) ?? '') + (options.ssr ? '-ssr' : '') - if (server._persistentCache && !code.includes('import.meta.glob')) { + if ( + server._persistentCache && + !code.includes('import.meta.glob') && + (!server.config.resolvedServerPersistentCacheOptions?.exclude || + !server.config.resolvedServerPersistentCacheOptions.exclude(url)) + ) { const cached = await server._persistentCache.read(persistentCacheKey) if (cached) { result = { @@ -284,7 +289,11 @@ async function loadAndTransform( etag: getEtag(code, { weak: true }) } as TransformResult) - if (server._persistentCache) { + if ( + server._persistentCache && + (!server.config.resolvedServerPersistentCacheOptions?.exclude || + !server.config.resolvedServerPersistentCacheOptions.exclude(url)) + ) { await server._persistentCache.write(persistentCacheKey, file, code, map) } } From 12216c307fc0055a1e9d0c82f5659e1c3273188a Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Fri, 28 Oct 2022 01:49:42 +0200 Subject: [PATCH 05/58] fix: add id in cache key --- packages/vite/src/node/server/transformRequest.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index b4c821e9707523..f45b0f759713ec 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -233,7 +233,8 @@ async function loadAndTransform( // persistent cache const persistentCacheKey = - (server._persistentCache?.getKey(code) ?? '') + (options.ssr ? '-ssr' : '') + (server._persistentCache?.getKey(id + code) ?? '') + + (options.ssr ? '-ssr' : '') if ( server._persistentCache && From a8f8d28caf3f69b8b127613b39212092229570e8 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Fri, 28 Oct 2022 02:10:56 +0200 Subject: [PATCH 06/58] refactor: includedInPersistentCache --- .../vite/src/node/server/transformRequest.ts | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index f45b0f759713ec..a4cd2c21ca371f 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -232,17 +232,17 @@ async function loadAndTransform( // persistent cache - const persistentCacheKey = - (server._persistentCache?.getKey(id + code) ?? '') + - (options.ssr ? '-ssr' : '') - - if ( + const includedInPersistentCache = server._persistentCache && - !code.includes('import.meta.glob') && (!server.config.resolvedServerPersistentCacheOptions?.exclude || !server.config.resolvedServerPersistentCacheOptions.exclude(url)) - ) { - const cached = await server._persistentCache.read(persistentCacheKey) + const persistentCacheKey = includedInPersistentCache + ? (server._persistentCache?.getKey(id + code) ?? '') + + (options.ssr ? '-ssr' : '') + : '' + + if (includedInPersistentCache && !code.includes('import.meta.glob')) { + const cached = await server._persistentCache?.read(persistentCacheKey) if (cached) { result = { code: cached.code, @@ -290,12 +290,8 @@ async function loadAndTransform( etag: getEtag(code, { weak: true }) } as TransformResult) - if ( - server._persistentCache && - (!server.config.resolvedServerPersistentCacheOptions?.exclude || - !server.config.resolvedServerPersistentCacheOptions.exclude(url)) - ) { - await server._persistentCache.write(persistentCacheKey, file, code, map) + if (includedInPersistentCache) { + await server._persistentCache?.write(persistentCacheKey, file, code, map) } } From fc7379004f4175040a62fe567ca600afa8b3edc7 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Fri, 28 Oct 2022 02:42:51 +0200 Subject: [PATCH 07/58] fix: cache loadResult to support svelte --- packages/vite/src/node/index.ts | 1 + .../vite/src/node/server/persistentCache.ts | 14 +++-- .../vite/src/node/server/transformRequest.ts | 52 ++++++++++++++++--- 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/packages/vite/src/node/index.ts b/packages/vite/src/node/index.ts index bf4afc87c38fd5..6b0abd031077f9 100644 --- a/packages/vite/src/node/index.ts +++ b/packages/vite/src/node/index.ts @@ -98,6 +98,7 @@ export type { HmrOptions, HmrContext } from './server/hmr' export type { PersistentCache, PersistentCacheEntry, + PersistentCacheFile, PersistentCacheManifest, PersistentCacheResult } from './server/persistentCache' diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index 16deb7f390754c..4d07647df3199e 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -10,11 +10,13 @@ export interface PersistentCache { getKey: (code: string) => string read: (key: string) => Promise write: (key: string, file: string, code: string, map?: any) => Promise + queueManifestWrite: () => void } export interface PersistentCacheManifest { version: string modules: Record + files: Record } export interface PersistentCacheEntry { @@ -28,6 +30,10 @@ export interface PersistentCacheResult { map?: any } +export interface PersistentCacheFile { + relatedModules: Record +} + function hashCode(code: string) { return crypto.createHash('sha1').update(code).digest('hex') } @@ -102,9 +108,10 @@ export async function createPersistentCache( ) } } - const resolvedManifest = manifest ?? { + const resolvedManifest: PersistentCacheManifest = manifest ?? { version: cacheVersion, - modules: {} + modules: {}, + files: {} } // Manifest write queue @@ -207,6 +214,7 @@ export async function createPersistentCache( manifest: resolvedManifest, getKey, read, - write + write, + queueManifestWrite } } diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index a4cd2c21ca371f..ee8afb7976f301 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -3,7 +3,7 @@ import path from 'node:path' import { performance } from 'node:perf_hooks' import getEtag from 'etag' import * as convertSourceMap from 'convert-source-map' -import type { SourceDescription, SourceMap } from 'rollup' +import type { LoadResult, SourceDescription, SourceMap } from 'rollup' import colors from 'picocolors' import type { ViteDevServer } from '..' import { @@ -17,6 +17,7 @@ import { } from '../utils' import { checkPublicFile } from '../plugins/asset' import { getDepsOptimizer } from '../optimizer' +import { DEP_VERSION_RE } from '../constants' import { injectSourcesContent } from './sourcemap' import { isFileServingAllowed } from './middlewares/static' @@ -168,7 +169,50 @@ async function loadAndTransform( // load const loadStart = isDebug ? performance.now() : 0 - const loadResult = await pluginContainer.load(id, { ssr }) + let loadResult: LoadResult + + const idWithoutHmrFlag = id.replace(DEP_VERSION_RE, '') + const loadCacheKey = ssr ? `ssr:${idWithoutHmrFlag}` : idWithoutHmrFlag + + loadResult = await pluginContainer.load(id, { ssr }) + + const includedInPersistentCache = + server._persistentCache && + (!server.config.resolvedServerPersistentCacheOptions?.exclude || + !server.config.resolvedServerPersistentCacheOptions.exclude(url)) + + // Persist load result just in case (for example: svelte component CSS subrequest) + + if ( + server._persistentCache && + includedInPersistentCache && + idWithoutHmrFlag !== file + ) { + const fileCacheInfo = (server._persistentCache.manifest.files[file] = server + ._persistentCache.manifest.files[file] ?? { + relatedModules: {} + }) + if (loadResult != null) { + const saveKey = server._persistentCache.getKey(loadCacheKey) + let code: string + let map: any | null + if (typeof loadResult === 'string') { + code = loadResult + } else { + code = loadResult.code + map = loadResult.map + } + await server._persistentCache.write(saveKey, file, code, map) + fileCacheInfo.relatedModules[loadCacheKey] = saveKey + server._persistentCache.queueManifestWrite() + } else { + const saveKey = fileCacheInfo.relatedModules[loadCacheKey] + if (saveKey) { + loadResult = await server._persistentCache.read(saveKey) + } + } + } + if (loadResult == null) { // if this is an html request and there is no load result, skip ahead to // SPA fallback. @@ -232,10 +276,6 @@ async function loadAndTransform( // persistent cache - const includedInPersistentCache = - server._persistentCache && - (!server.config.resolvedServerPersistentCacheOptions?.exclude || - !server.config.resolvedServerPersistentCacheOptions.exclude(url)) const persistentCacheKey = includedInPersistentCache ? (server._persistentCache?.getKey(id + code) ?? '') + (options.ssr ? '-ssr' : '') From 061e645fa152899031767425467b88335ae4c547 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Fri, 28 Oct 2022 03:17:20 +0200 Subject: [PATCH 08/58] fix: resolve `versionFromFiles` path from `resolvedRoot` --- packages/vite/src/node/config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index 8191ef87c084dc..62563136b261a4 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -674,8 +674,9 @@ export async function resolveConfig( ? path.join(path.dirname(pkgPath), `node_modules/.vite-server-cache`) : path.join(resolvedRoot, `.vite-server-cache`) - const cacheVersionFromFiles: string[] = + const cacheVersionFromFiles: string[] = ( castedToObject?.cacheVersionFromFiles ?? [] + ).map((file) => path.join(resolvedRoot, file)) if (resolvedConfigFile) { cacheVersionFromFiles.push(resolvedConfigFile) From d1283652c209be8b9d1b23f2f43e9caae578f9dc Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Fri, 28 Oct 2022 17:13:04 +0200 Subject: [PATCH 09/58] fix: not waiting for clearing the cache files --- packages/vite/src/node/server/persistentCache.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index 4d07647df3199e..e2c4b70083e691 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -87,9 +87,7 @@ export async function createPersistentCache( // Empty the directory const files = await fs.promises.readdir(resolvedCacheDir) await Promise.all( - files.map((file) => - fs.promises.unlink(path.join(resolvedCacheDir, file)) - ) + files.map((file) => fs.promises.unlink(path.join(resolvedCacheDir, file))) ) } catch (e) { logger.warn( From 138afc0ec58b41626132cbc11335092c2ab87038 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Fri, 28 Oct 2022 17:49:18 +0200 Subject: [PATCH 10/58] feat: clearing cache log --- packages/vite/src/node/server/persistentCache.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index e2c4b70083e691..34f104b17fb104 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -82,12 +82,19 @@ export async function createPersistentCache( try { manifest = JSON.parse(await fs.promises.readFile(manifestPath, 'utf-8')) if (manifest && manifest.version !== cacheVersion) { - // Burst cache if version changed + // Bust cache if version changed + logger.info( + colors.blue( + `Clearing persistent cache (${cacheVersion} from ${manifest.version})...` + ) + ) try { // Empty the directory const files = await fs.promises.readdir(resolvedCacheDir) await Promise.all( - files.map((file) => fs.promises.unlink(path.join(resolvedCacheDir, file))) + files.map((file) => + fs.promises.unlink(path.join(resolvedCacheDir, file)) + ) ) } catch (e) { logger.warn( From 97673722151a283ba1ee0f34f85064ef3ba977e6 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Fri, 28 Oct 2022 17:57:05 +0200 Subject: [PATCH 11/58] feat: clearer generated cacheVersion --- packages/vite/src/node/config.ts | 3 ++- .../vite/src/node/server/persistentCache.ts | 18 +++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index 62563136b261a4..d90d7dcc0fed41 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -703,7 +703,8 @@ export async function resolveConfig( cacheVersion: castedToObject?.cacheVersion ?? '', exclude: castedToObject?.exclude } - resolvedServerPersistentCacheOptions.cacheVersion += version + // Add vite version + resolvedServerPersistentCacheOptions.cacheVersion += `(vite:${version})` } else { resolvedServerPersistentCacheOptions = null } diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index 34f104b17fb104..705155150e09e1 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -64,15 +64,15 @@ export async function createPersistentCache( // Cache version - const cacheVersion = - (await Promise.all( - options.cacheVersionFromFiles.map((file) => { - if (!fs.existsSync(file)) { - throw new Error(`Persistent cache version file not found: ${file}`) - } - return fs.promises.readFile(file, 'utf-8') - }) - ).then((codes) => hashCode(codes.join('')))) + options.cacheVersion + const hashedVersionFiles = await Promise.all( + options.cacheVersionFromFiles.map((file) => { + if (!fs.existsSync(file)) { + throw new Error(`Persistent cache version file not found: ${file}`) + } + return fs.promises.readFile(file, 'utf-8') + }) + ).then((codes) => hashCode(codes.join(''))) + const cacheVersion = `${options.cacheVersion}-${hashedVersionFiles}` // Manifest From 228670cd3b0e792b6c44edb508a0024eb064d9e7 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Sat, 29 Oct 2022 01:07:45 +0200 Subject: [PATCH 12/58] feat: auto include tsconfig in versionFromFiles --- packages/vite/src/node/config.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index d90d7dcc0fed41..9e112df5b87a1f 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -697,6 +697,13 @@ export async function resolveConfig( cacheVersionFromFiles.push(packageLockFile) } + const tsconfigFile = lookupFile(resolvedRoot, ['tsconfig.json'], { + pathOnly: true + }) + if (tsconfigFile) { + cacheVersionFromFiles.push(tsconfigFile) + } + resolvedServerPersistentCacheOptions = { cacheDir: dir, cacheVersionFromFiles, From d45302c0a57bfe775073a2af9c2608d0a0d45877 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Sat, 29 Oct 2022 01:21:29 +0200 Subject: [PATCH 13/58] refactor: move resolve options from config to persistentCache --- packages/vite/src/node/config.ts | 65 ++------------- .../vite/src/node/server/persistentCache.ts | 83 ++++++++++++++++++- 2 files changed, 87 insertions(+), 61 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index 9e112df5b87a1f..3c3476d2e63b39 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -60,7 +60,7 @@ import type { PackageCache } from './packages' import { loadEnv, resolveEnvPrefix } from './env' import type { ResolvedSSROptions, SSROptions } from './ssr' import { resolveSSROptions } from './ssr' -import { version } from './publicUtils' +import { resolvePersistentCacheOptions } from './server/persistentCache' const debug = createDebugger('vite:config') @@ -655,66 +655,13 @@ export async function resolveConfig( const resolvedConfigFile = configFile ? normalizePath(configFile) : undefined - // [experimental] Server persistent caching - - let resolvedServerPersistentCacheOptions: ResolvedServerPersistentCacheOptions | null - if ( - config.experimental?.serverPersistentCaching != null && - (config.experimental?.serverPersistentCaching !== false || - (typeof config.experimental?.serverPersistentCaching === 'object' && - config.experimental.serverPersistentCaching.enabled !== false)) - ) { - const castedToObject = - typeof config.experimental?.serverPersistentCaching === 'object' - ? config.experimental.serverPersistentCaching - : null - const dir = castedToObject?.cacheDir - ? path.resolve(resolvedRoot, castedToObject.cacheDir) - : pkgPath - ? path.join(path.dirname(pkgPath), `node_modules/.vite-server-cache`) - : path.join(resolvedRoot, `.vite-server-cache`) - - const cacheVersionFromFiles: string[] = ( - castedToObject?.cacheVersionFromFiles ?? [] - ).map((file) => path.join(resolvedRoot, file)) - - if (resolvedConfigFile) { - cacheVersionFromFiles.push(resolvedConfigFile) - } - - const packageLockFile = lookupFile( + const resolvedServerPersistentCacheOptions = + await resolvePersistentCacheOptions({ + config, + pkgPath, resolvedRoot, - [ - 'package-lock.json', - 'yarn.lock', - 'pnpm-lock.yaml', - 'bun.lockb', - 'npm-shrinkwrap.json' - ], - { pathOnly: true } - ) - if (packageLockFile) { - cacheVersionFromFiles.push(packageLockFile) - } - - const tsconfigFile = lookupFile(resolvedRoot, ['tsconfig.json'], { - pathOnly: true + resolvedConfigFile }) - if (tsconfigFile) { - cacheVersionFromFiles.push(tsconfigFile) - } - - resolvedServerPersistentCacheOptions = { - cacheDir: dir, - cacheVersionFromFiles, - cacheVersion: castedToObject?.cacheVersion ?? '', - exclude: castedToObject?.exclude - } - // Add vite version - resolvedServerPersistentCacheOptions.cacheVersion += `(vite:${version})` - } else { - resolvedServerPersistentCacheOptions = null - } const resolvedConfig: ResolvedConfig = { configFile: resolvedConfigFile, diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index 705155150e09e1..3136ec16d679e7 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -2,8 +2,13 @@ import fs from 'node:fs' import path from 'node:path' import crypto from 'node:crypto' import colors from 'picocolors' -import type { ResolvedConfig } from '../config' -import { normalizePath } from '../publicUtils' +import type { + InlineConfig, + ResolvedConfig, + ResolvedServerPersistentCacheOptions +} from '../config' +import { normalizePath, version } from '../publicUtils' +import { lookupFile } from '../utils' export interface PersistentCache { manifest: PersistentCacheManifest @@ -223,3 +228,77 @@ export async function createPersistentCache( queueManifestWrite } } + +interface ResolveServerPersistentCacheConfigPayload { + config: InlineConfig + pkgPath: string | undefined + resolvedRoot: string + resolvedConfigFile: string | undefined +} + +export async function resolvePersistentCacheOptions( + payload: ResolveServerPersistentCacheConfigPayload +): Promise { + const { config, resolvedRoot, pkgPath, resolvedConfigFile } = payload + + let resolvedServerPersistentCacheOptions: ResolvedServerPersistentCacheOptions | null + if ( + config.experimental?.serverPersistentCaching != null && + (config.experimental?.serverPersistentCaching !== false || + (typeof config.experimental?.serverPersistentCaching === 'object' && + config.experimental.serverPersistentCaching.enabled !== false)) + ) { + const castedToObject = + typeof config.experimental?.serverPersistentCaching === 'object' + ? config.experimental.serverPersistentCaching + : null + const dir = castedToObject?.cacheDir + ? path.resolve(resolvedRoot, castedToObject.cacheDir) + : pkgPath + ? path.join(path.dirname(pkgPath), `node_modules/.vite-server-cache`) + : path.join(resolvedRoot, `.vite-server-cache`) + + const cacheVersionFromFiles: string[] = ( + castedToObject?.cacheVersionFromFiles ?? [] + ).map((file) => path.join(resolvedRoot, file)) + + if (resolvedConfigFile) { + cacheVersionFromFiles.push(resolvedConfigFile) + } + + const packageLockFile = lookupFile( + resolvedRoot, + [ + 'package-lock.json', + 'yarn.lock', + 'pnpm-lock.yaml', + 'bun.lockb', + 'npm-shrinkwrap.json' + ], + { pathOnly: true } + ) + if (packageLockFile) { + cacheVersionFromFiles.push(packageLockFile) + } + + const tsconfigFile = lookupFile(resolvedRoot, ['tsconfig.json'], { + pathOnly: true + }) + if (tsconfigFile) { + cacheVersionFromFiles.push(tsconfigFile) + } + + resolvedServerPersistentCacheOptions = { + cacheDir: dir, + cacheVersionFromFiles, + cacheVersion: castedToObject?.cacheVersion ?? '', + exclude: castedToObject?.exclude + } + // Add vite version + resolvedServerPersistentCacheOptions.cacheVersion += `(vite:${version})` + } else { + resolvedServerPersistentCacheOptions = null + } + + return resolvedServerPersistentCacheOptions +} From f4ff16b3f0acb4fdf88c225d5d6e25a5a7c87f9b Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Sat, 29 Oct 2022 02:34:04 +0200 Subject: [PATCH 14/58] feat: save request id in manifest --- .../vite/src/node/server/persistentCache.ts | 18 ++++++++++++++++-- .../vite/src/node/server/transformRequest.ts | 10 ++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index 3136ec16d679e7..95523bf9c6b0c3 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -14,7 +14,13 @@ export interface PersistentCache { manifest: PersistentCacheManifest getKey: (code: string) => string read: (key: string) => Promise - write: (key: string, file: string, code: string, map?: any) => Promise + write: ( + key: string, + id: string, + file: string, + code: string, + map?: any + ) => Promise queueManifestWrite: () => void } @@ -25,6 +31,7 @@ export interface PersistentCacheManifest { } export interface PersistentCacheEntry { + id: string file: string fileCode: string fileMap?: string @@ -194,7 +201,13 @@ export async function createPersistentCache( } } - async function write(key: string, file: string, code: string, map?: any) { + async function write( + key: string, + id: string, + file: string, + code: string, + map?: any + ) { try { const fileCode = path.resolve(resolvedCacheDir, 'c-' + key) const fileMap = map ? fileCode + '-map' : undefined @@ -205,6 +218,7 @@ export async function createPersistentCache( } resolvedManifest.modules[key] = { + id, file, fileCode, fileMap diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index ee8afb7976f301..f29e62d1c4b8be 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -202,7 +202,7 @@ async function loadAndTransform( code = loadResult.code map = loadResult.map } - await server._persistentCache.write(saveKey, file, code, map) + await server._persistentCache.write(saveKey, id, file, code, map) fileCacheInfo.relatedModules[loadCacheKey] = saveKey server._persistentCache.queueManifestWrite() } else { @@ -331,7 +331,13 @@ async function loadAndTransform( } as TransformResult) if (includedInPersistentCache) { - await server._persistentCache?.write(persistentCacheKey, file, code, map) + await server._persistentCache?.write( + persistentCacheKey, + id, + file, + code, + map + ) } } From 8c512e6a65c1f0a733ca66eb7c874085f5e0701c Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Sat, 29 Oct 2022 03:06:44 +0200 Subject: [PATCH 15/58] fix: manifest write debounce --- packages/vite/src/node/server/persistentCache.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index 95523bf9c6b0c3..bc19bdf50b4b31 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -135,24 +135,30 @@ export async function createPersistentCache( let isManifestWriteQueued = false let isManifestWriting = false + let manifestWriteTimer: any = null function queueManifestWrite() { if (isManifestWriteQueued) { return } - + isManifestWriteQueued = true if (isManifestWriting) { - isManifestWriteQueued = true return } - setTimeout(async () => { + writeManifest() + } + + function writeManifest() { + clearTimeout(manifestWriteTimer) + manifestWriteTimer = setTimeout(async () => { isManifestWriting = true try { await fs.promises.writeFile( manifestPath, JSON.stringify(resolvedManifest, null, 2) ) + logger.info(colors.blue(`Persistent cache manifest saved`)) } catch (e) { logger.warn( colors.yellow( @@ -164,9 +170,9 @@ export async function createPersistentCache( if (isManifestWriteQueued) { isManifestWriteQueued = false - queueManifestWrite() + writeManifest() } - }, 500) + }, 1000) } // Methods From 5750ddbcf26ed73341ec88ef1f26849e5c7ff063 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Sat, 29 Oct 2022 23:36:14 +0200 Subject: [PATCH 16/58] feat: cleanup stale cache files --- .../vite/src/node/server/persistentCache.ts | 62 +++++++++++++------ 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index bc19bdf50b4b31..63172f4034a00a 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -93,29 +93,53 @@ export async function createPersistentCache( if (fs.existsSync(manifestPath)) { try { manifest = JSON.parse(await fs.promises.readFile(manifestPath, 'utf-8')) - if (manifest && manifest.version !== cacheVersion) { - // Bust cache if version changed - logger.info( - colors.blue( - `Clearing persistent cache (${cacheVersion} from ${manifest.version})...` - ) - ) - try { - // Empty the directory - const files = await fs.promises.readdir(resolvedCacheDir) - await Promise.all( - files.map((file) => - fs.promises.unlink(path.join(resolvedCacheDir, file)) + if (manifest) { + if (manifest.version !== cacheVersion) { + // Bust cache if version changed + logger.info( + colors.blue( + `Clearing persistent cache (${cacheVersion} from ${manifest.version})...` ) ) - } catch (e) { - logger.warn( - colors.yellow( - `Failed to empty persistent cache directory '${resolvedCacheDir}': ${e.message}` + try { + // Empty the directory + const files = await fs.promises.readdir(resolvedCacheDir) + await Promise.all( + files.map((file) => + fs.promises.unlink(path.join(resolvedCacheDir, file)) + ) ) - ) + logger.info(`Deleted ${files.length} files.`) + } catch (e) { + logger.warn( + colors.yellow( + `Failed to empty persistent cache directory '${resolvedCacheDir}': ${e.message}` + ) + ) + } + manifest = null + } else { + // Clean up stale cache files (no longer present in manifest) + setTimeout(async () => { + const files = await fs.promises.readdir(resolvedCacheDir) + let cleaned = 0 + await Promise.all( + files.map(async (file) => { + const matched = /^c-(.+)(?:-map)?$/.exec(file) + if (matched) { + const key = matched[1] + if (!manifest?.modules[key]) { + await fs.promises.unlink(path.join(resolvedCacheDir, file)) + cleaned++ + } + } + }) + ) + if (cleaned) { + logger.info(`Cleaned ${cleaned} stale cache files.`) + } + }, 10000) } - manifest = null } } catch (e) { logger.warn( From 8c86c754e6890fb243a71ea6502e387d74aa591b Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Sun, 30 Oct 2022 01:17:25 +0200 Subject: [PATCH 17/58] feat: cached modules HMR support --- .../vite/src/node/server/persistentCache.ts | 44 ++++++++++++++- .../vite/src/node/server/transformRequest.ts | 56 ++++++++++++++----- 2 files changed, 83 insertions(+), 17 deletions(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index 63172f4034a00a..ebf5656b9edb8d 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -9,6 +9,7 @@ import type { } from '../config' import { normalizePath, version } from '../publicUtils' import { lookupFile } from '../utils' +import type { ModuleNode } from './moduleGraph' export interface PersistentCache { manifest: PersistentCacheManifest @@ -17,6 +18,8 @@ export interface PersistentCache { write: ( key: string, id: string, + mod: ModuleNode | null, + ssr: boolean, file: string, code: string, map?: any @@ -35,6 +38,12 @@ export interface PersistentCacheEntry { file: string fileCode: string fileMap?: string + importedModules?: string[] + importedBindings?: Record + acceptedHmrDeps?: string[] + acceptedHmrExports?: string[] + isSelfAccepting?: boolean + ssr: boolean } export interface PersistentCacheResult { @@ -234,6 +243,8 @@ export async function createPersistentCache( async function write( key: string, id: string, + mod: ModuleNode | null, + ssr: boolean, file: string, code: string, map?: any @@ -247,13 +258,42 @@ export async function createPersistentCache( await fs.promises.writeFile(fileMap, JSON.stringify(map), 'utf8') } - resolvedManifest.modules[key] = { + const entry: PersistentCacheEntry = { id, file, fileCode, - fileMap + fileMap, + ssr } + if (mod) { + entry.importedModules = Array.from(mod.importedModules) + .map((m) => m.url) + .filter(Boolean) as string[] + const importedBindings: any = {} + if (mod.importedBindings) { + for (const k in mod.importedBindings) { + const s = mod.importedBindings.get(k) + if (s) { + importedBindings[k] = Array.from(s) + } + } + } + entry.importedBindings = importedBindings + + entry.acceptedHmrDeps = Array.from(mod.acceptedHmrDeps) + .map((m) => m.url) + .filter(Boolean) as string[] + + entry.acceptedHmrExports = mod.acceptedHmrExports + ? (Array.from(mod.acceptedHmrExports).filter(Boolean) as string[]) + : [] + + entry.isSelfAccepting = mod.isSelfAccepting + } + + resolvedManifest.modules[key] = entry + queueManifestWrite() } catch (e) { logger.warn( diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index f29e62d1c4b8be..9e6381440fe984 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -157,7 +157,8 @@ async function loadAndTransform( options: TransformOptions, timestamp: number ) { - const { config, pluginContainer, moduleGraph, watcher } = server + const { config, pluginContainer, moduleGraph, watcher, _persistentCache } = + server const { root, logger } = config const prettyUrl = isDebug ? prettifyUrl(url, config.root) : '' const ssr = !!options.ssr @@ -177,23 +178,23 @@ async function loadAndTransform( loadResult = await pluginContainer.load(id, { ssr }) const includedInPersistentCache = - server._persistentCache && + _persistentCache && (!server.config.resolvedServerPersistentCacheOptions?.exclude || !server.config.resolvedServerPersistentCacheOptions.exclude(url)) // Persist load result just in case (for example: svelte component CSS subrequest) if ( - server._persistentCache && + _persistentCache && includedInPersistentCache && idWithoutHmrFlag !== file ) { - const fileCacheInfo = (server._persistentCache.manifest.files[file] = server - ._persistentCache.manifest.files[file] ?? { - relatedModules: {} - }) + const fileCacheInfo = (_persistentCache.manifest.files[file] = + _persistentCache.manifest.files[file] ?? { + relatedModules: {} + }) if (loadResult != null) { - const saveKey = server._persistentCache.getKey(loadCacheKey) + const saveKey = _persistentCache.getKey(loadCacheKey) let code: string let map: any | null if (typeof loadResult === 'string') { @@ -202,13 +203,13 @@ async function loadAndTransform( code = loadResult.code map = loadResult.map } - await server._persistentCache.write(saveKey, id, file, code, map) + await _persistentCache.write(saveKey, id, null, ssr, file, code, map) fileCacheInfo.relatedModules[loadCacheKey] = saveKey - server._persistentCache.queueManifestWrite() + _persistentCache.queueManifestWrite() } else { const saveKey = fileCacheInfo.relatedModules[loadCacheKey] if (saveKey) { - loadResult = await server._persistentCache.read(saveKey) + loadResult = await _persistentCache.read(saveKey) } } } @@ -277,13 +278,36 @@ async function loadAndTransform( // persistent cache const persistentCacheKey = includedInPersistentCache - ? (server._persistentCache?.getKey(id + code) ?? '') + - (options.ssr ? '-ssr' : '') + ? (_persistentCache?.getKey(id + code) ?? '') + (options.ssr ? '-ssr' : '') : '' if (includedInPersistentCache && !code.includes('import.meta.glob')) { - const cached = await server._persistentCache?.read(persistentCacheKey) + const cached = await _persistentCache?.read(persistentCacheKey) if (cached) { + // Restore module graph node info for HMR + const entry = _persistentCache?.manifest.modules[persistentCacheKey] + if ( + entry && + entry.importedModules && + entry.importedBindings && + entry.acceptedHmrDeps && + entry.acceptedHmrExports + ) { + const importedBindings = new Map>() + for (const [key, value] of Object.entries(entry.importedBindings)) { + importedBindings.set(key, new Set(value)) + } + await moduleGraph.updateModuleInfo( + mod, + new Set(entry.importedModules), + importedBindings, + new Set(entry.acceptedHmrDeps), + new Set(entry.acceptedHmrExports), + entry.isSelfAccepting as boolean, + entry.ssr + ) + } + result = { code: cached.code, map: cached.map, @@ -331,9 +355,11 @@ async function loadAndTransform( } as TransformResult) if (includedInPersistentCache) { - await server._persistentCache?.write( + await _persistentCache?.write( persistentCacheKey, id, + mod, + ssr, file, code, map From 830b5fbfcf0e83c94cbe15151b9aeea5f154acd3 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Sun, 30 Oct 2022 01:18:05 +0200 Subject: [PATCH 18/58] fix: disable cache file cleanup for now --- .../vite/src/node/server/persistentCache.ts | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index ebf5656b9edb8d..2042b7a4256a03 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -128,26 +128,27 @@ export async function createPersistentCache( } manifest = null } else { - // Clean up stale cache files (no longer present in manifest) - setTimeout(async () => { - const files = await fs.promises.readdir(resolvedCacheDir) - let cleaned = 0 - await Promise.all( - files.map(async (file) => { - const matched = /^c-(.+)(?:-map)?$/.exec(file) - if (matched) { - const key = matched[1] - if (!manifest?.modules[key]) { - await fs.promises.unlink(path.join(resolvedCacheDir, file)) - cleaned++ - } - } - }) - ) - if (cleaned) { - logger.info(`Cleaned ${cleaned} stale cache files.`) - } - }, 10000) + // @TODO fix this + // // Clean up stale cache files (no longer present in manifest) + // setTimeout(async () => { + // const files = await fs.promises.readdir(resolvedCacheDir) + // let cleaned = 0 + // await Promise.all( + // files.map(async (file) => { + // const matched = /^c-(.+)(?:-map)?$/.exec(file) + // if (matched) { + // const key = matched[1] + // if (!manifest?.modules[key]) { + // await fs.promises.unlink(path.join(resolvedCacheDir, file)) + // cleaned++ + // } + // } + // }) + // ) + // if (cleaned) { + // logger.info(`Cleaned ${cleaned} stale cache files.`) + // } + // }, 10000) } } } catch (e) { From 0410cd375926df4585bbaae90e6a5351d07821b1 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Sun, 30 Oct 2022 01:35:14 +0200 Subject: [PATCH 19/58] fix: state cache files cleanup --- .../vite/src/node/server/persistentCache.ts | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index 2042b7a4256a03..97cbbdef6fa72b 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -128,27 +128,26 @@ export async function createPersistentCache( } manifest = null } else { - // @TODO fix this - // // Clean up stale cache files (no longer present in manifest) - // setTimeout(async () => { - // const files = await fs.promises.readdir(resolvedCacheDir) - // let cleaned = 0 - // await Promise.all( - // files.map(async (file) => { - // const matched = /^c-(.+)(?:-map)?$/.exec(file) - // if (matched) { - // const key = matched[1] - // if (!manifest?.modules[key]) { - // await fs.promises.unlink(path.join(resolvedCacheDir, file)) - // cleaned++ - // } - // } - // }) - // ) - // if (cleaned) { - // logger.info(`Cleaned ${cleaned} stale cache files.`) - // } - // }, 10000) + // Clean up stale cache files (no longer present in manifest) + setTimeout(async () => { + const files = await fs.promises.readdir(resolvedCacheDir) + let cleaned = 0 + await Promise.all( + files.map(async (file) => { + const matched = /^c-([\w\d]+)(?:-map)?$/.exec(file) + if (matched) { + const key = matched[1] + if (!manifest?.modules[key]) { + await fs.promises.unlink(path.join(resolvedCacheDir, file)) + cleaned++ + } + } + }) + ) + if (cleaned) { + logger.info(`Cleaned ${cleaned} stale cache files.`) + } + }, 10000) } } } catch (e) { From f4b2e5ef1d9b351f7d71478a9d1c35b6f9729236 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 1 Nov 2022 04:10:27 +0100 Subject: [PATCH 20/58] feat: store url too --- packages/vite/src/node/server/persistentCache.ts | 4 ++++ packages/vite/src/node/server/transformRequest.ts | 12 +++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index 97cbbdef6fa72b..fcc28ad9951bb7 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -18,6 +18,7 @@ export interface PersistentCache { write: ( key: string, id: string, + url: string | undefined, mod: ModuleNode | null, ssr: boolean, file: string, @@ -35,6 +36,7 @@ export interface PersistentCacheManifest { export interface PersistentCacheEntry { id: string + url?: string file: string fileCode: string fileMap?: string @@ -243,6 +245,7 @@ export async function createPersistentCache( async function write( key: string, id: string, + url: string | undefined, mod: ModuleNode | null, ssr: boolean, file: string, @@ -260,6 +263,7 @@ export async function createPersistentCache( const entry: PersistentCacheEntry = { id, + url, file, fileCode, fileMap, diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index 9e6381440fe984..fc59825dc1bdcf 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -203,7 +203,16 @@ async function loadAndTransform( code = loadResult.code map = loadResult.map } - await _persistentCache.write(saveKey, id, null, ssr, file, code, map) + await _persistentCache.write( + saveKey, + id, + undefined, + null, + ssr, + file, + code, + map + ) fileCacheInfo.relatedModules[loadCacheKey] = saveKey _persistentCache.queueManifestWrite() } else { @@ -358,6 +367,7 @@ async function loadAndTransform( await _persistentCache?.write( persistentCacheKey, id, + url, mod, ssr, file, From 8dd8dd7ee5cf95183a225e106297623540d843d1 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 1 Nov 2022 04:11:14 +0100 Subject: [PATCH 21/58] refactor: simplify resolvePersistentCacheOptions --- .../vite/src/node/server/persistentCache.ts | 100 ++++++++---------- 1 file changed, 47 insertions(+), 53 deletions(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index fcc28ad9951bb7..0bf888e6d8e8bf 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -329,64 +329,58 @@ export async function resolvePersistentCacheOptions( ): Promise { const { config, resolvedRoot, pkgPath, resolvedConfigFile } = payload - let resolvedServerPersistentCacheOptions: ResolvedServerPersistentCacheOptions | null if ( - config.experimental?.serverPersistentCaching != null && - (config.experimental?.serverPersistentCaching !== false || - (typeof config.experimental?.serverPersistentCaching === 'object' && - config.experimental.serverPersistentCaching.enabled !== false)) + !config.experimental?.serverPersistentCaching || + (typeof config.experimental?.serverPersistentCaching === 'object' && + config.experimental.serverPersistentCaching?.enabled === false) ) { - const castedToObject = - typeof config.experimental?.serverPersistentCaching === 'object' - ? config.experimental.serverPersistentCaching - : null - const dir = castedToObject?.cacheDir - ? path.resolve(resolvedRoot, castedToObject.cacheDir) - : pkgPath - ? path.join(path.dirname(pkgPath), `node_modules/.vite-server-cache`) - : path.join(resolvedRoot, `.vite-server-cache`) - - const cacheVersionFromFiles: string[] = ( - castedToObject?.cacheVersionFromFiles ?? [] - ).map((file) => path.join(resolvedRoot, file)) - - if (resolvedConfigFile) { - cacheVersionFromFiles.push(resolvedConfigFile) - } + return null + } - const packageLockFile = lookupFile( - resolvedRoot, - [ - 'package-lock.json', - 'yarn.lock', - 'pnpm-lock.yaml', - 'bun.lockb', - 'npm-shrinkwrap.json' - ], - { pathOnly: true } - ) - if (packageLockFile) { - cacheVersionFromFiles.push(packageLockFile) - } + const castedToObject = + typeof config.experimental?.serverPersistentCaching === 'object' + ? config.experimental.serverPersistentCaching + : null + const dir = castedToObject?.cacheDir + ? path.resolve(resolvedRoot, castedToObject.cacheDir) + : pkgPath + ? path.join(path.dirname(pkgPath), `node_modules/.vite-server-cache`) + : path.join(resolvedRoot, `.vite-server-cache`) + + const cacheVersionFromFiles: string[] = ( + castedToObject?.cacheVersionFromFiles ?? [] + ).map((file) => path.join(resolvedRoot, file)) + + if (resolvedConfigFile) { + cacheVersionFromFiles.push(resolvedConfigFile) + } - const tsconfigFile = lookupFile(resolvedRoot, ['tsconfig.json'], { - pathOnly: true - }) - if (tsconfigFile) { - cacheVersionFromFiles.push(tsconfigFile) - } + const packageLockFile = lookupFile( + resolvedRoot, + [ + 'package-lock.json', + 'yarn.lock', + 'pnpm-lock.yaml', + 'bun.lockb', + 'npm-shrinkwrap.json' + ], + { pathOnly: true } + ) + if (packageLockFile) { + cacheVersionFromFiles.push(packageLockFile) + } - resolvedServerPersistentCacheOptions = { - cacheDir: dir, - cacheVersionFromFiles, - cacheVersion: castedToObject?.cacheVersion ?? '', - exclude: castedToObject?.exclude - } - // Add vite version - resolvedServerPersistentCacheOptions.cacheVersion += `(vite:${version})` - } else { - resolvedServerPersistentCacheOptions = null + const tsconfigFile = lookupFile(resolvedRoot, ['tsconfig.json'], { + pathOnly: true + }) + if (tsconfigFile) { + cacheVersionFromFiles.push(tsconfigFile) } - return resolvedServerPersistentCacheOptions + return { + cacheDir: dir, + cacheVersionFromFiles, + cacheVersion: `${castedToObject?.cacheVersion ?? ''}(vite:${version})`, + exclude: castedToObject?.exclude + } } From 967d8cd7ef8a4d76329d759c77bbe082233312ea Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 1 Nov 2022 04:12:02 +0100 Subject: [PATCH 22/58] refactor: remove cleanup --- .../vite/src/node/server/persistentCache.ts | 63 ++++++------------- 1 file changed, 20 insertions(+), 43 deletions(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index 0bf888e6d8e8bf..178a49efaed2b8 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -104,53 +104,30 @@ export async function createPersistentCache( if (fs.existsSync(manifestPath)) { try { manifest = JSON.parse(await fs.promises.readFile(manifestPath, 'utf-8')) - if (manifest) { - if (manifest.version !== cacheVersion) { - // Bust cache if version changed - logger.info( - colors.blue( - `Clearing persistent cache (${cacheVersion} from ${manifest.version})...` - ) + if (manifest && manifest.version !== cacheVersion) { + // Bust cache if version changed + logger.info( + colors.blue( + `Clearing persistent cache (${cacheVersion} from ${manifest.version})...` ) - try { - // Empty the directory - const files = await fs.promises.readdir(resolvedCacheDir) - await Promise.all( - files.map((file) => - fs.promises.unlink(path.join(resolvedCacheDir, file)) - ) - ) - logger.info(`Deleted ${files.length} files.`) - } catch (e) { - logger.warn( - colors.yellow( - `Failed to empty persistent cache directory '${resolvedCacheDir}': ${e.message}` - ) + ) + try { + // Empty the directory + const files = await fs.promises.readdir(resolvedCacheDir) + await Promise.all( + files.map((file) => + fs.promises.unlink(path.join(resolvedCacheDir, file)) ) - } - manifest = null - } else { - // Clean up stale cache files (no longer present in manifest) - setTimeout(async () => { - const files = await fs.promises.readdir(resolvedCacheDir) - let cleaned = 0 - await Promise.all( - files.map(async (file) => { - const matched = /^c-([\w\d]+)(?:-map)?$/.exec(file) - if (matched) { - const key = matched[1] - if (!manifest?.modules[key]) { - await fs.promises.unlink(path.join(resolvedCacheDir, file)) - cleaned++ - } - } - }) + ) + logger.info(`Deleted ${files.length} files.`) + } catch (e) { + logger.warn( + colors.yellow( + `Failed to empty persistent cache directory '${resolvedCacheDir}': ${e.message}` ) - if (cleaned) { - logger.info(`Cleaned ${cleaned} stale cache files.`) - } - }, 10000) + ) } + manifest = null } } catch (e) { logger.warn( From 6b3259947e2d169968094804fe3ab26adff882ba Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 1 Nov 2022 04:16:22 +0100 Subject: [PATCH 23/58] refactor: debug log --- packages/vite/src/node/server/persistentCache.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index 178a49efaed2b8..41c8c16ab05274 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -8,7 +8,7 @@ import type { ResolvedServerPersistentCacheOptions } from '../config' import { normalizePath, version } from '../publicUtils' -import { lookupFile } from '../utils' +import { createDebugger, lookupFile } from '../utils' import type { ModuleNode } from './moduleGraph' export interface PersistentCache { @@ -70,6 +70,7 @@ export async function createPersistentCache( } const logger = config.logger + const debugLog = createDebugger('vite:persistent-cache') logger.warn( colors.yellow( @@ -106,10 +107,8 @@ export async function createPersistentCache( manifest = JSON.parse(await fs.promises.readFile(manifestPath, 'utf-8')) if (manifest && manifest.version !== cacheVersion) { // Bust cache if version changed - logger.info( - colors.blue( - `Clearing persistent cache (${cacheVersion} from ${manifest.version})...` - ) + debugLog( + `Clearing persistent cache (${cacheVersion} from ${manifest.version})...` ) try { // Empty the directory @@ -170,7 +169,7 @@ export async function createPersistentCache( manifestPath, JSON.stringify(resolvedManifest, null, 2) ) - logger.info(colors.blue(`Persistent cache manifest saved`)) + debugLog(`Persistent cache manifest saved`) } catch (e) { logger.warn( colors.yellow( From d9695fba2506c4ed7674b12f998c5eaa34e98167 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 1 Nov 2022 04:17:25 +0100 Subject: [PATCH 24/58] fix: wording --- packages/vite/src/node/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index 3c3476d2e63b39..5cfb6391d09a16 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -314,7 +314,7 @@ export interface ServerPersistentCacheOptions { cacheVersionFromFiles?: string[] /** * Manual version string that should be taken into account when determining whether to clear the cache. - * Will be added to the result of `cacheVersionFromFiles`. + * Will be added to the hash of `cacheVersionFromFiles`. */ cacheVersion?: string /** From 59fcf27d84a1c1ea6ca4345cc5d619ba1ad05eda Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 1 Nov 2022 04:18:32 +0100 Subject: [PATCH 25/58] perf: readFileSync manifest --- packages/vite/src/node/server/persistentCache.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index 41c8c16ab05274..e886ba75f7d815 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -104,7 +104,7 @@ export async function createPersistentCache( let manifest: PersistentCacheManifest | null = null if (fs.existsSync(manifestPath)) { try { - manifest = JSON.parse(await fs.promises.readFile(manifestPath, 'utf-8')) + manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) if (manifest && manifest.version !== cacheVersion) { // Bust cache if version changed debugLog( From 60663a818b1a4f743d7f018a5125cd5630f74e39 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 1 Nov 2022 04:21:25 +0100 Subject: [PATCH 26/58] refactor: change cache dir location under .vite --- packages/vite/src/node/config.ts | 2 +- packages/vite/src/node/server/persistentCache.ts | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index 5cfb6391d09a16..5d6e8601f50034 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -658,7 +658,7 @@ export async function resolveConfig( const resolvedServerPersistentCacheOptions = await resolvePersistentCacheOptions({ config, - pkgPath, + cacheDir, resolvedRoot, resolvedConfigFile }) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index e886ba75f7d815..dd635117676f68 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -295,7 +295,7 @@ export async function createPersistentCache( interface ResolveServerPersistentCacheConfigPayload { config: InlineConfig - pkgPath: string | undefined + cacheDir: string resolvedRoot: string resolvedConfigFile: string | undefined } @@ -303,7 +303,7 @@ interface ResolveServerPersistentCacheConfigPayload { export async function resolvePersistentCacheOptions( payload: ResolveServerPersistentCacheConfigPayload ): Promise { - const { config, resolvedRoot, pkgPath, resolvedConfigFile } = payload + const { config, resolvedRoot, cacheDir, resolvedConfigFile } = payload if ( !config.experimental?.serverPersistentCaching || @@ -319,9 +319,7 @@ export async function resolvePersistentCacheOptions( : null const dir = castedToObject?.cacheDir ? path.resolve(resolvedRoot, castedToObject.cacheDir) - : pkgPath - ? path.join(path.dirname(pkgPath), `node_modules/.vite-server-cache`) - : path.join(resolvedRoot, `.vite-server-cache`) + : path.join(cacheDir, `server-cache`) const cacheVersionFromFiles: string[] = ( castedToObject?.cacheVersionFromFiles ?? [] From 662231b62b7d0c2bcdce83e6e44551bdbedb30c4 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 1 Nov 2022 04:22:55 +0100 Subject: [PATCH 27/58] refactor: use isDefined --- packages/vite/src/node/server/persistentCache.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/server/persistentCache.ts b/packages/vite/src/node/server/persistentCache.ts index dd635117676f68..852ddd29bfeacf 100644 --- a/packages/vite/src/node/server/persistentCache.ts +++ b/packages/vite/src/node/server/persistentCache.ts @@ -8,7 +8,7 @@ import type { ResolvedServerPersistentCacheOptions } from '../config' import { normalizePath, version } from '../publicUtils' -import { createDebugger, lookupFile } from '../utils' +import { createDebugger, isDefined, lookupFile } from '../utils' import type { ModuleNode } from './moduleGraph' export interface PersistentCache { @@ -263,7 +263,7 @@ export async function createPersistentCache( entry.acceptedHmrDeps = Array.from(mod.acceptedHmrDeps) .map((m) => m.url) - .filter(Boolean) as string[] + .filter(isDefined) entry.acceptedHmrExports = mod.acceptedHmrExports ? (Array.from(mod.acceptedHmrExports).filter(Boolean) as string[]) From f895075eea0d62b1b51135eb26fac422d9661b0a Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 1 Nov 2022 04:25:34 +0100 Subject: [PATCH 28/58] chore: more comments --- packages/vite/src/node/server/transformRequest.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index fc59825dc1bdcf..c4f330f439a30c 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -182,7 +182,12 @@ async function loadAndTransform( (!server.config.resolvedServerPersistentCacheOptions?.exclude || !server.config.resolvedServerPersistentCacheOptions.exclude(url)) - // Persist load result just in case (for example: svelte component CSS subrequest) + // Persist load result just in case it depends on a previous `transform` call + // that got cached (aka skipped) + // For example: svelte component CSS subrequest + // - `transform` is called on `MyComponent.svelte` => saves `