diff --git a/packages/compiler-sfc/src/cache.ts b/packages/compiler-sfc/src/cache.ts index 0bedc7b4d35..abc81274d19 100644 --- a/packages/compiler-sfc/src/cache.ts +++ b/packages/compiler-sfc/src/cache.ts @@ -1,11 +1,32 @@ import { LRUCache } from 'lru-cache' +export const COMPILER_CACHE_KEYS = { + parse: 'parse', + templateUsageCheck: 'templateUsageCheck', + tsConfig: 'tsConfig', + fileToScope: 'fileToScope', +} as const + +type CacheKey = keyof typeof COMPILER_CACHE_KEYS +type CacheOptions = Partial< + Record> +> + +let cacheOptions: CacheOptions = Object.create(null) + export function createCache( - max = 500, + key: CacheKey, ): Map | LRUCache { /* v8 ignore next 3 */ if (__GLOBAL__ || __ESM_BROWSER__) { return new Map() } - return new LRUCache({ max }) + return new LRUCache(cacheOptions[key] || { max: 500 }) +} + +/** + * @private + */ +export function configureCacheOptions(options: CacheOptions = {}): void { + cacheOptions = options } diff --git a/packages/compiler-sfc/src/index.ts b/packages/compiler-sfc/src/index.ts index 5123a908976..f890122b7b1 100644 --- a/packages/compiler-sfc/src/index.ts +++ b/packages/compiler-sfc/src/index.ts @@ -44,6 +44,9 @@ export { invalidateTypeCache, registerTS } from './script/resolveType' export { extractRuntimeProps } from './script/defineProps' export { extractRuntimeEmits } from './script/defineEmits' +// Internals for cache control +export { configureCacheOptions } from './cache' + // Types export type { SFCParseOptions, diff --git a/packages/compiler-sfc/src/parse.ts b/packages/compiler-sfc/src/parse.ts index 9172cfc67ff..0e1d9547156 100644 --- a/packages/compiler-sfc/src/parse.ts +++ b/packages/compiler-sfc/src/parse.ts @@ -14,7 +14,7 @@ import * as CompilerDOM from '@vue/compiler-dom' import { SourceMapGenerator } from 'source-map-js' import type { TemplateCompiler } from './compileTemplate' import { parseCssVars } from './style/cssVars' -import { createCache } from './cache' +import { COMPILER_CACHE_KEYS, createCache } from './cache' import type { ImportBinding } from './compileScript' import { isUsedInTemplate } from './script/importUsageCheck' import type { LRUCache } from 'lru-cache' @@ -102,9 +102,9 @@ export interface SFCParseResult { errors: (CompilerError | SyntaxError)[] } -export const parseCache: +export let parseCache: | Map - | LRUCache = createCache() + | LRUCache export function parse( source: string, @@ -114,7 +114,10 @@ export function parse( ...options, compiler: { parse: options.compiler?.parse }, }) - const cache = parseCache.get(sourceKey) + const cache = ( + parseCache || + (parseCache = createCache(COMPILER_CACHE_KEYS.parse)) + ).get(sourceKey) if (cache) { return cache } diff --git a/packages/compiler-sfc/src/script/importUsageCheck.ts b/packages/compiler-sfc/src/script/importUsageCheck.ts index 6fc16db446b..19c8c62e1d8 100644 --- a/packages/compiler-sfc/src/script/importUsageCheck.ts +++ b/packages/compiler-sfc/src/script/importUsageCheck.ts @@ -7,8 +7,9 @@ import { parserOptions, walkIdentifiers, } from '@vue/compiler-dom' -import { createCache } from '../cache' +import { COMPILER_CACHE_KEYS, createCache } from '../cache' import { camelize, capitalize, isBuiltInDirective } from '@vue/shared' +import type { LRUCache } from 'lru-cache' /** * Check if an identifier is used in the SFC's template. @@ -23,11 +24,16 @@ export function isUsedInTemplate( return resolveTemplateUsedIdentifiers(sfc).has(identifier) } -const templateUsageCheckCache = createCache>() +let templateUsageCheckCache: LRUCache> function resolveTemplateUsedIdentifiers(sfc: SFCDescriptor): Set { const { content, ast } = sfc.template! - const cached = templateUsageCheckCache.get(content) + const cached = ( + templateUsageCheckCache || + (templateUsageCheckCache = createCache>( + COMPILER_CACHE_KEYS.templateUsageCheck, + ) as LRUCache>) + ).get(content) if (cached) { return cached } diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index d8f43070050..020eaf8da56 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -37,11 +37,12 @@ import type { ImportBinding, SFCScriptCompileOptions } from '../compileScript' import { capitalize, hasOwn } from '@vue/shared' import { parse as babelParse } from '@babel/parser' import { parse } from '../parse' -import { createCache } from '../cache' +import { COMPILER_CACHE_KEYS, createCache } from '../cache' import type TS from 'typescript' import { dirname, extname, join } from 'path' import { minimatch as isMatch } from 'minimatch' import * as process from 'process' +import type { LRUCache } from 'lru-cache' export type SimpleTypeResolveOptions = Partial< Pick< @@ -999,7 +1000,7 @@ interface CachedConfig { cache?: TS.ModuleResolutionCache } -const tsConfigCache = createCache() +let tsConfigCache: LRUCache const tsConfigRefMap = new Map() function resolveWithTS( @@ -1018,7 +1019,12 @@ function resolveWithTS( if (configPath) { let configs: CachedConfig[] const normalizedConfigPath = normalizePath(configPath) - const cached = tsConfigCache.get(normalizedConfigPath) + const cached = ( + tsConfigCache || + (tsConfigCache = createCache( + COMPILER_CACHE_KEYS.tsConfig, + ) as LRUCache) + ).get(normalizedConfigPath) if (!cached) { configs = loadTSConfig(configPath, ts, fs).map(config => ({ config })) tsConfigCache.set(normalizedConfigPath, configs) @@ -1123,17 +1129,21 @@ function loadTSConfig( return res } -const fileToScopeCache = createCache() +let fileToScopeCache: LRUCache /** * @private */ export function invalidateTypeCache(filename: string): void { filename = normalizePath(filename) - fileToScopeCache.delete(filename) - tsConfigCache.delete(filename) - const affectedConfig = tsConfigRefMap.get(filename) - if (affectedConfig) tsConfigCache.delete(affectedConfig) + if (fileToScopeCache) { + fileToScopeCache.delete(filename) + } + if (tsConfigCache) { + tsConfigCache.delete(filename) + const affectedConfig = tsConfigRefMap.get(filename) + if (affectedConfig) tsConfigCache.delete(affectedConfig) + } } export function fileToScope( @@ -1141,7 +1151,12 @@ export function fileToScope( filename: string, asGlobal = false, ): TypeScope { - const cached = fileToScopeCache.get(filename) + const cached = ( + fileToScopeCache || + (fileToScopeCache = createCache( + COMPILER_CACHE_KEYS.fileToScope, + ) as LRUCache) + ).get(filename) if (cached) { return cached } @@ -1151,7 +1166,7 @@ export function fileToScope( const body = parseFile(filename, source, fs, ctx.options.babelParserPlugins) const scope = new TypeScope(filename, source, 0, recordImports(body)) recordTypes(ctx, body, scope, asGlobal) - fileToScopeCache.set(filename, scope) + fileToScopeCache!.set(filename, scope) return scope }