Skip to content

Commit

Permalink
feat: check consistency of JSX between swc and tsconfig
Browse files Browse the repository at this point in the history
  • Loading branch information
fi3ework committed Jan 14, 2025
1 parent 860dba6 commit d9efcf7
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 12 deletions.
51 changes: 51 additions & 0 deletions packages/core/src/check.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type { RsbuildConfig, RsbuildPlugin } from '@rsbuild/core';
import { color } from './utils/helper';
import { logger } from './utils/logger';

type PluginReactOptions = {
compilerOptions?: Record<string, any>;
};

const mapTsconfigJsxToSwcJsx = (swcJsx: string): string | null => {
switch (swcJsx) {
case 'react-jsx':
case 'react-jsxdev':
return 'automatic';
case 'react':
return 'classic';
default:
return 'classic';
}
};

const checkJsx = ({ compilerOptions }: PluginReactOptions): RsbuildPlugin => ({
name: 'rsbuild:lib-check',
setup(api) {
api.onBeforeEnvironmentCompile(({ environment }) => {
const envName = environment.name;
const config = api.getNormalizedConfig({
environment: envName,
});

const swc = config.tools.swc;
const tsconfigJsx = compilerOptions?.jsx;
// @ts-ignore
const swcJsx = swc.jsc.transform.react.runtime;
const mapped = mapTsconfigJsxToSwcJsx(tsconfigJsx);
if (swcJsx && mapped !== null) {
const matched = mapped === swcJsx;
if (!matched) {
logger.warn(
`You're using ${color.green(`"${swcJsx}"`)} JSX runtime in SWC, but ${color.green(`"${mapped}"`)} in tsconfig.json. This may cause unexpected behavior, considering aligning them.`,
);
}
}
});
},
});

export const composeCheckConfig = (
compilerOptions: Record<string, any>,
): RsbuildConfig => {
return { plugins: [checkJsx({ compilerOptions })] };
};
4 changes: 4 additions & 0 deletions packages/core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from '@rsbuild/core';
import { glob } from 'tinyglobby';
import { composeAssetConfig } from './asset/assetConfig';
import { composeCheckConfig } from './check';
import {
DEFAULT_CONFIG_EXTENSIONS,
DEFAULT_CONFIG_NAME,
Expand Down Expand Up @@ -1327,6 +1328,8 @@ async function composeLibRsbuildConfig(
rootPath,
config.source?.tsconfigPath,
);

const checkConfig = composeCheckConfig({ compilerOptions });
const cssModulesAuto = config.output?.cssModules?.auto ?? true;

const {
Expand Down Expand Up @@ -1438,6 +1441,7 @@ async function composeLibRsbuildConfig(
dtsConfig,
bannerFooterConfig,
decoratorsConfig,
checkConfig,
);
}

Expand Down
35 changes: 23 additions & 12 deletions packages/core/src/utils/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,21 +167,23 @@ export function omit<T extends object, U extends keyof T>(
);
}

export function isPluginIncluded(
function findPlugin(pluginName: string, plugins?: RsbuildPlugins) {
return plugins?.find((plugin) => {
if (Array.isArray(plugin)) {
return isPluginIncluded(pluginName, plugin);
}
if (typeof plugin === 'object' && plugin !== null && 'name' in plugin) {
return plugin.name === pluginName;
}
return false;
});
}

function isPluginIncluded(
pluginName: string,
plugins?: RsbuildPlugins,
): boolean {
return Boolean(
plugins?.some((plugin) => {
if (Array.isArray(plugin)) {
return isPluginIncluded(pluginName, plugin);
}
if (typeof plugin === 'object' && plugin !== null && 'name' in plugin) {
return plugin.name === pluginName;
}
return false;
}),
);
return Boolean(findPlugin(pluginName, plugins));
}

export function checkMFPlugin(
Expand Down Expand Up @@ -209,6 +211,15 @@ export function checkMFPlugin(
return added;
}

export function checkJsxOption(
config: LibConfig,
sharedPlugins?: RsbuildPlugins,
): boolean {
// console.log('🤬', config);
return true;
// return reactPlugin;
}

export function debounce<T extends (...args: any[]) => void>(
func: T,
wait: number,
Expand Down
12 changes: 12 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions tests/integration/check/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { join } from 'node:path';
import stripAnsi from 'strip-ansi';
import { buildAndGetResults, proxyConsole } from 'test-helper';
import { expect, test } from 'vitest';

test('should receive JSX mismatch warning of SWC with tsconfig', async () => {
const { logs, restore } = proxyConsole();
const fixturePath = join(__dirname, 'jsx');
await buildAndGetResults({ fixturePath });
const logStrings = logs
.map((log) => stripAnsi(log))
.filter((log) => log.startsWith('warn'))
.sort()
.join('\n');

expect(logStrings).toMatchInlineSnapshot(`
"warn You're using "automatic" JSX runtime in SWC, but "classic" in tsconfig.json. This may cause unexpected behavior, considering aligning them.
warn You're using "automatic" JSX runtime in SWC, but "classic" in tsconfig.json. This may cause unexpected behavior, considering aligning them."
`);

restore();
});
11 changes: 11 additions & 0 deletions tests/integration/check/jsx/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "check-jsx-test",
"version": "1.0.0",
"private": true,
"type": "module",
"devDependencies": {
"@rsbuild/plugin-react": "^1.1.0",
"@types/react": "^19.0.6",
"react": "^19.0.0"
}
}
8 changes: 8 additions & 0 deletions tests/integration/check/jsx/rslib.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { pluginReact } from '@rsbuild/plugin-react';
import { defineConfig } from '@rslib/core';
import { generateBundleCjsConfig, generateBundleEsmConfig } from 'test-helper';

export default defineConfig({
lib: [generateBundleEsmConfig(), generateBundleCjsConfig()],
plugins: [pluginReact()],
});
3 changes: 3 additions & 0 deletions tests/integration/check/jsx/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import React from 'react';

export const Foo = <div>foo</div>;
8 changes: 8 additions & 0 deletions tests/integration/check/jsx/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "@rslib/tsconfig/base",
"compilerOptions": {
"baseUrl": "./",
"jsx": "react"
},
"include": ["src"]
}

0 comments on commit d9efcf7

Please sign in to comment.