Skip to content

Commit 2787dde

Browse files
authored
feat(dts): support dts.tsgo (#1205)
1 parent d4e13fe commit 2787dde

File tree

142 files changed

+3494
-125
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

142 files changed

+3494
-125
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ test-results
2727
.env.local
2828
.env.*.local
2929
.rslib/**/*
30+
!dist-path/

packages/core/src/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,6 +1500,7 @@ const composeDtsConfig = async (
15001500
banner: banner?.dts,
15011501
footer: footer?.dts,
15021502
redirect: redirect?.dts,
1503+
tsgo: dts?.tsgo,
15031504
}),
15041505
],
15051506
};

packages/core/src/types/config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ export type Dts =
9494
* @see {@link https://rslib.rs/config/lib/dts#dtsalias}
9595
*/
9696
alias?: Record<string, string>;
97+
/**
98+
* Whether to generate declaration files with `tsgo`.
99+
* @experimental
100+
* @defaultValue `false`
101+
* @see {@link https://rslib.rs/config/lib/dts#dtstsgo}
102+
*/
103+
tsgo?: boolean;
97104
}
98105
| boolean;
99106

packages/plugin-dts/README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ pluginDts({
136136
});
137137
```
138138

139+
> When [tsgo](#tsgo) is enabled, if the project also enables [build](#build) or emits declaration files with different extensions to the same directory, `dtsExtension` may not work correctly.
140+
139141
### alias
140142

141143
- **Type:** `Record<string, string>`
@@ -280,6 +282,41 @@ import { foo } from './foo.mjs'; // expected output of './dist/bar.d.mts'
280282

281283
- When set to `false`, the file extension will remain unchanged from the original import path in the rewritten import path of the output file (regardless of whether it is specified or specified as any value).
282284

285+
### tsgo
286+
287+
- **Type:** `boolean`
288+
- **Default:** `false`
289+
290+
Whether to generate declaration files with [tsgo](https://github.com/microsoft/typescript-go), which can provide faster generation of declaration files, especially for large projects.
291+
292+
> This feature is currently an **experimental feature**. Since tsgo is still in the **experimental stage**, there may be some bugs and unresolved issues or limitations. So, make sure to fully test it in your project before enabling this option.
293+
294+
To enable this option, you need to:
295+
296+
1. Install [@typescript/native-preview](https://www.npmjs.com/package/@typescript/native-preview) as a development dependency.
297+
298+
```bash
299+
npm add @typescript/native-preview -D
300+
```
301+
302+
> `@typescript/native-preview` requires Node.js 20.6.0 or higher.
303+
304+
2. Set `tsgo` to `true`.
305+
306+
```js
307+
pluginDts({
308+
tsgo: true,
309+
});
310+
```
311+
312+
3. In order to ensure the consistency of local development, you need to install the corresponding [VS Code Preview Extension](https://marketplace.visualstudio.com/items?itemName=TypeScriptTeam.native-preview) and add the following configuration in the VS Code settings:
313+
314+
```json
315+
{
316+
"typescript.experimental.useTsgo": true
317+
}
318+
```
319+
283320
## Contributing
284321

285322
Please read the [Contributing Guide](https://github.com/web-infra-dev/rslib/blob/main/CONTRIBUTING.md).

packages/plugin-dts/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,24 @@
4040
"@microsoft/api-extractor": "^7.52.11",
4141
"@rsbuild/core": "~1.5.3",
4242
"@rslib/tsconfig": "workspace:*",
43+
"@typescript/native-preview": "7.0.0-dev.20250904.1",
4344
"rsbuild-plugin-publint": "^0.3.3",
4445
"rslib": "npm:@rslib/[email protected]",
4546
"typescript": "^5.9.2"
4647
},
4748
"peerDependencies": {
4849
"@microsoft/api-extractor": "^7",
4950
"@rsbuild/core": "1.x",
51+
"@typescript/native-preview": "7.x",
5052
"typescript": "^5"
5153
},
5254
"peerDependenciesMeta": {
5355
"@microsoft/api-extractor": {
5456
"optional": true
5557
},
58+
"@typescript/native-preview": {
59+
"optional": true
60+
},
5661
"typescript": {
5762
"optional": true
5863
}

packages/plugin-dts/src/dts.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
import { logger } from '@rsbuild/core';
1212
import color from 'picocolors';
1313
import type { DtsEntry, DtsGenOptions } from './index';
14-
import { emitDts } from './tsc';
1514
import {
1615
calcLongestCommonPath,
1716
ensureTempDeclarationDir,
@@ -136,6 +135,7 @@ export async function generateDts(data: DtsGenOptions): Promise<void> {
136135
path: true,
137136
extension: false,
138137
},
138+
tsgo,
139139
} = data;
140140
if (!isWatch) {
141141
logger.start(`generating declaration files... ${color.dim(`(${name})`)}`);
@@ -248,7 +248,11 @@ export async function generateDts(data: DtsGenOptions): Promise<void> {
248248
}
249249
};
250250

251-
await emitDts(
251+
const emitDts = tsgo
252+
? await import('./tsgo').then((mod) => mod.emitDtsTsgo)
253+
: await import('./tsc').then((mod) => mod.emitDtsTsc);
254+
255+
const hasError = await emitDts(
252256
{
253257
name,
254258
cwd,
@@ -268,8 +272,14 @@ export async function generateDts(data: DtsGenOptions): Promise<void> {
268272
build,
269273
);
270274

271-
if (!isWatch) {
272-
await bundleDtsIfNeeded();
275+
if (tsgo) {
276+
if (!hasError) {
277+
await bundleDtsIfNeeded();
278+
}
279+
} else {
280+
if (!isWatch) {
281+
await bundleDtsIfNeeded();
282+
}
273283
}
274284
}
275285

packages/plugin-dts/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export type PluginDtsOptions = {
4444
banner?: string;
4545
footer?: string;
4646
redirect?: DtsRedirect;
47+
tsgo?: boolean;
4748
};
4849

4950
export type DtsEntry = {
@@ -93,14 +94,15 @@ export const pluginDts = (options: PluginDtsOptions = {}): RsbuildPlugin => ({
9394
options.redirect.path = options.redirect.path ?? true;
9495
options.redirect.extension = options.redirect.extension ?? false;
9596
options.alias = options.alias ?? {};
97+
options.tsgo = options.tsgo ?? false;
9698

9799
const dtsPromises: Promise<TaskResult>[] = [];
98100
let promisesResult: TaskResult[] = [];
99101
let childProcesses: ChildProcess[] = [];
100102

101103
api.onBeforeEnvironmentCompile(
102104
async ({ isWatch, isFirstCompile, environment }) => {
103-
if (!isFirstCompile) {
105+
if (!isFirstCompile && !options.tsgo) {
104106
return;
105107
}
106108

packages/plugin-dts/src/tsc.ts

Lines changed: 31 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import { logger } from '@rsbuild/core';
22
import color from 'picocolors';
33
import ts from 'typescript';
44
import type { DtsRedirect } from './index';
5-
import { getTimeCost, processDtsFiles } from './utils';
5+
import {
6+
getTimeCost,
7+
processDtsFiles,
8+
renameDtsFile,
9+
updateDeclarationMapContent,
10+
} from './utils';
611

712
const logPrefixTsc = color.dim('[tsc]');
813

@@ -75,7 +80,7 @@ async function handleDiagnosticsAndProcessFiles(
7580
}
7681
}
7782

78-
export async function emitDts(
83+
export async function emitDtsTsc(
7984
options: EmitDtsOptions,
8085
onComplete: (isSuccess: boolean) => void,
8186
bundle = false,
@@ -174,45 +179,17 @@ export async function emitDts(
174179
}
175180
};
176181

177-
const renameDtsFile = (fileName: string): string => {
178-
if (bundle) {
179-
return fileName;
180-
}
181-
182-
if (fileName.endsWith('.d.ts.map')) {
183-
return fileName.replace(/\.d\.ts\.map$/, `${dtsExtension}.map`);
184-
}
185-
186-
return fileName.replace(/\.d\.ts$/, dtsExtension);
187-
};
188-
189-
const updateDeclarationMapContent = (
190-
fileName: string,
191-
content: string,
192-
): string => {
193-
if (bundle || !compilerOptions.declarationMap) {
194-
return content;
195-
}
196-
197-
if (fileName.endsWith('.d.ts')) {
198-
return content.replace(
199-
/(\/\/# sourceMappingURL=.+)\.d\.ts\.map/g,
200-
`$1${dtsExtension}.map`,
201-
);
202-
}
203-
204-
if (fileName.endsWith('.d.ts.map')) {
205-
return content.replace(/("file":"[^"]*)\.d\.ts"/g, `$1${dtsExtension}"`);
206-
}
207-
208-
return content;
209-
};
210-
211182
const system: ts.System = {
212183
...ts.sys,
213184
writeFile: (fileName, contents, writeByteOrderMark) => {
214-
const newFileName = renameDtsFile(fileName);
215-
const newContents = updateDeclarationMapContent(fileName, contents);
185+
const newFileName = renameDtsFile(fileName, dtsExtension, bundle);
186+
const newContents = updateDeclarationMapContent(
187+
fileName,
188+
contents,
189+
dtsExtension,
190+
bundle,
191+
compilerOptions.declarationMap,
192+
);
216193
ts.sys.writeFile(newFileName, newContents, writeByteOrderMark);
217194
},
218195
};
@@ -232,8 +209,14 @@ export async function emitDts(
232209
onError,
233210
sourceFiles,
234211
) => {
235-
const newFileName = renameDtsFile(fileName);
236-
const newContents = updateDeclarationMapContent(fileName, contents);
212+
const newFileName = renameDtsFile(fileName, dtsExtension, bundle);
213+
const newContents = updateDeclarationMapContent(
214+
fileName,
215+
contents,
216+
dtsExtension,
217+
bundle,
218+
compilerOptions.declarationMap,
219+
);
237220
originHost.writeFile(
238221
newFileName,
239222
newContents,
@@ -285,8 +268,14 @@ export async function emitDts(
285268
onError,
286269
sourceFiles,
287270
) => {
288-
const newFileName = renameDtsFile(fileName);
289-
const newContents = updateDeclarationMapContent(fileName, contents);
271+
const newFileName = renameDtsFile(fileName, dtsExtension, bundle);
272+
const newContents = updateDeclarationMapContent(
273+
fileName,
274+
contents,
275+
dtsExtension,
276+
bundle,
277+
compilerOptions.declarationMap,
278+
);
290279
originHost.writeFile(
291280
newFileName,
292281
newContents,

0 commit comments

Comments
 (0)