Skip to content

Commit ebb827f

Browse files
authored
feat(webpack): support tsconfig.app.json when present (#10221)
1 parent 6059984 commit ebb827f

File tree

4 files changed

+154
-52
lines changed

4 files changed

+154
-52
lines changed

packages/webpack5/__tests__/configuration/base.spec.ts

Lines changed: 134 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,84 @@ describe('base configuration', () => {
2222
});
2323
}
2424

25+
it('supports tsconfig.app.json if exists', () => {
26+
const fsSpy = jest.spyOn(fs, 'existsSync');
27+
fsSpy.withImplementation(
28+
(path) => {
29+
return path.toString().endsWith('tsconfig.app.json');
30+
},
31+
() => {
32+
init({
33+
ios: true,
34+
});
35+
const config = base(new Config());
36+
37+
expect(fsSpy).toHaveBeenCalledWith('__jest__/tsconfig.app.json');
38+
expect(fsSpy).not.toHaveBeenCalledWith('__jest__/tsconfig.json');
39+
40+
let configFiles = [];
41+
42+
config.module
43+
.rule('ts')
44+
.use('ts-loader')
45+
.tap((options) => {
46+
configFiles.push(options.configFile);
47+
return options;
48+
});
49+
50+
config.plugin('ForkTsCheckerWebpackPlugin').tap((args) => {
51+
configFiles.push(args.at(0).typescript.configFile);
52+
return args;
53+
});
54+
55+
expect(configFiles.length).toBe(2);
56+
expect(configFiles).toEqual([
57+
'__jest__/tsconfig.app.json', // ts-loader
58+
'__jest__/tsconfig.app.json', // fork-ts-checker
59+
]);
60+
}
61+
);
62+
});
63+
64+
it('falls back to tsconfig.json if no tsconfig.app.json exists', () => {
65+
const fsSpy = jest.spyOn(fs, 'existsSync');
66+
fsSpy.withImplementation(
67+
(path) => {
68+
return path.toString().endsWith('tsconfig.json');
69+
},
70+
() => {
71+
init({
72+
ios: true,
73+
});
74+
const config = base(new Config());
75+
76+
expect(fsSpy).toHaveBeenCalledWith('__jest__/tsconfig.app.json');
77+
expect(fsSpy).toHaveBeenCalledWith('__jest__/tsconfig.json');
78+
79+
let configFiles = [];
80+
81+
config.module
82+
.rule('ts')
83+
.use('ts-loader')
84+
.tap((options) => {
85+
configFiles.push(options.configFile);
86+
return options;
87+
});
88+
89+
config.plugin('ForkTsCheckerWebpackPlugin').tap((args) => {
90+
configFiles.push(args.at(0).typescript.configFile);
91+
return args;
92+
});
93+
94+
expect(configFiles.length).toBe(2);
95+
expect(configFiles).toEqual([
96+
'__jest__/tsconfig.json', // ts-loader
97+
'__jest__/tsconfig.json', // fork-ts-checker
98+
]);
99+
}
100+
);
101+
});
102+
25103
it('support env.watchNodeModules', () => {
26104
init({
27105
ios: true,
@@ -32,60 +110,73 @@ describe('base configuration', () => {
32110

33111
it('supports dotenv', () => {
34112
const fsSpy = jest.spyOn(fs, 'existsSync');
35-
fsSpy.mockReturnValue(true);
36-
37-
init({
38-
ios: true,
39-
});
40-
const config = base(new Config());
41-
42-
expect(config.plugin('DotEnvPlugin')).toBeDefined();
43-
config.plugin('DotEnvPlugin').tap((args) => {
44-
expect(args[0].path).toEqual('__jest__/.env');
45-
return args;
46-
});
113+
fsSpy.withImplementation(
114+
(path) => {
115+
return path.toString().endsWith('__jest__/.env');
116+
},
117+
() => {
118+
init({
119+
ios: true,
120+
});
121+
const config = base(new Config());
122+
123+
expect(config.plugin('DotEnvPlugin')).toBeDefined();
124+
config.plugin('DotEnvPlugin').tap((args) => {
125+
expect(args[0].path).toEqual('__jest__/.env');
126+
return args;
127+
});
128+
}
129+
);
47130

48131
fsSpy.mockRestore();
49132
});
50133

51134
it('supports env specific dotenv', () => {
52135
const fsSpy = jest.spyOn(fs, 'existsSync');
53-
fsSpy.mockReturnValue(true);
54-
55-
init({
56-
ios: true,
57-
env: 'prod',
58-
});
59-
const config = base(new Config());
60-
61-
expect(fsSpy).toHaveBeenCalledWith('__jest__/.env.prod');
62-
expect(fsSpy).toHaveBeenCalledTimes(1);
63-
expect(config.plugin('DotEnvPlugin')).toBeDefined();
64-
config.plugin('DotEnvPlugin').tap((args) => {
65-
expect(args[0].path).toEqual('__jest__/.env.prod');
66-
return args;
67-
});
136+
fsSpy.withImplementation(
137+
(path) => {
138+
return path.toString().endsWith('__jest__/.env.prod');
139+
},
140+
() => {
141+
init({
142+
ios: true,
143+
env: 'prod',
144+
});
145+
const config = base(new Config());
146+
147+
expect(fsSpy).toHaveBeenCalledWith('__jest__/.env.prod');
148+
expect(config.plugin('DotEnvPlugin')).toBeDefined();
149+
config.plugin('DotEnvPlugin').tap((args) => {
150+
expect(args[0].path).toEqual('__jest__/.env.prod');
151+
return args;
152+
});
153+
}
154+
);
68155
fsSpy.mockRestore();
69156
});
70157

71158
it('falls back to default .env', () => {
72159
const fsSpy = jest.spyOn(fs, 'existsSync');
73-
fsSpy.mockReturnValueOnce(false).mockReturnValueOnce(true);
74-
75-
init({
76-
ios: true,
77-
env: 'prod',
78-
});
79-
const config = base(new Config());
80-
81-
expect(fsSpy).toHaveBeenCalledWith('__jest__/.env.prod');
82-
expect(fsSpy).toHaveBeenCalledWith('__jest__/.env');
83-
expect(fsSpy).toHaveBeenCalledTimes(2);
84-
expect(config.plugin('DotEnvPlugin')).toBeDefined();
85-
config.plugin('DotEnvPlugin').tap((args) => {
86-
expect(args[0].path).toEqual('__jest__/.env');
87-
return args;
88-
});
160+
fsSpy.withImplementation(
161+
(path) => {
162+
return path.toString().endsWith('__jest__/.env');
163+
},
164+
() => {
165+
init({
166+
ios: true,
167+
env: 'prod',
168+
});
169+
const config = base(new Config());
170+
171+
expect(fsSpy).toHaveBeenCalledWith('__jest__/.env.prod');
172+
expect(fsSpy).toHaveBeenCalledWith('__jest__/.env');
173+
expect(config.plugin('DotEnvPlugin')).toBeDefined();
174+
config.plugin('DotEnvPlugin').tap((args) => {
175+
expect(args[0].path).toEqual('__jest__/.env');
176+
return args;
177+
});
178+
}
179+
);
89180
fsSpy.mockRestore();
90181
});
91182

packages/webpack5/src/configuration/angular.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { existsSync } from 'fs';
44

55
import { getTypescript, readTsConfig } from '../helpers/typescript';
66
import { getDependencyPath } from '../helpers/dependencies';
7-
import { getProjectFilePath } from '../helpers/project';
7+
import { getProjectTSConfigPath } from '../helpers/project';
88
import { env as _env, IWebpackEnv } from '../index';
99
import { warnOnce } from '../helpers/log';
1010
import {
@@ -18,12 +18,7 @@ export default function (config: Config, env: IWebpackEnv = _env): Config {
1818
base(config, env);
1919

2020
const platform = getPlatformName();
21-
22-
const tsConfigPath = [
23-
getProjectFilePath('tsconfig.app.json'),
24-
getProjectFilePath('tsconfig.json'),
25-
].find((path) => existsSync(path));
26-
21+
const tsConfigPath = getProjectTSConfigPath();
2722
const disableAOT = !!env.disableAOT;
2823

2924
// remove default ts rule

packages/webpack5/src/configuration/base.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { PlatformSuffixPlugin } from '../plugins/PlatformSuffixPlugin';
1515
import { applyFileReplacements } from '../helpers/fileReplacements';
1616
import { addCopyRule, applyCopyRules } from '../helpers/copyRules';
1717
import { WatchStatePlugin } from '../plugins/WatchStatePlugin';
18-
import { getProjectFilePath } from '../helpers/project';
18+
import { getProjectFilePath, getProjectTSConfigPath } from '../helpers/project';
1919
import { hasDependency } from '../helpers/dependencies';
2020
import { applyDotEnvPlugin } from '../helpers/dotEnv';
2121
import { env as _env, IWebpackEnv } from '../index';
@@ -234,6 +234,13 @@ export default function (config: Config, env: IWebpackEnv = _env): Config {
234234
.use('nativescript-worker-loader')
235235
.loader('nativescript-worker-loader');
236236

237+
const tsConfigPath = getProjectTSConfigPath();
238+
const configFile = tsConfigPath
239+
? {
240+
configFile: tsConfigPath,
241+
}
242+
: undefined;
243+
237244
// set up ts support
238245
config.module
239246
.rule('ts')
@@ -243,7 +250,7 @@ export default function (config: Config, env: IWebpackEnv = _env): Config {
243250
.options({
244251
// todo: perhaps we can provide a default tsconfig
245252
// and use that if the project doesn't have one?
246-
// configFile: '',
253+
...configFile,
247254
transpileOnly: true,
248255
allowTsInNodeModules: true,
249256
compilerOptions: {
@@ -266,6 +273,7 @@ export default function (config: Config, env: IWebpackEnv = _env): Config {
266273
async: !!env.watch,
267274
typescript: {
268275
memoryLimit: 4096,
276+
...configFile,
269277
},
270278
},
271279
]);

packages/webpack5/src/helpers/project.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { existsSync } from 'fs';
12
import { resolve } from 'path';
23

34
export function getProjectRootPath(): string {
@@ -30,6 +31,13 @@ export function getProjectFilePath(filePath: string): string {
3031
return resolve(getProjectRootPath(), filePath);
3132
}
3233

34+
export function getProjectTSConfigPath(): string | undefined {
35+
return [
36+
getProjectFilePath('tsconfig.app.json'),
37+
getProjectFilePath('tsconfig.json'),
38+
].find((path) => existsSync(path));
39+
}
40+
3341
// unused helper, but keeping it here as we may need it
3442
// todo: remove if unused for next few releases
3543
// function findFile(fileName, currentDir): string | null {

0 commit comments

Comments
 (0)