diff --git a/packages/core/package.json b/packages/core/package.json index 155b6e0e6..c96c11685 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -51,6 +51,7 @@ "prebundle": "1.2.2", "rslib": "npm:@rslib/core@0.0.5", "rslog": "^1.2.3", + "tsconfck": "3.1.3", "typescript": "^5.5.4" }, "peerDependencies": { diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index 0151b0c35..1091768a4 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -10,7 +10,6 @@ import { rspack, } from '@rsbuild/core'; import glob from 'fast-glob'; -import ts from 'typescript'; import { DEFAULT_CONFIG_NAME, DEFAULT_EXTENSIONS, @@ -41,7 +40,7 @@ import { } from './utils/helper'; import { logger } from './utils/logger'; import { transformSyntaxToBrowserslist } from './utils/syntax'; -import { getTsconfigCompilerOptions } from './utils/tsconfig'; +import { loadTsconfig } from './utils/tsconfig'; /** * This function helps you to autocomplete configuration types. @@ -363,12 +362,12 @@ export function composeBannerFooterConfig( } export function composeDecoratorsConfig( - options: ts.CompilerOptions, + compilerOptions?: Record, version?: NonNullable< NonNullable['decorators'] >['version'], ): RsbuildConfig { - if (version || !options.experimentalDecorators) { + if (version || !compilerOptions?.experimentalDecorators) { return {}; } @@ -811,15 +810,10 @@ const composeExternalHelpersConfig = ( async function composeLibRsbuildConfig(config: LibConfig, configPath: string) { const rootPath = dirname(configPath); const pkgJson = readPackageJson(rootPath); - let compilerOptions: ts.CompilerOptions = {}; - const tsconfigPath = ts.findConfigFile( + const { compilerOptions } = await loadTsconfig( rootPath, - ts.sys.fileExists, config.source?.tsconfigPath, ); - if (tsconfigPath) { - compilerOptions = getTsconfigCompilerOptions(tsconfigPath); - } const { format, diff --git a/packages/core/src/utils/tsconfig.ts b/packages/core/src/utils/tsconfig.ts index 96bdc199b..552a12391 100644 --- a/packages/core/src/utils/tsconfig.ts +++ b/packages/core/src/utils/tsconfig.ts @@ -1,21 +1,21 @@ -import path from 'node:path'; -import ts from 'typescript'; +import { basename, join } from 'node:path'; +import { find, parse } from 'tsconfck'; -export function loadTsconfig(tsconfigPath: string): ts.ParsedCommandLine { - const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile); - const configFileContent = ts.parseJsonConfigFileContent( - configFile.config, - ts.sys, - path.dirname(tsconfigPath), - ); +export async function loadTsconfig( + root: string, + tsconfigPath = 'tsconfig.json', +): Promise<{ + compilerOptions?: Record; +}> { + const tsconfigFileName = await find(join(root, tsconfigPath), { + root, + configName: basename(tsconfigPath), + }); - return configFileContent; -} - -export function getTsconfigCompilerOptions( - tsconfigPath: string, -): ts.CompilerOptions { - const { options } = loadTsconfig(tsconfigPath); + if (tsconfigFileName) { + const { tsconfig } = await parse(tsconfigFileName); + return tsconfig; + } - return options; + return {}; } diff --git a/packages/core/tests/extension.test.ts b/packages/core/tests/extension.test.ts index 7e5b05f39..dcad0ce77 100644 --- a/packages/core/tests/extension.test.ts +++ b/packages/core/tests/extension.test.ts @@ -1,11 +1,18 @@ import { describe, expect, it, vi } from 'vitest'; +import type { Format, PkgJson } from '../src/types'; import { getDefaultExtension } from '../src/utils/extension'; +type Options = { + format: Format; + pkgJson?: PkgJson; + autoExtension: boolean; +}; + vi.mock('rslog'); describe('should get extension correctly', () => { it('autoExtension is false', () => { - const options = { + const options: Options = { format: 'cjs', pkgJson: {}, autoExtension: false, @@ -20,7 +27,7 @@ describe('should get extension correctly', () => { }); it('package.json is broken', () => { - const options = { + const options: Options = { format: 'cjs', autoExtension: true, }; @@ -34,7 +41,7 @@ describe('should get extension correctly', () => { }); it('format is cjs and type is module in package.json', () => { - const options = { + const options: Options = { format: 'cjs', pkgJson: { type: 'module', @@ -52,7 +59,7 @@ describe('should get extension correctly', () => { }); it('format is cjs and type is commonjs in package.json', () => { - const options = { + const options: Options = { format: 'cjs', pkgJson: { type: 'commonjs', @@ -70,7 +77,7 @@ describe('should get extension correctly', () => { }); it('format is esm and type is commonjs in package.json', () => { - const options = { + const options: Options = { format: 'esm', pkgJson: { type: 'commonjs', @@ -88,7 +95,7 @@ describe('should get extension correctly', () => { }); it('format is esm and type is module in package.json', () => { - const options = { + const options: Options = { format: 'esm', pkgJson: { type: 'module', diff --git a/packages/core/tests/fixtures/tsconfig/exist/tsconfig.custom.json b/packages/core/tests/fixtures/tsconfig/exist/tsconfig.custom.json new file mode 100644 index 000000000..34d0787d0 --- /dev/null +++ b/packages/core/tests/fixtures/tsconfig/exist/tsconfig.custom.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "rootDir": "custom" + } +} diff --git a/packages/core/tests/fixtures/tsconfig/exist/tsconfig.json b/packages/core/tests/fixtures/tsconfig/exist/tsconfig.json new file mode 100644 index 000000000..397165af4 --- /dev/null +++ b/packages/core/tests/fixtures/tsconfig/exist/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "rootDir": "./" + } +} diff --git a/packages/core/tests/fixtures/tsconfig/no-exist/index.js b/packages/core/tests/fixtures/tsconfig/no-exist/index.js new file mode 100644 index 000000000..3329a7d97 --- /dev/null +++ b/packages/core/tests/fixtures/tsconfig/no-exist/index.js @@ -0,0 +1 @@ +export const foo = 'foo'; diff --git a/packages/core/tests/tsconfig.test.ts b/packages/core/tests/tsconfig.test.ts new file mode 100644 index 000000000..ccea7091e --- /dev/null +++ b/packages/core/tests/tsconfig.test.ts @@ -0,0 +1,33 @@ +import { join } from 'node:path'; +import { describe, expect, it } from 'vitest'; +import { loadTsconfig } from '../src/utils/tsconfig'; + +describe('loadTsconfig', () => { + it('should return tsconfig when a valid tsconfig file is found', async () => { + const fixtureDir = join(__dirname, 'fixtures/tsconfig/exist'); + const result1 = await loadTsconfig(fixtureDir); + const result2 = await loadTsconfig(fixtureDir, './tsconfig.custom.json'); + + expect(result1).toMatchInlineSnapshot(` + { + "compilerOptions": { + "rootDir": "./", + }, + } + `); + expect(result2).toMatchInlineSnapshot(` + { + "compilerOptions": { + "rootDir": "custom", + }, + } + `); + }); + + it('should return an empty object when no tsconfig file is found', async () => { + const fixtureDir = join(__dirname, 'fixtures/tsconfig/no-exist'); + const result = await loadTsconfig(fixtureDir); + + expect(result).toEqual({}); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 73ed5a35e..8a2488440 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -341,6 +341,9 @@ importers: rslog: specifier: ^1.2.3 version: 1.2.3 + tsconfck: + specifier: 3.1.3 + version: 3.1.3(typescript@5.5.4) typescript: specifier: ^5.5.4 version: 5.5.4 @@ -3902,6 +3905,16 @@ packages: trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + tsconfck@3.1.3: + resolution: {integrity: sha512-ulNZP1SVpRDesxeMLON/LtWM8HIgAJEIVpVVhBM6gsmvQ8+Rh+ZG7FWGvHh7Ah3pRABwVJWklWCr/BTZSv0xnQ==} + engines: {node: ^18 || >=20} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + tsconfig-paths@4.2.0: resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} engines: {node: '>=6'} @@ -8159,6 +8172,10 @@ snapshots: trough@2.2.0: {} + tsconfck@3.1.3(typescript@5.5.4): + optionalDependencies: + typescript: 5.5.4 + tsconfig-paths@4.2.0: dependencies: json5: 2.2.3 diff --git a/scripts/dictionary.txt b/scripts/dictionary.txt index fac4da9ea..e7c7b2384 100644 --- a/scripts/dictionary.txt +++ b/scripts/dictionary.txt @@ -118,6 +118,7 @@ templating transpiling treeshaking tsbuildinfo +tsconfck tsdoc tsup unocss