Skip to content

Commit f51c4a7

Browse files
committed
perf(babel): uses babel-jest cache key as part of ours
1 parent 0ed1587 commit f51c4a7

9 files changed

Lines changed: 121 additions & 159 deletions

README.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,13 +206,13 @@ module.exports = {
206206
### Using `babel-jest`
207207
By default ts-jest does not rely on babel-jest. But you may want to use some babel plugins and stll be able to write TypeScript. This can be achieved using the `babelJest` config key. It can be:
208208

209-
- `true`, in which case it'll try to find a babel configuration file:
209+
- `true`, in which case it'll use defaults from babelrc or any other found config file:
210210
```js
211211
// jest.config.js
212212
module.exports = {
213213
globals: {
214214
'ts-jest': {
215-
babelConfig: true
215+
babelJest: true
216216
}
217217
}
218218
};
@@ -224,7 +224,7 @@ By default ts-jest does not rely on babel-jest. But you may want to use some bab
224224
module.exports = {
225225
globals: {
226226
'ts-jest': {
227-
babelConfig: 'babelrc.test.js'
227+
babelJest: 'babelrc.test.js'
228228
}
229229
}
230230
};
@@ -236,7 +236,7 @@ By default ts-jest does not rely on babel-jest. But you may want to use some bab
236236
module.exports = {
237237
globals: {
238238
'ts-jest': {
239-
babelConfig: {
239+
babelJest: {
240240
plugins: [
241241
// ...
242242
]
@@ -246,6 +246,18 @@ By default ts-jest does not rely on babel-jest. But you may want to use some bab
246246
};
247247
```
248248

249+
- `false`, in which case it'll disable the use of babel-jest (which is the default):
250+
```js
251+
// jest.config.js
252+
module.exports = {
253+
globals: {
254+
'ts-jest': {
255+
babelJest: false
256+
}
257+
}
258+
};
259+
```
260+
249261
### TS compiler & error reporting
250262

251263
<center>=== TBD ===</center>

src/ts-jest-transformer.spec.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import TsJestTransformer from './ts-jest-transformer';
1+
import TsJestTransformerOriginal from './ts-jest-transformer';
22
import * as fakers from './__helpers__/fakers';
3-
import * as babelCfg from './utils/babel-config';
43
import * as closesPkgJson from './utils/closest-package-json';
54
import * as TsJestProgram from './ts-program';
65

@@ -9,28 +8,35 @@ jest.mock('./utils/closest-package-json');
98
jest.mock('./utils/backports');
109

1110
const mocks = {
12-
babelConfig: undefined as any,
11+
babelJestCacheKey: undefined as any,
1312
set packageJson(val: any) {
1413
(closesPkgJson as any).__default = val;
1514
},
1615
set tsConfig(val: any) {
1716
(TsJestProgram as any).__tsConfig = val;
1817
},
1918
reset() {
20-
this.babelConfig = undefined;
19+
this.babelJestCacheKey = 'babel-jest-cache-key';
2120
this.packageJson = { name: 'mock' };
2221
this.tsConfig = {};
2322
},
2423
};
25-
beforeAll(() => {
26-
jest
27-
.spyOn(babelCfg, 'loadDefault')
28-
.mockImplementation(() => mocks.babelConfig);
29-
});
3024
afterEach(() => {
3125
mocks.reset();
3226
});
3327

28+
class TsJestTransformer extends TsJestTransformerOriginal {
29+
babelJestFor(jestCfg: jest.ProjectConfig) {
30+
const bj = super.babelJestFor(jestCfg);
31+
if (bj && !(bj.getCacheKey as any).mock) {
32+
jest
33+
.spyOn(bj, 'getCacheKey')
34+
.mockImplementation(() => mocks.babelJestCacheKey);
35+
}
36+
return bj;
37+
}
38+
}
39+
3440
describe('process', () => {
3541
describe('hoisting', () => {
3642
const transformer = new TsJestTransformer();
@@ -78,7 +84,10 @@ describe('getCacheKey', () => {
7884
const call: typeof TsJestTransformer['prototype']['getCacheKey'] = (
7985
// tslint:disable-next-line:trailing-comma
8086
...args
81-
) => new TsJestTransformer().getCacheKey(...args);
87+
) => {
88+
const tr = new TsJestTransformer();
89+
return tr.getCacheKey(...args);
90+
};
8291
const defaultCall = () => call(fakeSource, fakeFilePath, fakeJestConfig);
8392

8493
it('should be a 28 chars string, different for each case', () => {
@@ -91,7 +100,7 @@ describe('getCacheKey', () => {
91100
call(fakeSource, fakeFilePath, fakeJestConfig, { rootDir: '/child' }),
92101
];
93102

94-
mocks.babelConfig = '{sourceMaps: true}';
103+
mocks.babelJestCacheKey = 'another-babel-jest-cache-key';
95104
allCacheKeys.push(defaultCall());
96105
mocks.reset();
97106

src/ts-jest-transformer.ts

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
TsJestConfig,
44
BabelConfig,
55
TsJestHooksMap,
6+
BabelJestTransformer,
67
} from './types';
78
import TsProgram from './ts-program';
89
import Memoize from './utils/memoize';
@@ -11,7 +12,6 @@ import { backportJestConfig } from './utils/backports';
1112
import jestRootDir from './utils/jest-root-dir';
1213
import { sep, resolve } from 'path';
1314
import parseJsonUnsafe from './utils/parse-json-unsafe';
14-
import * as babelCfg from './utils/babel-config';
1515
import closestPatckageJson from './utils/closest-package-json';
1616
import sha1 from './utils/sha1';
1717
import importer from './utils/importer';
@@ -42,25 +42,28 @@ export default class TsJestTransformer implements jest.Transformer {
4242
}
4343

4444
@Memoize(jestRootDir)
45-
babelJestFor(jestConfig: jest.ProjectConfig): jest.Transformer {
45+
babelJestFor(
46+
jestConfig: jest.ProjectConfig,
47+
): BabelJestTransformer | undefined {
48+
const babelJestConfig = this.babelJestConfigFor(jestConfig);
49+
if (!babelJestConfig) {
50+
return;
51+
}
4652
return importer
4753
.babelJest(ImportReasons.babelJest)
48-
.createTransformer(this.babelConfigFor(jestConfig));
54+
.createTransformer(babelJestConfig) as BabelJestTransformer;
4955
}
5056

5157
@Memoize(jestRootDir)
52-
babelConfigFor(jestConfig: jest.ProjectConfig): BabelConfig | undefined {
58+
babelJestConfigFor(jestConfig: jest.ProjectConfig): BabelConfig | undefined {
5359
const config = this.configFor(jestConfig);
5460
const rootDir = jestRootDir(jestConfig);
5561
if (config.babelJest === false) {
5662
return;
5763
}
5864

5965
let babelConfig!: BabelConfig;
60-
if (config.babelJest === true) {
61-
// lookup babelrc file
62-
babelConfig = babelCfg.extend({}, babelCfg.loadDefault(rootDir));
63-
} else if (typeof config.babelJest === 'string') {
66+
if (typeof config.babelJest === 'string') {
6467
// path to a babelrc file
6568
let filePath = config.babelJest.replace('<rootDir>', `${rootDir}${sep}`);
6669
filePath = resolve(rootDir, filePath);
@@ -70,8 +73,7 @@ export default class TsJestTransformer implements jest.Transformer {
7073
babelConfig = config.babelJest;
7174
}
7275

73-
// ensure to return a freezed copy object
74-
return babelCfg.freeze(babelCfg.extend({}, babelConfig));
76+
return babelConfig;
7577
}
7678

7779
@Memoize(jestRootDir)
@@ -99,6 +101,11 @@ export default class TsJestTransformer implements jest.Transformer {
99101
stringifyRegEx = undefined;
100102
}
101103

104+
// babelJest true => {}
105+
if (options.babelJest === true) {
106+
options.babelJest = {};
107+
}
108+
102109
// parsed options
103110
return {
104111
inputOptions: options,
@@ -126,7 +133,7 @@ export default class TsJestTransformer implements jest.Transformer {
126133
const stringify =
127134
config.stringifyContentPathRegex &&
128135
config.stringifyContentPathRegex.test(filePath);
129-
const useBabelJest = !stringify && config.babelJest;
136+
const babelJest = !stringify && this.babelJestFor(jestConfig);
130137

131138
// get the tranformer instance
132139
const program = this.programFor(jestConfig);
@@ -142,8 +149,8 @@ export default class TsJestTransformer implements jest.Transformer {
142149
result = program.transpileModule(filePath, source, instrument);
143150

144151
// calling babel-jest transformer
145-
if (useBabelJest) {
146-
result = this.babelJestFor(jestConfig).process(
152+
if (babelJest) {
153+
result = babelJest.process(
147154
result,
148155
filePath,
149156
jestConfig,
@@ -170,11 +177,10 @@ export default class TsJestTransformer implements jest.Transformer {
170177
fileContent: string,
171178
filePath: string,
172179
jestConfigStr: string,
173-
{
174-
instrument = false,
175-
rootDir,
176-
}: { instrument?: boolean; rootDir?: string } = {},
180+
transformOptions: { instrument?: boolean; rootDir?: string } = {},
177181
): string {
182+
// tslint:disable-next-line:prefer-const
183+
let { instrument = false, rootDir } = transformOptions;
178184
const CHAR0 = '\0';
179185
// will be used as the hashing data source
180186
const hashData: string[] = [];
@@ -192,14 +198,24 @@ export default class TsJestTransformer implements jest.Transformer {
192198
const sanitizedJestConfig: jest.ProjectConfig = this.sanitizedJestConfigFor(
193199
jestConfig,
194200
);
201+
195202
// add jest config
196203
hashUpdate(JSON.stringify(sanitizedJestConfig));
197204
// add project's package.json
198205
const projectPkg = closestPatckageJson(rootDir, true);
199206
hashUpdate(projectPkg);
200-
// add babel config if using babel jest
201-
const babelConfig = this.babelConfigFor(jestConfig) || {};
202-
hashUpdate(JSON.stringify(babelConfig));
207+
// if using babel jest, adds its cacheKey as well
208+
const babelJest = this.babelJestFor(jestConfig);
209+
if (babelJest) {
210+
hashUpdate(
211+
babelJest.getCacheKey(
212+
fileContent,
213+
filePath,
214+
jestConfigStr,
215+
transformOptions as any,
216+
),
217+
);
218+
}
203219
// add tsconfig
204220
const tsConfig = this.programFor(sanitizedJestConfig).parsedConfig;
205221
hashUpdate(JSON.stringify(tsConfig));

src/types.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ export type TBabelCore = typeof _babel;
77
export type TPackageJson = IPackageJSON;
88
export type TClosestFileData = typeof _closestFileData;
99
export type TBabelJest = Required<jest.Transformer>;
10+
export type BabelJestTransformer = {
11+
[K in Exclude<keyof jest.Transformer, 'createTransformer'>]: Exclude<
12+
jest.Transformer[K],
13+
undefined
14+
>
15+
};
1016

1117
// CAUTION: use same key-value pair allow us to not store a list of values somewhere
1218
export enum DiagnosticTypes {
@@ -53,7 +59,7 @@ export interface TsJestGlobalOptions {
5359

5460
export interface TsJestConfig {
5561
inputOptions: TsJestGlobalOptions;
56-
babelJest: BabelConfig | string | boolean;
62+
babelJest: BabelConfig | string | false;
5763
diagnostics: DiagnosticTypes[];
5864

5965
// to deprecate / deprecated === === ===

src/utils/babel-config.spec.ts

Lines changed: 0 additions & 53 deletions
This file was deleted.

src/utils/babel-config.ts

Lines changed: 0 additions & 57 deletions
This file was deleted.

0 commit comments

Comments
 (0)