Skip to content

Commit

Permalink
feat: add fsCache option to improve build performance (#56)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Fu <github@antfu.me>
  • Loading branch information
sapphi-red and antfu authored Sep 28, 2024
1 parent 5698a87 commit d8eeff0
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 10 deletions.
61 changes: 51 additions & 10 deletions packages/twoslash/src/core.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ErrorLevel, NodeError, NodeWithoutPosition, Position, Range } from 'twoslash-protocol'
import type { CompilerOptions, CompletionEntry, CompletionTriggerKind, DiagnosticCategory, JsxEmit } from 'typescript'
import type { CompilerOptions, CompletionEntry, CompletionTriggerKind, DiagnosticCategory, JsxEmit, System } from 'typescript'

import type { CompilerOptionDeclaration, CreateTwoslashOptions, TwoslashExecuteOptions, TwoslashInstance, TwoslashOptions, TwoslashReturn, TwoslashReturnMeta, VirtualFile } from './types'
import { createFSBackedSystem, createSystem, createVirtualTypeScriptEnvironment } from '@typescript/vfs'
Expand Down Expand Up @@ -28,15 +28,7 @@ export function createTwoslasher(createOptions: CreateTwoslashOptions = {}): Two
const vfs = createOptions.fsMap || new Map<string, string>()
const system = useFS
? createSystem(vfs)
: {
...createFSBackedSystem(vfs, _root, ts, createOptions.tsLibDirectory),
// To work with non-hoisted packages structure
realpath(path: string) {
if (vfs.has(path))
return path
return ts.sys.realpath?.(path) || path
},
}
: createCacheableFSBackedSystem(vfs, _root, ts, createOptions.tsLibDirectory, createOptions.fsCache)
const fsRoot = useFS ? '/' : `${_root}/`

const cache = createOptions.cache === false
Expand Down Expand Up @@ -508,6 +500,55 @@ export function createTwoslasher(createOptions: CreateTwoslashOptions = {}): Two
return twoslasher
}

function createCacheableFSBackedSystem(
vfs: Map<string, string>,
root: string,
ts: TS,
tsLibDirectory?: string,
enableFsCache = true,
): System {
function withCache<T>(fn: (key: string) => T) {
const cache = new Map<string, T>()
return (key: string) => {
const cached = cache.get(key)
if (cached !== undefined)
return cached

const result = fn(key)
cache.set(key, result)
return result
}
}
const cachedReadFile = withCache(ts.sys.readFile)

const cachedTs = enableFsCache
? {
...ts,
sys: {
...ts.sys,
directoryExists: withCache(ts.sys.directoryExists),
fileExists: withCache(ts.sys.fileExists),
...(ts.sys.realpath ? { realpath: withCache(ts.sys.realpath) } : {}),
readFile(path, encoding) {
if (encoding === undefined)
return cachedReadFile(path)
return ts.sys.readFile(path, encoding)
},
} satisfies System,
}
: ts

return {
...createFSBackedSystem(vfs, root, cachedTs, tsLibDirectory),
// To work with non-hoisted packages structure
realpath(path: string) {
if (vfs.has(path))
return path
return cachedTs.sys.realpath?.(path) || path
},
}
}

/**
* Run Twoslash on a string of code
*
Expand Down
7 changes: 7 additions & 0 deletions packages/twoslash/src/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,11 @@ export interface CreateTwoslashOptions extends TwoslashExecuteOptions {
* Cache the ts envs based on compiler options, defaults to true
*/
cache?: boolean | Map<string, VirtualTypeScriptEnvironment>

/**
* Cache file system requests
*
* @default true
*/
fsCache?: boolean
}

0 comments on commit d8eeff0

Please sign in to comment.