From 16367c18bd486478800077ed91b61d1c9d7ee3af Mon Sep 17 00:00:00 2001 From: Timeless0911 <1604889533@qq.com> Date: Tue, 17 Jun 2025 19:03:44 +0800 Subject: [PATCH 1/2] refactor: remove circular dependency and add CircularDependencyRspackPlugin --- packages/core/rslib.config.ts | 7 +- packages/core/src/cli/restart.ts | 3 +- packages/core/src/config.ts | 5 +- packages/core/src/css/cssConfig.ts | 79 ++------------------ packages/core/src/css/libCssExtractLoader.ts | 2 +- packages/core/src/css/utils.ts | 72 +++++++++++++++++- packages/core/src/utils/color.ts | 2 + packages/core/src/utils/helper.ts | 4 +- packages/core/src/utils/logger.ts | 2 +- 9 files changed, 91 insertions(+), 85 deletions(-) create mode 100644 packages/core/src/utils/color.ts diff --git a/packages/core/rslib.config.ts b/packages/core/rslib.config.ts index c266d4af3..278e46405 100644 --- a/packages/core/rslib.config.ts +++ b/packages/core/rslib.config.ts @@ -2,7 +2,7 @@ import fs from 'node:fs'; import path from 'node:path'; import type { RsbuildPlugin } from '@rsbuild/core'; import { pluginPublint } from 'rsbuild-plugin-publint'; -import { defineConfig } from 'rslib'; +import { defineConfig, rspack } from 'rslib'; const pluginFixDtsTypes: RsbuildPlugin = { name: 'fix-dts-types', @@ -54,4 +54,9 @@ export default defineConfig({ rslog: '../compiled/rslog/index.js', }, }, + tools: { + rspack: { + plugins: [new rspack.CircularDependencyRspackPlugin({})], + }, + }, }); diff --git a/packages/core/src/cli/restart.ts b/packages/core/src/cli/restart.ts index e199c7806..a7a0f39f5 100644 --- a/packages/core/src/cli/restart.ts +++ b/packages/core/src/cli/restart.ts @@ -1,5 +1,6 @@ import path from 'node:path'; -import { color, debounce, isTTY } from '../utils/helper'; +import { color } from '../utils/color'; +import { debounce, isTTY } from '../utils/helper'; import { logger } from '../utils/logger'; export async function watchFilesForRestart( diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index 2c60c2991..d41542ca2 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -23,12 +23,11 @@ import { SWC_HELPERS, } from './constant'; import { - type CssLoaderOptionsAuto, RSLIB_CSS_ENTRY_FLAG, composeCssConfig, cssExternalHandler, - isCssGlobalFile, } from './css/cssConfig'; +import { type CssLoaderOptionsAuto, isCssGlobalFile } from './css/utils'; import { composeEntryChunkConfig } from './plugins/EntryChunkPlugin'; import { pluginCjsImportMetaUrlShim, @@ -58,11 +57,11 @@ import type { Shims, Syntax, } from './types'; +import { color } from './utils/color'; import { getDefaultExtension } from './utils/extension'; import { calcLongestCommonPath, checkMFPlugin, - color, getAbsolutePath, isEmptyObject, isIntermediateOutputFormat, diff --git a/packages/core/src/css/cssConfig.ts b/packages/core/src/css/cssConfig.ts index 82f93ec6d..f6ad10382 100644 --- a/packages/core/src/css/cssConfig.ts +++ b/packages/core/src/css/cssConfig.ts @@ -1,82 +1,15 @@ import { createRequire } from 'node:module'; -import path from 'node:path'; -import type { - CSSLoaderOptions, - EnvironmentConfig, - RsbuildPlugin, -} from '@rsbuild/core'; -import { CSS_EXTENSIONS_PATTERN } from '../constant'; +import type { EnvironmentConfig, RsbuildPlugin } from '@rsbuild/core'; import { LibCssExtractPlugin } from './LibCssExtractPlugin'; +import { + type CssLoaderOptionsAuto, + isCssFile, + isCssModulesFile, +} from './utils'; const require = createRequire(import.meta.url); export const RSLIB_CSS_ENTRY_FLAG = '__rslib_css__'; -// https://rsbuild.rs/config/output/css-modules#cssmodulesauto -export type CssLoaderOptionsAuto = CSSLoaderOptions['modules'] extends infer T - ? T extends { auto?: any } - ? T['auto'] - : never - : never; - -export function isCssFile(filepath: string): boolean { - return CSS_EXTENSIONS_PATTERN.test(filepath); -} - -const CSS_MODULE_REG = /\.module\.\w+$/i; - -/** - * This function is modified based on - * https://github.com/web-infra-dev/rspack/blob/7b80a45a1c58de7bc506dbb107fad6fda37d2a1f/packages/rspack/src/loader-runner/index.ts#L903 - */ -const PATH_QUERY_FRAGMENT_REGEXP = - /^((?:\u200b.|[^?#\u200b])*)(\?(?:\u200b.|[^#\u200b])*)?(#.*)?$/; -export function parsePathQueryFragment(str: string): { - path: string; - query: string; - fragment: string; -} { - const match = PATH_QUERY_FRAGMENT_REGEXP.exec(str); - return { - path: match?.[1]?.replace(/\u200b(.)/g, '$1') || '', - query: match?.[2] ? match[2].replace(/\u200b(.)/g, '$1') : '', - fragment: match?.[3] || '', - }; -} - -export function isCssModulesFile( - filepath: string, - auto: CssLoaderOptionsAuto, -): boolean { - const filename = path.basename(filepath); - if (auto === true) { - return CSS_MODULE_REG.test(filename); - } - - if (auto instanceof RegExp) { - return auto.test(filepath); - } - - if (typeof auto === 'function') { - const { path, query, fragment } = parsePathQueryFragment(filepath); - // this is a mock for loader - return auto(path, query, fragment); - } - - return false; -} - -export function isCssGlobalFile( - filepath: string, - auto: CssLoaderOptionsAuto, -): boolean { - const isCss = isCssFile(filepath); - if (!isCss) { - return false; - } - const isCssModules = isCssModulesFile(filepath, auto); - return !isCssModules; -} - type ExternalCallback = (arg0?: undefined, arg1?: string) => void; export async function cssExternalHandler( diff --git a/packages/core/src/css/libCssExtractLoader.ts b/packages/core/src/css/libCssExtractLoader.ts index fea899ff6..c8bc0e316 100644 --- a/packages/core/src/css/libCssExtractLoader.ts +++ b/packages/core/src/css/libCssExtractLoader.ts @@ -7,7 +7,7 @@ */ import path, { extname } from 'node:path'; import type { Rspack } from '@rsbuild/core'; -import { type CssLoaderOptionsAuto, isCssModulesFile } from './cssConfig'; +import { type CssLoaderOptionsAuto, isCssModulesFile } from './utils'; export const BASE_URI = 'webpack://'; export const MODULE_TYPE = 'css/mini-extract'; diff --git a/packages/core/src/css/utils.ts b/packages/core/src/css/utils.ts index 3fd765500..776f32975 100644 --- a/packages/core/src/css/utils.ts +++ b/packages/core/src/css/utils.ts @@ -1,9 +1,20 @@ +import path from 'node:path'; +import type { CSSLoaderOptions } from '@rsbuild/core'; +import { CSS_EXTENSIONS_PATTERN } from '../constant'; + +// https://rsbuild.rs/config/output/css-modules#cssmodulesauto +export type CssLoaderOptionsAuto = CSSLoaderOptions['modules'] extends infer T + ? T extends { auto?: any } + ? T['auto'] + : never + : never; + /** * This function is copied from * https://github.com/webpack-contrib/mini-css-extract-plugin/blob/3effaa0319bad5cc1bf0ae760553bf7abcbc35a4/src/utils.js#L169 * linted by biome */ -function getUndoPath( +export function getUndoPath( filename: string, outputPathArg: string, enforceRelative: boolean, @@ -42,4 +53,61 @@ function getUndoPath( : append; } -export { getUndoPath }; +export function isCssFile(filepath: string): boolean { + return CSS_EXTENSIONS_PATTERN.test(filepath); +} + +const CSS_MODULE_REG = /\.module\.\w+$/i; + +/** + * This function is modified based on + * https://github.com/web-infra-dev/rspack/blob/7b80a45a1c58de7bc506dbb107fad6fda37d2a1f/packages/rspack/src/loader-runner/index.ts#L903 + */ +const PATH_QUERY_FRAGMENT_REGEXP = + /^((?:\u200b.|[^?#\u200b])*)(\?(?:\u200b.|[^#\u200b])*)?(#.*)?$/; +export function parsePathQueryFragment(str: string): { + path: string; + query: string; + fragment: string; +} { + const match = PATH_QUERY_FRAGMENT_REGEXP.exec(str); + return { + path: match?.[1]?.replace(/\u200b(.)/g, '$1') || '', + query: match?.[2] ? match[2].replace(/\u200b(.)/g, '$1') : '', + fragment: match?.[3] || '', + }; +} + +export function isCssModulesFile( + filepath: string, + auto: CssLoaderOptionsAuto, +): boolean { + const filename = path.basename(filepath); + if (auto === true) { + return CSS_MODULE_REG.test(filename); + } + + if (auto instanceof RegExp) { + return auto.test(filepath); + } + + if (typeof auto === 'function') { + const { path, query, fragment } = parsePathQueryFragment(filepath); + // this is a mock for loader + return auto(path, query, fragment); + } + + return false; +} + +export function isCssGlobalFile( + filepath: string, + auto: CssLoaderOptionsAuto, +): boolean { + const isCss = isCssFile(filepath); + if (!isCss) { + return false; + } + const isCssModules = isCssModulesFile(filepath, auto); + return !isCssModules; +} diff --git a/packages/core/src/utils/color.ts b/packages/core/src/utils/color.ts new file mode 100644 index 000000000..ec4425d1d --- /dev/null +++ b/packages/core/src/utils/color.ts @@ -0,0 +1,2 @@ +import color from 'picocolors'; +export { color }; diff --git a/packages/core/src/utils/helper.ts b/packages/core/src/utils/helper.ts index f33809b57..472f15d3c 100644 --- a/packages/core/src/utils/helper.ts +++ b/packages/core/src/utils/helper.ts @@ -2,9 +2,9 @@ import fs from 'node:fs'; import fsP from 'node:fs/promises'; import path, { isAbsolute, join } from 'node:path'; import type { RsbuildPlugins } from '@rsbuild/core'; -import color from 'picocolors'; import type { Format, LibConfig, PkgJson } from '../types'; +import { color } from './color'; import { logger } from './logger'; /** @@ -242,8 +242,6 @@ export const isIntermediateOutputFormat = (format: Format): boolean => { return format === 'cjs' || format === 'esm'; }; -export { color }; - const windowsSlashRegex = /\\/g; export function normalizeSlash(p: string): string { return p.replace(windowsSlashRegex, '/'); diff --git a/packages/core/src/utils/logger.ts b/packages/core/src/utils/logger.ts index a4c820d05..479e0ccb8 100644 --- a/packages/core/src/utils/logger.ts +++ b/packages/core/src/utils/logger.ts @@ -13,7 +13,7 @@ * and important alerts that require attention. */ import { type Logger, logger } from 'rslog'; -import { color } from './helper'; +import { color } from './color'; export const isDebug = (): boolean => { if (!process.env.DEBUG) { From f7b979d44a5546080910bf2434cb5fa5738e4a4d Mon Sep 17 00:00:00 2001 From: Timeless0911 <1604889533@qq.com> Date: Tue, 17 Jun 2025 20:04:55 +0800 Subject: [PATCH 2/2] chore: update --- packages/core/src/css/LibCssExtractPlugin.ts | 2 +- packages/core/src/css/const.ts | 6 ++++++ packages/core/src/css/libCssExtractLoader.ts | 15 +++++++-------- 3 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 packages/core/src/css/const.ts diff --git a/packages/core/src/css/LibCssExtractPlugin.ts b/packages/core/src/css/LibCssExtractPlugin.ts index a22153f19..65a671c9b 100644 --- a/packages/core/src/css/LibCssExtractPlugin.ts +++ b/packages/core/src/css/LibCssExtractPlugin.ts @@ -4,7 +4,7 @@ import { AUTO_PUBLIC_PATH, BASE_URI, SINGLE_DOT_PATH_SEGMENT, -} from './libCssExtractLoader'; +} from './const'; import { getUndoPath } from './utils'; const pluginName = 'LIB_CSS_EXTRACT_PLUGIN'; diff --git a/packages/core/src/css/const.ts b/packages/core/src/css/const.ts new file mode 100644 index 000000000..7c6bc4c35 --- /dev/null +++ b/packages/core/src/css/const.ts @@ -0,0 +1,6 @@ +export const BASE_URI = 'webpack://'; +export const MODULE_TYPE = 'css/mini-extract'; +export const AUTO_PUBLIC_PATH = '__mini_css_extract_plugin_public_path_auto__'; +export const ABSOLUTE_PUBLIC_PATH: string = `${BASE_URI}/mini-css-extract-plugin/`; +export const SINGLE_DOT_PATH_SEGMENT = + '__mini_css_extract_plugin_single_dot_path_segment__'; diff --git a/packages/core/src/css/libCssExtractLoader.ts b/packages/core/src/css/libCssExtractLoader.ts index c8bc0e316..2f542a206 100644 --- a/packages/core/src/css/libCssExtractLoader.ts +++ b/packages/core/src/css/libCssExtractLoader.ts @@ -7,15 +7,14 @@ */ import path, { extname } from 'node:path'; import type { Rspack } from '@rsbuild/core'; -import { type CssLoaderOptionsAuto, isCssModulesFile } from './utils'; - -export const BASE_URI = 'webpack://'; -export const MODULE_TYPE = 'css/mini-extract'; -export const AUTO_PUBLIC_PATH = '__mini_css_extract_plugin_public_path_auto__'; -export const ABSOLUTE_PUBLIC_PATH: string = `${BASE_URI}/mini-css-extract-plugin/`; -export const SINGLE_DOT_PATH_SEGMENT = - '__mini_css_extract_plugin_single_dot_path_segment__'; +import { + ABSOLUTE_PUBLIC_PATH, + AUTO_PUBLIC_PATH, + BASE_URI, + SINGLE_DOT_PATH_SEGMENT, +} from './const'; +import { type CssLoaderOptionsAuto, isCssModulesFile } from './utils'; interface DependencyDescription { identifier: string; content: string;