Skip to content

Commit 0cbeb46

Browse files
committed
build: parallel typescript build
1 parent 4809212 commit 0cbeb46

File tree

1 file changed

+116
-50
lines changed

1 file changed

+116
-50
lines changed

src/build/build-tsc.ts

Lines changed: 116 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,53 @@ enum ExitCodes {
1010
ParseError = 4,
1111
}
1212

13+
type CompileResult = {
14+
exitCode: ExitCodes;
15+
logs: string[];
16+
type: "browser" | "cjs" | "esm" | "types";
17+
};
18+
19+
function getDefaultOptions(type: "browser" | "cjs" | "esm" | "types"): unknown {
20+
switch (type) {
21+
case "browser":
22+
return {
23+
extends: "@tsparticles/tsconfig/dist/tsconfig.browser.json",
24+
compilerOptions: {
25+
rootDir: "./src",
26+
outDir: "./dist/browser",
27+
},
28+
include: ["./src"],
29+
};
30+
case "cjs":
31+
return {
32+
extends: "@tsparticles/tsconfig/dist/tsconfig.json",
33+
compilerOptions: {
34+
rootDir: "./src",
35+
outDir: "./dist/cjs",
36+
},
37+
include: ["./src"],
38+
};
39+
case "esm":
40+
return {
41+
extends: "@tsparticles/tsconfig/dist/tsconfig.module.json",
42+
compilerOptions: {
43+
rootDir: "./src",
44+
outDir: "./dist/esm",
45+
},
46+
include: ["./src"],
47+
};
48+
case "types":
49+
return {
50+
extends: "@tsparticles/tsconfig/dist/tsconfig.types.json",
51+
compilerOptions: {
52+
rootDir: "./src",
53+
outDir: "./dist/types",
54+
},
55+
include: ["./src"],
56+
};
57+
}
58+
}
59+
1360
/**
1461
* @param basePath -
1562
* @param file -
@@ -33,89 +80,100 @@ async function readConfig(basePath: string, file: string): Promise<string | unde
3380
* @param silent -
3481
* @returns the exit code
3582
*/
36-
async function compile(basePath: string, type: "browser" | "cjs" | "esm" | "types", silent: boolean): Promise<number> {
83+
async function compile(
84+
basePath: string,
85+
type: "browser" | "cjs" | "esm" | "types",
86+
silent: boolean,
87+
): Promise<CompileResult> {
3788
let options: unknown, data: string | undefined;
89+
const logs: string[] = [];
3890

3991
switch (type) {
4092
case "browser":
4193
data = await readConfig(basePath, "tsconfig.browser.json");
4294

4395
if (!data) {
44-
options = {
45-
extends: "@tsparticles/tsconfig/dist/tsconfig.browser.json",
46-
compilerOptions: {
47-
rootDir: "./src",
48-
outDir: "./dist/browser",
49-
},
50-
include: ["./src"],
51-
};
96+
options = getDefaultOptions(type);
5297
}
5398

5499
break;
55100
case "cjs":
56101
data = await readConfig(basePath, "tsconfig.json");
57102

58103
if (!data) {
59-
options = {
60-
extends: "@tsparticles/tsconfig/dist/tsconfig.json",
61-
compilerOptions: {
62-
rootDir: "./src",
63-
outDir: "./dist/cjs",
64-
},
65-
include: ["./src"],
66-
};
104+
options = getDefaultOptions(type);
67105
}
68106

69107
break;
70108
case "esm":
71109
data = await readConfig(basePath, "tsconfig.module.json");
72110

73111
if (!data) {
74-
options = {
75-
extends: "@tsparticles/tsconfig/dist/tsconfig.module.json",
76-
compilerOptions: {
77-
rootDir: "./src",
78-
outDir: "./dist/esm",
79-
},
80-
include: ["./src"],
81-
};
112+
options = getDefaultOptions(type);
82113
}
83114

84115
break;
85116
case "types":
86117
data = await readConfig(basePath, "tsconfig.types.json");
87118

88119
if (!data) {
89-
options = {
90-
extends: "@tsparticles/tsconfig/dist/tsconfig.types.json",
91-
compilerOptions: {
92-
rootDir: "./src",
93-
outDir: "./dist/types",
94-
},
95-
include: ["./src"],
96-
};
120+
options = getDefaultOptions(type);
97121
}
98122

99123
break;
100124
}
101125

102126
if (!data && !options) {
103-
return ExitCodes.NoDataOrOptions;
127+
logs.push(`No TS config found for ${type} build.`);
128+
129+
return {
130+
type,
131+
logs,
132+
exitCode: ExitCodes.NoDataOrOptions,
133+
};
104134
}
105135

106136
if (!options && data) {
107137
options = JSON.parse(data);
108138
}
109139

110140
if (!options) {
111-
return ExitCodes.NoOptions;
141+
logs.push(`No TS options available for ${type} build.`);
142+
143+
return {
144+
type,
145+
logs,
146+
exitCode: ExitCodes.NoOptions,
147+
};
112148
}
113149

114-
const ts = await import("typescript"),
115-
parsed = ts.parseJsonConfigFileContent(options, ts.sys, basePath);
150+
const ts = await import("typescript");
151+
let parsed = ts.parseJsonConfigFileContent(options, ts.sys, basePath);
152+
153+
if (parsed.errors.length && type === "cjs" && data) {
154+
const noInputsCode = 18003,
155+
hasNoInputsError = parsed.errors.some(diagnostic => diagnostic.code === noInputsCode);
156+
157+
if (hasNoInputsError) {
158+
options = getDefaultOptions(type);
159+
parsed = ts.parseJsonConfigFileContent(options, ts.sys, basePath);
160+
161+
if (!silent) {
162+
logs.push("Using default cjs build options because tsconfig.json has no input files for this build.");
163+
}
164+
}
165+
}
116166

117167
if (parsed.errors.length) {
118-
return ExitCodes.ParseError;
168+
for (const diagnostic of parsed.errors) {
169+
logs.push(ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"));
170+
}
171+
172+
return {
173+
type,
174+
logs,
175+
exitCode: ExitCodes.ParseError,
176+
};
119177
}
120178

121179
const program = ts.createProgram(parsed.fileNames, parsed.options),
@@ -133,21 +191,25 @@ async function compile(basePath: string, type: "browser" | "cjs" | "esm" | "type
133191
message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"),
134192
increment = 1;
135193

136-
console.log(
194+
logs.push(
137195
`${diagnostic.file.fileName} (${(line + increment).toString()},${(character + increment).toString()}): ${message}`,
138196
);
139197
} else {
140-
console.log(ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"));
198+
logs.push(ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"));
141199
}
142200
}
143201

144202
const exitCode = emitResult.emitSkipped || failed ? ExitCodes.EmitErrors : ExitCodes.OK;
145203

146204
if (!silent || exitCode) {
147-
console.log(`TSC for ${type} done with exit code: '${exitCode.toLocaleString()}'.`);
205+
logs.push(`TSC for ${type} done with exit code: '${exitCode.toLocaleString()}'.`);
148206
}
149207

150-
return exitCode;
208+
return {
209+
type,
210+
logs,
211+
exitCode,
212+
};
151213
}
152214

153215
/**
@@ -160,24 +222,28 @@ export async function buildTS(basePath: string, silent: boolean): Promise<boolea
160222
console.log("Building TS files");
161223
}
162224

163-
let res = true;
164-
165225
const types: ("browser" | "cjs" | "esm" | "types")[] = ["browser", "cjs", "esm", "types"];
166226

227+
const results = await Promise.all(types.map(type => compile(basePath, type, silent)));
228+
167229
for (const type of types) {
230+
const result = results.find(r => r.type === type);
231+
232+
if (!result) {
233+
continue;
234+
}
235+
168236
if (!silent) {
169237
console.log(`Building TS files for ${type} configuration`);
170238
}
171239

172-
const exitCode = await compile(basePath, type, silent);
173-
174-
if (exitCode) {
175-
res = false;
176-
177-
break;
240+
for (const log of result.logs) {
241+
console.log(log);
178242
}
179243
}
180244

245+
const res = results.every(result => result.exitCode === ExitCodes.OK);
246+
181247
if (!silent) {
182248
console.log("Building TS files done");
183249
}

0 commit comments

Comments
 (0)