Skip to content

Commit

Permalink
chore(compiler): improve performance for isolatedModules: false (#1558
Browse files Browse the repository at this point in the history
)
  • Loading branch information
ahnpnl committed Apr 22, 2020
1 parent ec62440 commit f1d1b6e
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 251 deletions.
48 changes: 0 additions & 48 deletions appveyor.yml

This file was deleted.

12 changes: 6 additions & 6 deletions e2e/__tests__/__snapshots__/logger.test.ts.snap
Expand Up @@ -22,14 +22,14 @@ Array [
"[level:20] file caching disabled",
"[level:20] initializeLanguageServiceInstance(): create typescript compiler",
"[level:20] compileUsingLanguageService(): creating language service",
"[level:20] readThrough(): no cache",
"[level:20] compileAndCacheResult(): no cache",
"[level:20] compileFn(): compiling using language service",
"[level:20] updateMemoryCache(): update memory cache for language service",
"[level:20] visitSourceFileNode(): hoisting",
"[level:20] compileFn(): computing diagnostics for <cwd>/Hello.spec.ts using language service",
"[level:20] computing cache key for <cwd>/Hello.ts",
"[level:20] processing <cwd>/Hello.ts",
"[level:20] readThrough(): no cache",
"[level:20] compileAndCacheResult(): no cache",
"[level:20] compileFn(): compiling using language service",
"[level:20] updateMemoryCache(): update memory cache for language service",
"[level:20] visitSourceFileNode(): hoisting",
Expand Down Expand Up @@ -63,15 +63,15 @@ Array [
"[level:20] file caching disabled",
"[level:20] initializeLanguageServiceInstance(): create typescript compiler",
"[level:20] compileUsingLanguageService(): creating language service",
"[level:20] readThrough(): no cache",
"[level:20] compileAndCacheResult(): no cache",
"[level:20] compileFn(): compiling using language service",
"[level:20] updateMemoryCache(): update memory cache for language service",
"[level:20] visitSourceFileNode(): hoisting",
"[level:20] compileFn(): computing diagnostics for <cwd>/Hello.spec.ts using language service",
"[level:20] calling babel-jest processor",
"[level:20] computing cache key for <cwd>/Hello.ts",
"[level:20] processing <cwd>/Hello.ts",
"[level:20] readThrough(): no cache",
"[level:20] compileAndCacheResult(): no cache",
"[level:20] compileFn(): compiling using language service",
"[level:20] updateMemoryCache(): update memory cache for language service",
"[level:20] visitSourceFileNode(): hoisting",
Expand Down Expand Up @@ -107,15 +107,15 @@ Array [
"[level:20] file caching disabled",
"[level:20] initializeLanguageServiceInstance(): create typescript compiler",
"[level:20] compileUsingLanguageService(): creating language service",
"[level:20] readThrough(): no cache",
"[level:20] compileAndCacheResult(): no cache",
"[level:20] compileFn(): compiling using language service",
"[level:20] updateMemoryCache(): update memory cache for language service",
"[level:20] visitSourceFileNode(): hoisting",
"[level:20] compileFn(): computing diagnostics for <cwd>/Hello.spec.ts using language service",
"[level:20] calling babel-jest processor",
"[level:20] computing cache key for <cwd>/Hello.ts",
"[level:20] processing <cwd>/Hello.ts",
"[level:20] readThrough(): no cache",
"[level:20] compileAndCacheResult(): no cache",
"[level:20] compileFn(): compiling using language service",
"[level:20] updateMemoryCache(): update memory cache for language service",
"[level:20] visitSourceFileNode(): hoisting",
Expand Down
2 changes: 2 additions & 0 deletions src/__helpers__/fakers.ts
Expand Up @@ -72,6 +72,8 @@ export function makeCompiler({
...jestConfig,
testMatch: ['^.+\\.tsx?$'],
testRegex: jestConfig?.testRegex ? [...testRegex, ...jestConfig.testRegex] : testRegex,
setupFiles: [],
setupFilesAfterEnv: [],
}
const cs = new ConfigSet(getJestConfig(jestConfig, tsJestConfig), parentConfig)

Expand Down
67 changes: 0 additions & 67 deletions src/compiler/compiler-utils.spec.ts

This file was deleted.

9 changes: 3 additions & 6 deletions src/compiler/compiler-utils.ts
Expand Up @@ -12,18 +12,15 @@ import { sha1 } from '../util/sha1'
/**
* @internal
*/
export const hasOwn = Object.prototype.hasOwnProperty
/**
* @internal
*/
export function getResolvedModulesCache(cachedir: string): string {
return join(cachedir, sha1('ts-jest-resolved-modules', '\x00'))
export function getResolvedModulesCache(cacheDir: string): string {
return join(cacheDir, sha1('ts-jest-resolved-modules', '\x00'))
}

/**
* @internal
* Get resolved modules of a test file and put into memory cache
*/
/* istanbul ignore next (we leave this for e2e) */
export function cacheResolvedModules(
fileName: string,
fileContent: string,
Expand Down
100 changes: 49 additions & 51 deletions src/compiler/instance.ts
Expand Up @@ -32,7 +32,7 @@
import { Logger } from 'bs-logger'
import { readFileSync, writeFileSync } from 'fs'
import mkdirp = require('mkdirp')
import { basename, extname, join, normalize } from 'path'
import { basename, extname, join } from 'path'

import { ConfigSet } from '../config/config-set'
import { CompileFn, CompilerInstance, MemoryCache, TSFile, TsCompiler } from '../types'
Expand Down Expand Up @@ -92,60 +92,54 @@ const isValidCacheContent = (contents: string): boolean => {
* cache mode
*/
const compileAndCacheResult = (
cachedir: string | undefined,
cacheDir: string | undefined,
memoryCache: MemoryCache,
compileFn: CompileFn,
getExtension: (fileName: string) => string,
logger: Logger,
) => {
if (!cachedir) {
return (code: string, fileName: string, lineOffset?: number) => {
const normalizedFileName = normalize(fileName)

logger.debug({ normalizedFileName }, 'readThrough(): no cache')

const [value, sourceMap] = compileFn(code, normalizedFileName, lineOffset)
return (code: string, fileName: string, lineOffset?: number) => {
function getCompileOutput(): string {
const [value, sourceMap] = compileFn(code, fileName, lineOffset)
const output = updateOutput(value, fileName, sourceMap, getExtension)
memoryCache.outputs[normalizedFileName] = output
memoryCache.files.set(fileName, {
...memoryCache.files.get(fileName)!,
output,
})

return output
}
}

// Make sure the cache directory exists before continuing.
mkdirp.sync(cachedir)
try {
const resolvedModulesCache = readFileSync(getResolvedModulesCache(cachedir), 'utf-8')
/* istanbul ignore next (covered by e2e) */
memoryCache.resolvedModules = JSON.parse(resolvedModulesCache)
} catch (e) {}
if (!cacheDir) {
logger.debug({ fileName }, 'compileAndCacheResult(): no cache')

return (code: string, fileName: string, lineOffset?: number) => {
const normalizedFileName = normalize(fileName)
const cachePath = join(cachedir, getCacheName(code, normalizedFileName))
const extension = getExtension(normalizedFileName)
const outputPath = `${cachePath}${extension}`
try {
const output = readFileSync(outputPath, 'utf8')
if (isValidCacheContent(output)) {
logger.debug({ normalizedFileName }, 'readThrough(): cache hit')
memoryCache.outputs[normalizedFileName] = output
return getCompileOutput()
} else {
const cachePath = join(cacheDir, getCacheName(code, fileName))
const extension = getExtension(fileName)
const outputPath = `${cachePath}${extension}`
try {
const output = readFileSync(outputPath, 'utf8')
if (isValidCacheContent(output)) {
logger.debug({ fileName }, 'compileAndCacheResult(): cache hit')
memoryCache.files.set(fileName, {
...memoryCache.files.get(fileName)!,
output,
})

return output
}
} catch (err) {}
return output
}
} catch (err) {}

logger.debug({ fileName }, 'readThrough(): cache miss')
logger.debug({ fileName }, 'compileAndCacheResult(): cache miss')

const [value, sourceMap] = compileFn(code, normalizedFileName, lineOffset)
const output = updateOutput(value, normalizedFileName, sourceMap, getExtension)
const output = getCompileOutput()

logger.debug({ normalizedFileName, outputPath }, 'readThrough(): writing caches')
logger.debug({ fileName, outputPath }, 'compileAndCacheResult(): writing caches')

memoryCache.outputs[normalizedFileName] = output
writeFileSync(outputPath, output)
writeFileSync(outputPath, output)

return output
return output
}
}
}

Expand All @@ -156,16 +150,13 @@ const compileAndCacheResult = (
export const createCompilerInstance = (configs: ConfigSet): TsCompiler => {
const logger = configs.logger.child({ namespace: 'ts-compiler' })
const {
typescript: { options: compilerOptions, fileNames },
typescript: { options: compilerOptions },
tsJest,
} = configs
const cachedir = configs.tsCacheDir
const cacheDir = configs.tsCacheDir
const ts = configs.compilerModule // Require the TypeScript compiler and configuration.
const extensions = ['.ts', '.tsx']
const memoryCache: MemoryCache = {
contents: Object.create(null),
versions: Object.create(null),
outputs: Object.create(null),
resolvedModules: Object.create(null),
files: new Map<string, TSFile>(),
}
Expand All @@ -174,14 +165,21 @@ export const createCompilerInstance = (configs: ConfigSet): TsCompiler => {
extensions.push('.js')
extensions.push('.jsx')
}
// Initialize files from TypeScript into project.
for (const path of fileNames) {
const normalizedFilePath = normalize(path)
memoryCache.versions[normalizedFilePath] = 1
memoryCache.files.set(normalizedFilePath, {
if (cacheDir) {
// Make sure the cache directory exists before continuing.
mkdirp.sync(cacheDir)
try {
const resolvedModulesCache = readFileSync(getResolvedModulesCache(cacheDir), 'utf-8')
/* istanbul ignore next (covered by e2e) */
memoryCache.resolvedModules = JSON.parse(resolvedModulesCache)
} catch (e) {}
}
/* istanbul ignore next (we leave this for e2e) */
configs.jest.setupFiles.concat(configs.jest.setupFilesAfterEnv).forEach(setupFile => {
memoryCache.files.set(setupFile, {
version: 0,
})
}
})
/**
* Get the extension for a transpiled file.
*/
Expand All @@ -196,7 +194,7 @@ export const createCompilerInstance = (configs: ConfigSet): TsCompiler => {
} else {
compilerInstance = initializeTranspilerInstance(configs, memoryCache, logger)
}
const compile = compileAndCacheResult(cachedir, memoryCache, compilerInstance.compileFn, getExtension, logger)
const compile = compileAndCacheResult(cacheDir, memoryCache, compilerInstance.compileFn, getExtension, logger)

return { cwd: configs.cwd, compile, program: compilerInstance.program }
}

0 comments on commit f1d1b6e

Please sign in to comment.