Skip to content

Commit 9c9e2aa

Browse files
authored
feat: support tsc --build to enable incremental build for project references (#337)
1 parent 01d0706 commit 9c9e2aa

File tree

35 files changed

+577
-110
lines changed

35 files changed

+577
-110
lines changed

packages/core/src/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,7 @@ const composeDtsConfig = async (
930930
// Only setting ⁠dts.bundle to true will generate the bundled d.ts.
931931
bundle: dts?.bundle ?? false,
932932
distPath: dts?.distPath ?? output?.distPath?.root ?? './dist',
933+
build: dts?.build ?? false,
933934
abortOnError: dts?.abortOnError ?? true,
934935
dtsExtension: dts?.autoExtension ? dtsExtension : '.d.ts',
935936
autoExternal,

packages/core/src/types/config/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ export type Syntax =
2929
| string[];
3030

3131
export type Dts =
32-
| (Pick<PluginDtsOptions, 'bundle' | 'distPath' | 'abortOnError'> & {
32+
| (Pick<
33+
PluginDtsOptions,
34+
'bundle' | 'distPath' | 'abortOnError' | 'build'
35+
> & {
3336
autoExtension?: boolean;
3437
})
3538
| boolean;

packages/plugin-dts/src/dts.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import fs from 'node:fs';
2-
import { basename, dirname, isAbsolute, join, relative } from 'node:path';
2+
import {
3+
basename,
4+
dirname,
5+
isAbsolute,
6+
join,
7+
normalize,
8+
relative,
9+
resolve,
10+
} from 'node:path';
311
import { logger } from '@rsbuild/core';
412
import color from 'picocolors';
513
import ts from 'typescript';
@@ -110,6 +118,7 @@ export async function generateDts(data: DtsGenOptions): Promise<void> {
110118
tsconfigPath,
111119
name,
112120
cwd,
121+
build,
113122
isWatch,
114123
dtsExtension = '.d.ts',
115124
autoExternal = true,
@@ -133,6 +142,33 @@ export async function generateDts(data: DtsGenOptions): Promise<void> {
133142
? distPath
134143
: rawCompilerOptions.declarationDir || './dist';
135144

145+
if (build) {
146+
// do not allow to use bundle DTS when 'build: true' since temp declarationDir should be set by user in tsconfig
147+
if (bundle) {
148+
throw Error(`Can not set "dts.bundle: true" when "dts.build: true"`);
149+
}
150+
151+
// can not set '--declarationDir' or '--outDir' when 'build: true'.
152+
if (
153+
(!rawCompilerOptions.outDir ||
154+
normalize(rawCompilerOptions.outDir) !==
155+
normalize(resolve(dirname(configPath), outDir))) &&
156+
(!rawCompilerOptions.declarationDir ||
157+
normalize(rawCompilerOptions.declarationDir) !==
158+
normalize(resolve(dirname(configPath), outDir)))
159+
) {
160+
const info =
161+
rawCompilerOptions.outDir && !rawCompilerOptions.declarationDir
162+
? 'outDir'
163+
: 'declarationDir';
164+
throw Error(
165+
`Please set ${info}: "${outDir}" in ${color.underline(
166+
configPath,
167+
)} to keep it same as "dts.distPath" or "output.distPath" field in lib config.`,
168+
);
169+
}
170+
}
171+
136172
const getDeclarationDir = (bundle: boolean, distPath?: string) => {
137173
if (bundle) {
138174
return ensureTempDeclarationDir(cwd);
@@ -204,6 +240,7 @@ export async function generateDts(data: DtsGenOptions): Promise<void> {
204240
onComplete,
205241
bundle,
206242
isWatch,
243+
build,
207244
);
208245

209246
if (!isWatch) {

packages/plugin-dts/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const __dirname = dirname(__filename);
1010
export type PluginDtsOptions = {
1111
bundle?: boolean;
1212
distPath?: string;
13+
build?: boolean;
1314
abortOnError?: boolean;
1415
dtsExtension?: string;
1516
autoExternal?:
@@ -33,6 +34,7 @@ export type DtsGenOptions = PluginDtsOptions & {
3334
cwd: string;
3435
isWatch: boolean;
3536
dtsEntry: DtsEntry;
37+
build?: boolean;
3638
tsconfigPath?: string;
3739
userExternals?: NonNullable<RsbuildConfig['output']>['externals'];
3840
};
@@ -46,14 +48,14 @@ export const PLUGIN_DTS_NAME = 'rsbuild:dts';
4648

4749
// use ts compiler API to generate bundleless dts
4850
// use ts compiler API and api-extractor to generate dts bundle
49-
// TODO: support incremental build, to build one or more projects and their dependencies
5051
// TODO: deal alias in dts
5152
export const pluginDts = (options: PluginDtsOptions): RsbuildPlugin => ({
5253
name: PLUGIN_DTS_NAME,
5354

5455
setup(api) {
5556
options.bundle = options.bundle ?? false;
5657
options.abortOnError = options.abortOnError ?? true;
58+
options.build = options.build ?? false;
5759

5860
const dtsPromises: Promise<TaskResult>[] = [];
5961
let promisesResult: TaskResult[] = [];

0 commit comments

Comments
 (0)