diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml index 9f5e891e27..2878033af4 100644 --- a/.github/workflows/release-nightly.yml +++ b/.github/workflows/release-nightly.yml @@ -2,11 +2,13 @@ name: Release Nightly on: workflow_dispatch: + # Nightly release disabled # schedule: # 00:00 AM Beijing Time. # - cron: "0 16 * * *" permissions: + # To publish packages with provenance id-token: write jobs: diff --git a/e2e/cases/type-check/multiple-tsconfig/index.test.ts b/e2e/cases/type-check/multiple-tsconfig/index.test.ts new file mode 100644 index 0000000000..b296a0559e --- /dev/null +++ b/e2e/cases/type-check/multiple-tsconfig/index.test.ts @@ -0,0 +1,30 @@ +import { build } from '@e2e/helper'; +import { proxyConsole } from '@e2e/helper'; +import { expect, test } from '@playwright/test'; + +test('should check multiple tsconfig.json as expected', async () => { + const { logs, restore } = proxyConsole(); + await expect( + build({ + cwd: __dirname, + }), + ).rejects.toThrowError('build failed!'); + + expect( + logs.find((log) => + log.includes( + `Argument of type 'string' is not assignable to parameter of type 'number'.`, + ), + ), + ).toBeTruthy(); + + expect( + logs.find((log) => + log.includes( + `Argument of type '{}' is not assignable to parameter of type 'number'.`, + ), + ), + ).toBeTruthy(); + + restore(); +}); diff --git a/e2e/cases/type-check/multiple-tsconfig/rsbuild.config.ts b/e2e/cases/type-check/multiple-tsconfig/rsbuild.config.ts new file mode 100644 index 0000000000..67cd46a1f6 --- /dev/null +++ b/e2e/cases/type-check/multiple-tsconfig/rsbuild.config.ts @@ -0,0 +1,21 @@ +import { defineConfig } from '@rsbuild/core'; +import { pluginTypeCheck } from '@rsbuild/plugin-type-check'; + +export default defineConfig({ + plugins: [pluginTypeCheck()], + environments: { + web: { + output: { + target: 'web', + }, + }, + node: { + source: { + tsconfigPath: './tsconfig.server.json', + }, + output: { + target: 'node', + }, + }, + }, +}); diff --git a/e2e/cases/type-check/multiple-tsconfig/server/index.ts b/e2e/cases/type-check/multiple-tsconfig/server/index.ts new file mode 100644 index 0000000000..84f0b908be --- /dev/null +++ b/e2e/cases/type-check/multiple-tsconfig/server/index.ts @@ -0,0 +1,4 @@ +const add = (a: number, b: number) => a + b; + +// this is a type error +add(1, '2'); diff --git a/e2e/cases/type-check/multiple-tsconfig/src/index.ts b/e2e/cases/type-check/multiple-tsconfig/src/index.ts new file mode 100644 index 0000000000..5921c99234 --- /dev/null +++ b/e2e/cases/type-check/multiple-tsconfig/src/index.ts @@ -0,0 +1,4 @@ +const add = (a: number, b: number) => a + b; + +// this is a type error +add(1, {}); diff --git a/e2e/cases/type-check/multiple-tsconfig/tsconfig.json b/e2e/cases/type-check/multiple-tsconfig/tsconfig.json new file mode 100644 index 0000000000..b380d07d73 --- /dev/null +++ b/e2e/cases/type-check/multiple-tsconfig/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "@rsbuild/config/tsconfig", + "compilerOptions": { + "jsx": "react-jsx", + "baseUrl": "./", + "outDir": "./dist", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src"] +} diff --git a/e2e/cases/type-check/multiple-tsconfig/tsconfig.server.json b/e2e/cases/type-check/multiple-tsconfig/tsconfig.server.json new file mode 100644 index 0000000000..b5cba17a2b --- /dev/null +++ b/e2e/cases/type-check/multiple-tsconfig/tsconfig.server.json @@ -0,0 +1,12 @@ +{ + "extends": "@rsbuild/config/tsconfig", + "compilerOptions": { + "jsx": "react-jsx", + "baseUrl": "./", + "outDir": "./dist", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["server"] +} diff --git a/packages/plugin-type-check/src/index.ts b/packages/plugin-type-check/src/index.ts index c0f8de8aa0..3852e629be 100644 --- a/packages/plugin-type-check/src/index.ts +++ b/packages/plugin-type-check/src/index.ts @@ -34,6 +34,13 @@ export const pluginTypeCheck = ( name: PLUGIN_TYPE_CHECK_NAME, setup(api) { + const checkedTsconfig = new Map< + // tsconfig path + string, + // environment + string + >(); + api.modifyBundlerChain(async (chain, { isProd, environment }) => { const { enable = true, forkTsCheckerOptions } = options; const { tsconfigPath } = api.context.environments[environment]; @@ -42,11 +49,15 @@ export const pluginTypeCheck = ( return; } - // If there is multiple environment, only apply type checker to the first target - // to avoid multiple type checker running at the same time - if (environment !== Object.keys(api.context.environments)[0]) { + // If there are identical tsconfig.json files, + // apply type checker only once to avoid duplicate checks. + if ( + checkedTsconfig.has(tsconfigPath) && + checkedTsconfig.get(tsconfigPath) !== environment + ) { return; } + checkedTsconfig.set(tsconfigPath, environment); // use typescript of user project let typescriptPath: string;