Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions packages/compiler-sfc/src/cache.ts
Original file line number Diff line number Diff line change
@@ -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<CacheKey, LRUCache.Options<string, any, unknown>>
>

let cacheOptions: CacheOptions = Object.create(null)

export function createCache<T extends {}>(
max = 500,
key: CacheKey,
): Map<string, T> | LRUCache<string, T> {
/* v8 ignore next 3 */
if (__GLOBAL__ || __ESM_BROWSER__) {
return new Map<string, T>()
}
return new LRUCache({ max })
return new LRUCache<string, T>(cacheOptions[key] || { max: 500 })
}

/**
* @private
*/
export function configureCacheOptions(options: CacheOptions = {}): void {
cacheOptions = options
}
3 changes: 3 additions & 0 deletions packages/compiler-sfc/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
11 changes: 7 additions & 4 deletions packages/compiler-sfc/src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -102,9 +102,9 @@ export interface SFCParseResult {
errors: (CompilerError | SyntaxError)[]
}

export const parseCache:
export let parseCache:
| Map<string, SFCParseResult>
| LRUCache<string, SFCParseResult> = createCache<SFCParseResult>()
| LRUCache<string, SFCParseResult>

export function parse(
source: string,
Expand All @@ -114,7 +114,10 @@ export function parse(
...options,
compiler: { parse: options.compiler?.parse },
})
const cache = parseCache.get(sourceKey)
const cache = (
parseCache ||
(parseCache = createCache<SFCParseResult>(COMPILER_CACHE_KEYS.parse))
).get(sourceKey)
if (cache) {
return cache
}
Expand Down
12 changes: 9 additions & 3 deletions packages/compiler-sfc/src/script/importUsageCheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -23,11 +24,16 @@ export function isUsedInTemplate(
return resolveTemplateUsedIdentifiers(sfc).has(identifier)
}

const templateUsageCheckCache = createCache<Set<string>>()
let templateUsageCheckCache: LRUCache<string, Set<string>>

function resolveTemplateUsedIdentifiers(sfc: SFCDescriptor): Set<string> {
const { content, ast } = sfc.template!
const cached = templateUsageCheckCache.get(content)
const cached = (
templateUsageCheckCache ||
(templateUsageCheckCache = createCache<Set<string>>(
COMPILER_CACHE_KEYS.templateUsageCheck,
) as LRUCache<string, Set<string>>)
).get(content)
if (cached) {
return cached
}
Expand Down
35 changes: 25 additions & 10 deletions packages/compiler-sfc/src/script/resolveType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<
Expand Down Expand Up @@ -999,7 +1000,7 @@ interface CachedConfig {
cache?: TS.ModuleResolutionCache
}

const tsConfigCache = createCache<CachedConfig[]>()
let tsConfigCache: LRUCache<string, CachedConfig[], unknown>
const tsConfigRefMap = new Map<string, string>()

function resolveWithTS(
Expand All @@ -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<CachedConfig[]>(
COMPILER_CACHE_KEYS.tsConfig,
) as LRUCache<string, CachedConfig[], unknown>)
).get(normalizedConfigPath)
if (!cached) {
configs = loadTSConfig(configPath, ts, fs).map(config => ({ config }))
tsConfigCache.set(normalizedConfigPath, configs)
Expand Down Expand Up @@ -1123,25 +1129,34 @@ function loadTSConfig(
return res
}

const fileToScopeCache = createCache<TypeScope>()
let fileToScopeCache: LRUCache<string, TypeScope>

/**
* @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(
ctx: TypeResolveContext,
filename: string,
asGlobal = false,
): TypeScope {
const cached = fileToScopeCache.get(filename)
const cached = (
fileToScopeCache ||
(fileToScopeCache = createCache<TypeScope>(
COMPILER_CACHE_KEYS.fileToScope,
) as LRUCache<string, TypeScope>)
).get(filename)
if (cached) {
return cached
}
Expand All @@ -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
}

Expand Down
Loading