@rsbuild/core 2.1.2 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/756.js CHANGED
@@ -3500,7 +3500,7 @@ function createPublicContext(context) {
3500
3500
  async function createContext(options, userConfig, logger) {
3501
3501
  let { cwd } = options, rootPath = userConfig.root ? ensureAbsolutePath(cwd, userConfig.root) : cwd, rsbuildConfig = await withDefaultConfig(rootPath, userConfig), cachePath = join(rootPath, 'node_modules', '.cache'), specifiedEnvironments = options.environment && options.environment.length > 0 ? options.environment : void 0;
3502
3502
  return {
3503
- version: "2.1.2",
3503
+ version: "2.1.3",
3504
3504
  rootPath,
3505
3505
  distPath: '',
3506
3506
  cachePath,
@@ -3778,12 +3778,15 @@ let configChain_CHAIN_ID = {
3778
3778
  JS_MAIN: 'js',
3779
3779
  JS_WORKER: 'js-worker',
3780
3780
  JS_RAW: 'js-raw',
3781
+ JS_TEXT: 'js-text',
3781
3782
  CSS_MAIN: 'css',
3782
3783
  CSS_RAW: 'css-raw',
3784
+ CSS_TEXT: 'css-text',
3783
3785
  CSS_URL: 'css-url',
3784
3786
  CSS_INLINE: 'css-inline',
3785
3787
  SVG: 'svg',
3786
3788
  SVG_RAW: 'svg-asset-raw',
3789
+ SVG_TEXT: 'svg-asset-text',
3787
3790
  SVG_URL: 'svg-asset-url',
3788
3791
  SVG_ASSET: 'svg-asset',
3789
3792
  SVG_REACT: 'svg-react',
@@ -4817,7 +4820,9 @@ let chainStaticAssetRule = ({ emit, rule, maxSize, filename, assetType })=>{
4817
4820
  let generatorOptions = {
4818
4821
  filename
4819
4822
  };
4820
- emit || (generatorOptions.emit = !1), rule.oneOf(`${assetType}-asset-url`).type('asset/resource').resourceQuery(URL_QUERY_REGEX).set('generator', generatorOptions), rule.oneOf(`${assetType}-asset-inline`).type('asset/inline').resourceQuery(INLINE_QUERY_REGEX), rule.oneOf(`${assetType}-asset-raw`).type('asset/source').resourceQuery(RAW_QUERY_REGEX), rule.oneOf(`${assetType}-asset`).type('asset').parser({
4823
+ emit || (generatorOptions.emit = !1), rule.oneOf(`${assetType}-asset-url`).type('asset/resource').resourceQuery(URL_QUERY_REGEX).set('generator', generatorOptions), rule.oneOf(`${assetType}-asset-inline`).type('asset/inline').resourceQuery(INLINE_QUERY_REGEX), rule.oneOf(`${assetType}-asset-text`).type('asset/source').with({
4824
+ type: 'text'
4825
+ }), rule.oneOf(`${assetType}-asset-raw`).type('asset/source').resourceQuery(RAW_QUERY_REGEX), rule.oneOf(`${assetType}-asset`).type('asset').parser({
4821
4826
  dataUrlCondition: {
4822
4827
  maxSize
4823
4828
  }
@@ -5150,7 +5155,7 @@ async function saveSnapshots(snapshotPath, snapshots, logger) {
5150
5155
  logger.debug('Failed to save file size snapshots:', err);
5151
5156
  }
5152
5157
  }
5153
- let EXCLUDE_ASSET_REGEX = /\.(?:map|LICENSE\.txt|d\.ts)$/, isSignificantDiff = (diff)=>Math.abs(diff) >= 10, formatDiff = (diff)=>{
5158
+ let EXCLUDE_ASSET_REGEX = /\.(?:map|LICENSE\.txt|d\.(?:ts|mts|cts))$/, isSignificantDiff = (diff)=>Math.abs(diff) >= 10, formatDiff = (diff)=>{
5154
5159
  let label = `(${diff > 0 ? '+' : '-'}${calcFileSize(Math.abs(diff))})`;
5155
5160
  return {
5156
5161
  label: (diff > 0 ? color.red : color.green)(label),
@@ -5175,7 +5180,7 @@ function getHeader(maxFileLength, maxSizeLength, fileHeader, showGzipHeader) {
5175
5180
  let calcFileSize = (len)=>{
5176
5181
  let val = len / 1000;
5177
5182
  return `${val.toFixed(val < 1 ? 2 : 1)} kB`;
5178
- }, COMPRESSIBLE_REGEX = /\.(?:js|css|html|json|svg|txt|xml|xhtml|wasm|manifest|md)$/i, isCompressible = (assetName)=>COMPRESSIBLE_REGEX.test(assetName), getFilePath = (assetName)=>{
5183
+ }, COMPRESSIBLE_REGEX = /\.(?:js|mjs|cjs|jsx|ts|tsx|mts|cts|css|html|json|svg|txt|xml|xhtml|wasm|manifest|md)$/i, isCompressible = (assetName)=>COMPRESSIBLE_REGEX.test(assetName), getFilePath = (assetName)=>{
5179
5184
  let queryIndex = assetName.indexOf('?');
5180
5185
  return -1 === queryIndex ? assetName : assetName.slice(0, queryIndex);
5181
5186
  };
@@ -5823,7 +5828,8 @@ let supportedChromiumBrowsers = [
5823
5828
  'Microsoft Edge',
5824
5829
  'Brave Browser',
5825
5830
  'Vivaldi',
5826
- 'Chromium'
5831
+ 'Chromium',
5832
+ 'Helium'
5827
5833
  ], mapChromiumBrowserName = (browser)=>'chrome' === browser || 'google chrome' === browser ? 'Google Chrome' : browser;
5828
5834
  async function openBrowser(url, logger) {
5829
5835
  let browser = process.env.BROWSER, browserArgs = process.env.BROWSER_ARGS;
@@ -8736,7 +8742,11 @@ function applyDefaultPlugins(pluginManager, context) {
8736
8742
  ], emitAssets), createAssetRule(configChain_CHAIN_ID.RULE.MEDIA, [
8737
8743
  ...VIDEO_EXTENSIONS,
8738
8744
  ...AUDIO_EXTENSIONS
8739
- ], emitAssets), createAssetRule(configChain_CHAIN_ID.RULE.FONT, FONT_EXTENSIONS, emitAssets), chain.module.rule(configChain_CHAIN_ID.RULE.JSON).test(/\.json$/i).oneOf('json-asset-raw').type('asset/source').resourceQuery(RAW_QUERY_REGEX);
8745
+ ], emitAssets), createAssetRule(configChain_CHAIN_ID.RULE.FONT, FONT_EXTENSIONS, emitAssets);
8746
+ let rule = chain.module.rule(configChain_CHAIN_ID.RULE.JSON).test(/\.json$/i);
8747
+ rule.oneOf('json-asset-text').type('asset/source').with({
8748
+ type: 'text'
8749
+ }), rule.oneOf('json-asset-raw').type('asset/source').resourceQuery(RAW_QUERY_REGEX);
8740
8750
  let assetsFilename = getMergedFilename('assets');
8741
8751
  chain.output.assetModuleFilename(assetsFilename), emitAssets || chain.module.generator.merge({
8742
8752
  'asset/resource': {
@@ -9034,7 +9044,9 @@ try {
9034
9044
  let cssRule = chain.module.rule(CHAIN_ID.RULE.CSS), { config } = environment;
9035
9045
  cssRule.test(CSS_REGEX).dependency({
9036
9046
  not: 'url'
9037
- });
9047
+ }), cssRule.oneOf(CHAIN_ID.ONE_OF.CSS_TEXT).with({
9048
+ type: 'text'
9049
+ }).type('asset/source');
9038
9050
  let urlRule = cssRule.oneOf(CHAIN_ID.ONE_OF.CSS_URL).resourceQuery(URL_QUERY_REGEX);
9039
9051
  urlRule.use(CHAIN_ID.USE.CSS_URL).loader(node_path.join(dirname, 'cssUrlLoader.mjs'));
9040
9052
  let inlineRule = cssRule.oneOf(CHAIN_ID.ONE_OF.CSS_INLINE).resourceQuery(INLINE_QUERY_REGEX);
@@ -9194,7 +9206,9 @@ try {
9194
9206
  let { config, browserslist } = environment, cacheRoot = node_path.join(api.context.cachePath, '.swc'), rule = chain.module.rule(CHAIN_ID.RULE.JS).test(SCRIPT_REGEX).dependency({
9195
9207
  not: 'url'
9196
9208
  });
9197
- rule.oneOf(CHAIN_ID.ONE_OF.JS_RAW).resourceQuery(RAW_QUERY_REGEX).type('asset/source');
9209
+ rule.oneOf(CHAIN_ID.ONE_OF.JS_TEXT).with({
9210
+ type: 'text'
9211
+ }).type('asset/source'), rule.oneOf(CHAIN_ID.ONE_OF.JS_RAW).resourceQuery(RAW_QUERY_REGEX).type('asset/source');
9198
9212
  let mainRule = rule.oneOf(CHAIN_ID.ONE_OF.JS_MAIN).type("javascript/auto"), dataUriRule = chain.module.rule(CHAIN_ID.RULE.JS_DATA_URI).mimetype({
9199
9213
  or: [
9200
9214
  "text/javascript",
@@ -9853,36 +9867,53 @@ async function createRsbuild(options = {}) {
9853
9867
  function defineConfig(config) {
9854
9868
  return config;
9855
9869
  }
9856
- async function loadConfig_loadConfig({ cwd = process.cwd(), path, envMode, meta, loader = 'auto' } = {}) {
9857
- let configExport, configFilePath = ((root, customConfig)=>{
9870
+ let DEFAULT_CONFIG_FILE_NAMES = [
9871
+ 'rsbuild.config.ts',
9872
+ 'rsbuild.config.js',
9873
+ 'rsbuild.config.mts',
9874
+ 'rsbuild.config.mjs',
9875
+ 'rsbuild.config.cts',
9876
+ 'rsbuild.config.cjs'
9877
+ ], getConfigExport = (module)=>module && 'object' == typeof module && 'default' in module ? module.default : module, tryFreshImport = async (configFileURL)=>{
9878
+ try {
9879
+ let { freshImport } = await import("./fresh-import.js");
9880
+ return await freshImport(configFileURL);
9881
+ } catch (err) {
9882
+ src_logger.debug('failed to initialize fresh-import, fallback to dynamic import.'), src_logger.debug(err);
9883
+ }
9884
+ }, loadConfigWithNative = async (configFilePath)=>{
9885
+ let configFileURL = pathToFileURL(configFilePath).href, freshImportResult = await tryFreshImport(configFileURL);
9886
+ return freshImportResult ? {
9887
+ configExport: getConfigExport(freshImportResult.result),
9888
+ dependencies: freshImportResult.dependencies.sort()
9889
+ } : {
9890
+ configExport: getConfigExport(await import(`${configFileURL}?t=${Date.now()}`)),
9891
+ dependencies: []
9892
+ };
9893
+ };
9894
+ async function loadConfig_loadConfig({ cwd = process.cwd(), path, configFileNames, envMode, meta, loader = 'auto', command } = {}) {
9895
+ let configExport, configFilePath = ((root, customConfig, configFileNames = DEFAULT_CONFIG_FILE_NAMES)=>{
9858
9896
  if (customConfig) {
9859
9897
  let customConfigPath = external_node_path_isAbsolute(customConfig) ? customConfig : join(root, customConfig);
9860
9898
  if (node_fs.existsSync(customConfigPath)) return customConfigPath;
9861
9899
  throw Error(`Cannot find config file: ${color.dim(customConfigPath)}`);
9862
9900
  }
9863
- for (let file of [
9864
- 'rsbuild.config.ts',
9865
- 'rsbuild.config.js',
9866
- 'rsbuild.config.mts',
9867
- 'rsbuild.config.mjs',
9868
- 'rsbuild.config.cts',
9869
- 'rsbuild.config.cjs'
9870
- ]){
9901
+ for (let file of configFileNames){
9871
9902
  let configFile = join(root, file);
9872
9903
  if (node_fs.existsSync(configFile)) return configFile;
9873
9904
  }
9874
9905
  return null;
9875
- })(cwd, path);
9906
+ })(cwd, path, configFileNames);
9876
9907
  if (!configFilePath) return src_logger.debug('no config file found.'), {
9877
9908
  content: {},
9878
- filePath: configFilePath
9909
+ filePath: configFilePath,
9910
+ dependencies: []
9879
9911
  };
9880
- let applyMetaInfo = (config)=>(config._privateMeta = {
9912
+ let dependencies = [], applyMetaInfo = (config)=>(config._privateMeta = {
9881
9913
  configFilePath
9882
9914
  }, config);
9883
9915
  if ('native' === loader || 'auto' === loader && (process.features.typescript || process.versions.bun || process.versions.deno) || /\.(?:js|mjs|cjs)$/.test(configFilePath)) try {
9884
- let configFileURL = pathToFileURL(configFilePath).href, exportModule = await import(`${configFileURL}?t=${Date.now()}`);
9885
- configExport = exportModule.default ? exportModule.default : exportModule;
9916
+ ({ configExport, dependencies } = await loadConfigWithNative(configFilePath));
9886
9917
  } catch (err) {
9887
9918
  let errorMessage = `Failed to load file with native loader: ${color.dim(configFilePath)}`;
9888
9919
  if ('native' === loader) throw src_logger.error(errorMessage), err;
@@ -9903,66 +9934,75 @@ async function loadConfig_loadConfig({ cwd = process.cwd(), path, envMode, meta,
9903
9934
  throw src_logger.error(`Failed to load file with jiti: ${color.dim(configFilePath)}`), err;
9904
9935
  }
9905
9936
  if ('function' == typeof configExport) {
9906
- let command = process.argv[2], nodeEnv = process.env.NODE_ENV || '', result = await configExport({
9937
+ let nodeEnv = process.env.NODE_ENV || '', configParams = {
9907
9938
  env: nodeEnv,
9908
- command,
9939
+ command: command ?? process.argv[2],
9909
9940
  envMode: envMode || nodeEnv,
9910
9941
  meta
9911
- });
9942
+ }, result = await configExport(configParams);
9912
9943
  if (void 0 === result) throw Error(`${color.dim('[rsbuild:loadConfig]')} The config function must return a config object.`);
9913
9944
  return {
9914
9945
  content: applyMetaInfo(result),
9915
- filePath: configFilePath
9946
+ filePath: configFilePath,
9947
+ dependencies
9916
9948
  };
9917
9949
  }
9918
9950
  if (!isObject(configExport)) throw Error(`${color.dim('[rsbuild:loadConfig]')} The config must be an object or a function that returns an object, get ${color.yellow(configExport)}`);
9919
9951
  return src_logger.debug('configuration loaded from:', configFilePath), {
9920
9952
  content: applyMetaInfo(configExport),
9921
- filePath: configFilePath
9953
+ filePath: configFilePath,
9954
+ dependencies
9922
9955
  };
9923
9956
  }
9924
- let commonOpts = {}, init_loadConfig = async (root)=>{
9925
- let { content: config, filePath } = await loadConfig_loadConfig({
9957
+ let cliState = {
9958
+ options: {}
9959
+ }, initCliAction = (command, options)=>{
9960
+ process.env.NODE_ENV || (process.env.NODE_ENV = 'build' === command || 'preview' === command ? 'production' : 'development'), options.environment?.some((env)=>env.includes(',')) && (options.environment = options.environment.flatMap((env)=>env.split(','))), cliState.command = command, cliState.options = options;
9961
+ }, init_loadConfig = async (root)=>{
9962
+ let { options, command } = cliState, { content: config, filePath, dependencies } = await loadConfig_loadConfig({
9926
9963
  cwd: root,
9927
- path: commonOpts.config,
9928
- envMode: commonOpts.envMode,
9929
- loader: commonOpts.configLoader
9964
+ path: options.config,
9965
+ envMode: options.envMode,
9966
+ loader: options.configLoader,
9967
+ command
9930
9968
  });
9931
- if (config.dev ||= {}, config.source ||= {}, config.server ||= {}, commonOpts.base && (config.server.base = commonOpts.base), commonOpts.root && (config.root = root), commonOpts.mode && (config.mode = commonOpts.mode), commonOpts.logLevel && (config.logLevel = commonOpts.logLevel), commonOpts.open && !config.server?.open && (config.server.open = commonOpts.open), void 0 !== commonOpts.host && (config.server.host = commonOpts.host), commonOpts.port && (config.server.port = commonOpts.port), void 0 !== commonOpts.distPath) {
9969
+ if (config.dev ||= {}, config.source ||= {}, config.server ||= {}, options.base && (config.server.base = options.base), options.root && (config.root = root), options.mode && (config.mode = options.mode), options.logLevel && (config.logLevel = options.logLevel), options.open && !config.server?.open && (config.server.open = options.open), void 0 !== options.host && (config.server.host = options.host), options.port && (config.server.port = options.port), void 0 !== options.strictPort && (config.server.strictPort = options.strictPort), void 0 !== options.distPath) {
9932
9970
  config.output ||= {};
9933
9971
  let { distPath } = config.output;
9934
9972
  config.output.distPath = distPath && 'object' == typeof distPath ? {
9935
9973
  ...distPath,
9936
- root: commonOpts.distPath
9974
+ root: options.distPath
9937
9975
  } : {
9938
- root: commonOpts.distPath
9976
+ root: options.distPath
9939
9977
  };
9940
9978
  }
9941
- if (void 0 !== commonOpts.sourceMap) {
9942
- let sourceMap = commonOpts.sourceMap;
9979
+ if (void 0 !== options.sourceMap) {
9980
+ let sourceMap = options.sourceMap;
9943
9981
  if ('boolean' != typeof sourceMap) throw Error('The "--source-map" option only accepts a boolean value.');
9944
9982
  config.output ||= {}, config.output.sourceMap = sourceMap;
9945
9983
  }
9946
9984
  return void 0 === config.dev.cliShortcuts && (config.dev.cliShortcuts = !0), filePath && (config.dev.watchFiles = [
9947
9985
  ...config.dev.watchFiles ? helpers_castArray(config.dev.watchFiles) : [],
9948
9986
  {
9949
- paths: filePath,
9987
+ paths: [
9988
+ filePath,
9989
+ ...dependencies
9990
+ ],
9950
9991
  type: 'reload-server'
9951
9992
  }
9952
9993
  ]), config;
9953
9994
  };
9954
- async function init_init({ cliOptions, isRestart, isBuildWatch = !1 }) {
9955
- cliOptions && (commonOpts = cliOptions), commonOpts.environment?.some((env)=>env.includes(',')) && (commonOpts.environment = commonOpts.environment.flatMap((env)=>env.split(',')));
9956
- let logger = src_logger;
9995
+ async function init_init({ isRestart, isBuildWatch = !1 } = {}) {
9996
+ let logger = src_logger, { options } = cliState;
9957
9997
  try {
9958
9998
  var envDir;
9959
- let cwd = process.cwd(), root = commonOpts.root ? ensureAbsolutePath(cwd, commonOpts.root) : cwd, rsbuild = await createRsbuild({
9999
+ let cwd = process.cwd(), root = options.root ? ensureAbsolutePath(cwd, options.root) : cwd, rsbuild = await createRsbuild({
9960
10000
  cwd: root,
9961
10001
  config: ()=>init_loadConfig(root),
9962
- environment: commonOpts.environment,
9963
- loadEnv: !1 !== commonOpts.env && {
9964
- cwd: (envDir = commonOpts.envDir) ? node_path.isAbsolute(envDir) ? envDir : node_path.join(root, envDir) : root,
9965
- mode: commonOpts.envMode
10002
+ environment: options.environment,
10003
+ loadEnv: !1 !== options.env && {
10004
+ cwd: (envDir = options.envDir) ? node_path.isAbsolute(envDir) ? envDir : node_path.join(root, envDir) : root,
10005
+ mode: options.envMode
9966
10006
  }
9967
10007
  });
9968
10008
  return logger = rsbuild.logger, rsbuild.onBeforeCreateCompiler(()=>{
@@ -10042,11 +10082,11 @@ async function watchFilesForRestart({ files, rsbuild, isBuildWatch, watchOptions
10042
10082
  watcher.on('add', onChange), watcher.on('change', onChange), watcher.on('unlink', onChange);
10043
10083
  }
10044
10084
  let applyServerOptions = (command)=>{
10045
- command.option('-o, --open [url]', 'Open the page in browser on startup').option('--port <port>', 'Set the port number for the server').option('--host [host]', 'Set the host that the server listens to');
10085
+ command.option('-o, --open [url]', 'Open the page in browser on startup').option('--port <port>', 'Set the port number for the server').option('--strict-port', 'Exit if the specified port is already in use').option('--host [host]', 'Set the host that the server listens to');
10046
10086
  };
10047
- function setupCommands() {
10087
+ function setupCommands(argv) {
10048
10088
  let cli = ((name = "")=>new CAC(name))('rsbuild');
10049
- cli.version("2.1.2"), cli.option('--base <base>', 'Set the base path of the server').option('-c, --config <config>', 'Set the configuration file (relative or absolute path)').option('--config-loader <loader>', 'Set the config file loader (auto | jiti | native)', {
10089
+ cli.version("2.1.3"), cli.option('--base <base>', 'Set the base path of the server').option('-c, --config <config>', 'Set the configuration file (relative or absolute path)').option('--config-loader <loader>', 'Set the config file loader (auto | jiti | native)', {
10050
10090
  default: 'auto'
10051
10091
  }).option('--dist-path <dir>', 'Set the root directory of output files').option('--source-map', 'Enable source map').option('--env-dir <dir>', 'Set the directory for loading `.env` files').option('--env-mode <mode>', 'Set the env mode to load the `.env.[mode]` file').option('--environment <name>', 'Set the environment name(s) to build', {
10052
10092
  type: [
@@ -10058,20 +10098,19 @@ function setupCommands() {
10058
10098
  applyServerOptions(devCommand), applyServerOptions(previewCommand);
10059
10099
  let logger = src_logger;
10060
10100
  devCommand.action(async (options)=>{
10101
+ initCliAction('dev', options);
10061
10102
  try {
10062
- let rsbuild = await init_init({
10063
- cliOptions: options
10064
- });
10103
+ let rsbuild = await init_init();
10065
10104
  if (!rsbuild) return;
10066
10105
  logger = rsbuild.logger, await rsbuild.startDevServer();
10067
10106
  } catch (err) {
10068
10107
  logger.error('Failed to start dev server.'), logger.error(err), process.exit(1);
10069
10108
  }
10070
10109
  }), buildCommand.option('-w, --watch', 'Enable watch mode to automatically rebuild on file changes').action(async (options)=>{
10110
+ initCliAction('build', options);
10071
10111
  try {
10072
10112
  options.watch || (process.env.RSPACK_UNSAFE_FAST_DROP = 'true');
10073
10113
  let rsbuild = await init_init({
10074
- cliOptions: options,
10075
10114
  isBuildWatch: options.watch
10076
10115
  });
10077
10116
  if (!rsbuild) return;
@@ -10084,20 +10123,18 @@ function setupCommands() {
10084
10123
  err instanceof Error && err.message === RSPACK_BUILD_ERROR || logger.error('Failed to build.'), logger.error(err), process.exit(1);
10085
10124
  }
10086
10125
  }), previewCommand.action(async (options)=>{
10126
+ initCliAction('preview', options);
10087
10127
  try {
10088
- let rsbuild = await init_init({
10089
- cliOptions: options
10090
- });
10128
+ let rsbuild = await init_init();
10091
10129
  if (!rsbuild) return;
10092
10130
  logger = rsbuild.logger, await rsbuild.preview();
10093
10131
  } catch (err) {
10094
10132
  logger.error('Failed to start preview server.'), logger.error(err), process.exit(1);
10095
10133
  }
10096
10134
  }), inspectCommand.option('--output <output>', 'Set the output path for inspection results').option('--verbose', 'Show complete function definitions in output').action(async (options)=>{
10135
+ initCliAction('inspect', options);
10097
10136
  try {
10098
- let rsbuild = await init_init({
10099
- cliOptions: options
10100
- });
10137
+ let rsbuild = await init_init();
10101
10138
  if (!rsbuild) return;
10102
10139
  logger = rsbuild.logger, await rsbuild.inspectConfig({
10103
10140
  verbose: options.verbose,
@@ -10109,21 +10146,17 @@ function setupCommands() {
10109
10146
  }
10110
10147
  }), cli.help((sections)=>{
10111
10148
  for (let section of (sections.shift(), sections))'Usage' === section.title && (section.body = section.body.replace('$ rsbuild', color.yellow("$ rsbuild [command] [options]"))), 'Commands' === section.title && (section.body = section.body.replace(` ${devDescription}`, `dev ${devDescription}`)), section.title?.startsWith('For more info') ? (section.title = color.dim(' For details on a sub-command, run'), section.body = color.dim(' $ rsbuild <command> -h')) : section.title && (section.title = color.cyan(section.title));
10112
- }), cli.parse();
10113
- }
10114
- let { argv: cli_argv } = process;
10115
- function initNodeEnv(command) {
10116
- process.env.NODE_ENV || (process.env.NODE_ENV = 'build' === command || 'preview' === command ? 'production' : 'development');
10149
+ }), cli.parse(argv);
10117
10150
  }
10118
10151
  function showGreeting() {
10119
10152
  let { npm_execpath, npm_lifecycle_event, NODE_RUN_SCRIPT_NAME } = process.env, isBun = npm_execpath?.includes('.bun');
10120
- src_logger.greet(`${'npx' === npm_lifecycle_event || isBun || NODE_RUN_SCRIPT_NAME ? '\n' : ''}Rsbuild v2.1.2\n`);
10153
+ src_logger.greet(`${'npx' === npm_lifecycle_event || isBun || NODE_RUN_SCRIPT_NAME ? '\n' : ''}Rsbuild v2.1.3\n`);
10121
10154
  }
10122
- function setupLogLevel() {
10123
- if (cli_argv.length <= 3) return;
10124
- let logLevelIndex = cli_argv.findIndex((item)=>'--log-level' === item || '--logLevel' === item);
10155
+ function setupLogLevel(argv) {
10156
+ if (argv.length <= 3) return;
10157
+ let logLevelIndex = argv.findIndex((item)=>'--log-level' === item || '--logLevel' === item);
10125
10158
  if (-1 !== logLevelIndex) {
10126
- let level = process.argv[logLevelIndex + 1];
10159
+ let level = argv[logLevelIndex + 1];
10127
10160
  level && [
10128
10161
  'warn',
10129
10162
  'error',
@@ -10131,13 +10164,13 @@ function setupLogLevel() {
10131
10164
  ].includes(level) && !isDebug() && (src_logger.level = level);
10132
10165
  }
10133
10166
  }
10134
- function runCLI() {
10135
- initNodeEnv(cli_argv[2]), setupLogLevel(), showGreeting();
10167
+ function runCLI({ argv = process.argv } = {}) {
10168
+ setupLogLevel(argv), showGreeting();
10136
10169
  try {
10137
- setupCommands();
10170
+ setupCommands(argv);
10138
10171
  } catch (err) {
10139
10172
  src_logger.error('Failed to start Rsbuild CLI.'), src_logger.error(err), process.exit(1);
10140
10173
  }
10141
10174
  }
10142
- let src_version = "2.1.2";
10175
+ let src_version = "2.1.3";
10143
10176
  export { PLUGIN_CSS_NAME, PLUGIN_SWC_NAME, core_rspack as rspack, createRsbuild, defaultAllowedOrigins, defineConfig, ensureAssetPrefix, loadConfig_loadConfig as loadConfig, loadEnv, logger_createLogger as createLogger, mergeRsbuildConfig, mrmime_lookup, runCLI, src_logger as logger, src_version as version };
@@ -0,0 +1,90 @@
1
+ let importer;
2
+ import { Module } from "node:module";
3
+ import { fileURLToPath } from "node:url";
4
+ import { MessageChannel } from "node:worker_threads";
5
+ let instanceId = Math.random().toString(36).slice(2), relativeImportRE = /^\.{1,2}(?:\/|\\)/;
6
+ function escapeRegExp(value) {
7
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8
+ }
9
+ function buildQueryName() {
10
+ return `fresh-import-${instanceId}`;
11
+ }
12
+ function buildQueryRE(queryName) {
13
+ return RegExp(`(?:\\?|&)${escapeRegExp(queryName)}=(\\d+),([^&]+)(?:&|$)`);
14
+ }
15
+ function formatTrackingQuery(queryName, id, context) {
16
+ return `?${queryName}=${id},${context}`;
17
+ }
18
+ function trackResolved(specifier, context, result, queryName, queryRE, onDependency) {
19
+ let isRelativeImport = relativeImportRE.test(specifier);
20
+ if ("builtin" === result.format || !isRelativeImport || !context.parentURL || queryRE.test(result.url) || !result.url.startsWith("file:")) return result;
21
+ let m = queryRE.exec(context.parentURL);
22
+ if (m) {
23
+ let [, id, contextFile] = m;
24
+ onDependency(contextFile, result.url), result.url = result.url.replace(/(\?)|$/, (_n, n1)=>`?${queryName}=${id},${contextFile}${"?" === n1 ? "&" : ""}`);
25
+ }
26
+ return result;
27
+ }
28
+ let nextId$1 = 0;
29
+ function createOffThreadImporter() {
30
+ let queryName = buildQueryName(), { port1, port2 } = new MessageChannel();
31
+ return Module.register('data:text/javascript,Math.random().toString(36).slice(2);%0Aconst relativeImportRE = /^\\.{1,2}(%3F:\\/|\\\\)/;%0Afunction escapeRegExp(value) {%0A%09return value.replace(/[.*+%3F^${}()|[\\]\\\\]/g, "\\\\$&");%0A}%0A/**%0A* Build the regex that matches the tracking query `%3F<name>=<id>,<context>`%0A* (or the `&<name>=...` form).%0A*/%0Afunction buildQueryRE(queryName) {%0A%09return new RegExp(`(%3F:\\\\%3F|&)${escapeRegExp(queryName)}=(\\\\d+),([^&]+)(%3F:&|$)`);%0A}%0A/**%0A* Shared body of the resolve hook for both the on-thread and off-thread%0A* importers. Given an already-resolved `result`, decides whether it is a tracked%0A* relative file dependency; if so, reports it via `onDependency` and tags the%0A* URL so the query propagates to its own dependencies.%0A*%0A* The sync/async difference between the two hooks lives entirely in the caller%0A* (which awaits `nextResolve` or not); this function performs no I/O. `result`%0A* is mutated in place and returned.%0A*/%0Afunction trackResolved(specifier, context, result, queryName, queryRE, onDependency) {%0A%09const isRelativeImport = relativeImportRE.test(specifier);%0A%09if (result.format === "builtin" || !isRelativeImport) return result;%0A%09if (!context.parentURL || queryRE.test(result.url) || !result.url.startsWith("file:")) return result;%0A%09const m = queryRE.exec(context.parentURL);%0A%09if (m) {%0A%09%09const [, id, contextFile] = m;%0A%09%09onDependency(contextFile, result.url);%0A%09%09result.url = result.url.replace(/(\\%3F)|$/, (_n, n1) => `%3F${queryName}=${id},${contextFile}${n1 === "%3F" %3F "&" : ""}`);%0A%09}%0A%09return result;%0A}%0A//%23endregion%0A//%23region src/off-thread/loader.ts%0Alet port;%0Alet queryName;%0Alet queryRE;%0Aconst initialize = async (data) => {%0A%09port = data.port;%0A%09queryName = data.queryName;%0A%09queryRE = buildQueryRE(queryName);%0A};%0Aconst resolve = async (specifier, context, nextResolve) => {%0A%09return trackResolved(specifier, context, await nextResolve(specifier, context), queryName, queryRE, (ctx, url) => {%0A%09%09port.postMessage({%0A%09%09%09context: ctx,%0A%09%09%09url%0A%09%09});%0A%09});%0A};%0A//%23endregion%0Aexport { initialize, resolve };%0A', {
32
+ data: {
33
+ port: port2,
34
+ queryName
35
+ },
36
+ transferList: [
37
+ port2
38
+ ]
39
+ }), port1.unref(), {
40
+ async collect (specifier) {
41
+ let id = nextId$1++, depsList = new Set(), onMessage = (e)=>{
42
+ e.context === specifier && depsList.add(e.url);
43
+ };
44
+ port1.on("message", onMessage), port1.unref();
45
+ try {
46
+ let result = await import(specifier + formatTrackingQuery(queryName, id, specifier));
47
+ return await new Promise((resolve)=>setImmediate(resolve)), {
48
+ result,
49
+ dependencies: [
50
+ ...depsList
51
+ ].filter((url)=>url.startsWith("file:")).map((url)=>fileURLToPath(url))
52
+ };
53
+ } finally{
54
+ port1.off("message", onMessage);
55
+ }
56
+ }
57
+ };
58
+ }
59
+ let nextId = 0;
60
+ function createOnThreadImporter() {
61
+ let registry = new Map(), queryName = buildQueryName(), queryRE = buildQueryRE(queryName);
62
+ return Module.registerHooks({
63
+ resolve: (specifier, context, nextResolve)=>trackResolved(specifier, context, nextResolve(specifier, context), queryName, queryRE, (ctx, url)=>{
64
+ registry.get(ctx)?.add(url);
65
+ })
66
+ }), {
67
+ async collect (specifier) {
68
+ let id = nextId++, depsList = new Set();
69
+ registry.set(specifier, depsList);
70
+ try {
71
+ return {
72
+ result: await import(specifier + formatTrackingQuery(queryName, id, specifier)),
73
+ dependencies: [
74
+ ...depsList
75
+ ].filter((url)=>url.startsWith("file:")).map((url)=>fileURLToPath(url))
76
+ };
77
+ } finally{
78
+ registry.delete(specifier);
79
+ }
80
+ }
81
+ };
82
+ }
83
+ function createImporter() {
84
+ return Module.registerHooks ? createOnThreadImporter() : Module.register ? createOffThreadImporter() : void 0;
85
+ }
86
+ let initialized = !1;
87
+ function freshImport(specifier) {
88
+ return initialized || (importer = createImporter(), initialized = !0), importer?.collect(specifier);
89
+ }
90
+ export { freshImport };
@@ -14,6 +14,7 @@ export type CommonOptions = {
14
14
  open?: boolean | string;
15
15
  host?: true | string;
16
16
  port?: number;
17
+ strictPort?: boolean;
17
18
  environment?: string[];
18
19
  logLevel?: LogLevel;
19
20
  };
@@ -27,4 +28,4 @@ export type InspectOptions = CommonOptions & {
27
28
  };
28
29
  export type DevOptions = CommonOptions;
29
30
  export type PreviewOptions = CommonOptions;
30
- export declare function setupCommands(): void;
31
+ export declare function setupCommands(argv: string[]): void;
@@ -1 +1,7 @@
1
- export declare function runCLI(): void;
1
+ export type RunCLIOptions = {
2
+ /**
3
+ * The command-line arguments to parse, matching the shape of Node.js `process.argv`
4
+ * @default process.argv
5
+ */ argv?: string[];
6
+ };
7
+ export declare function runCLI({ argv }?: RunCLIOptions): void;
@@ -1,7 +1,8 @@
1
1
  import type { RsbuildInstance } from '../types';
2
2
  import type { CommonOptions } from './commands';
3
- export declare function init({ cliOptions, isRestart, isBuildWatch }: {
4
- cliOptions?: CommonOptions;
3
+ export type CommandName = 'dev' | 'build' | 'preview' | 'inspect';
4
+ export declare const initCliAction: (command: CommandName, options: CommonOptions) => void;
5
+ export declare function init({ isRestart, isBuildWatch }?: {
5
6
  isRestart?: boolean;
6
7
  isBuildWatch?: boolean;
7
8
  }): Promise<RsbuildInstance | undefined>;
@@ -24,12 +24,15 @@ export declare const CHAIN_ID: {
24
24
  /** JS oneOf rules */ readonly JS_MAIN: 'js';
25
25
  readonly JS_WORKER: 'js-worker';
26
26
  readonly JS_RAW: 'js-raw';
27
+ readonly JS_TEXT: 'js-text';
27
28
  /** CSS oneOf rules */ readonly CSS_MAIN: 'css';
28
29
  readonly CSS_RAW: 'css-raw';
30
+ readonly CSS_TEXT: 'css-text';
29
31
  readonly CSS_URL: 'css-url';
30
32
  readonly CSS_INLINE: 'css-inline';
31
33
  /** SVG oneOf rules */ readonly SVG: 'svg';
32
34
  readonly SVG_RAW: 'svg-asset-raw';
35
+ readonly SVG_TEXT: 'svg-asset-text';
33
36
  readonly SVG_URL: 'svg-asset-url';
34
37
  readonly SVG_ASSET: 'svg-asset';
35
38
  readonly SVG_REACT: 'svg-react';
@@ -3,9 +3,9 @@
3
3
  * the public API of @rsbuild/core.
4
4
  */ import type * as Rspack from '@rspack/core';
5
5
  import { rspack } from '@rspack/core';
6
- export { runCLI } from './cli';
6
+ export { type RunCLIOptions, runCLI } from './cli';
7
7
  export { createRsbuild } from './createRsbuild';
8
- export { type ConfigParams, defineConfig, type LoadConfigOptions, type LoadConfigResult, loadConfig } from './loadConfig';
8
+ export { type ConfigParams, defineConfig, type LoadConfigOptions, type LoadConfigResult, type RsbuildConfigAsyncFn, type RsbuildConfigDefinition, type RsbuildConfigSyncFn, loadConfig } from './loadConfig';
9
9
  // Core methods
10
10
  export { type LoadEnvOptions, type LoadEnvResult, loadEnv } from './loadEnv';
11
11
  // Rsbuild version
@@ -7,7 +7,7 @@ export type ConfigParams = {
7
7
  };
8
8
  export type RsbuildConfigAsyncFn = (env: ConfigParams) => Promise<RsbuildConfig>;
9
9
  export type RsbuildConfigSyncFn = (env: ConfigParams) => RsbuildConfig;
10
- export type RsbuildConfigExport = RsbuildConfig | RsbuildConfigSyncFn | RsbuildConfigAsyncFn;
10
+ export type RsbuildConfigDefinition = RsbuildConfig | RsbuildConfigSyncFn | RsbuildConfigAsyncFn;
11
11
  export type LoadConfigOptions = {
12
12
  /**
13
13
  * The root path to resolve the config file.
@@ -18,6 +18,10 @@ export type LoadConfigOptions = {
18
18
  * If `path` is not provided, the function will search for the config file in the `cwd`.
19
19
  */ path?: string;
20
20
  /**
21
+ * Config file names to search in `cwd` when `path` is not provided.
22
+ * The list replaces the default `rsbuild.config.*` lookup order.
23
+ */ configFileNames?: string[];
24
+ /**
21
25
  * A custom meta object to be passed into the config function of `defineConfig`.
22
26
  */ meta?: Record<string, unknown>;
23
27
  /**
@@ -31,6 +35,10 @@ export type LoadConfigOptions = {
31
35
  * - 'native': Use native Node.js loader, requires TypeScript support in Node.js >= 22.6
32
36
  * @default 'auto'
33
37
  */ loader?: ConfigLoader;
38
+ /**
39
+ * The command passed to the config function.
40
+ * @default process.argv[2]
41
+ */ command?: string;
34
42
  };
35
43
  export type LoadConfigResult = {
36
44
  /**
@@ -40,6 +48,10 @@ export type LoadConfigResult = {
40
48
  * The path to the loaded configuration file.
41
49
  * Return `null` if the configuration file is not found.
42
50
  */ filePath: string | null;
51
+ /**
52
+ * Absolute file paths of statically imported (relative) dependencies of the
53
+ * config file.
54
+ */ dependencies: string[];
43
55
  };
44
56
  /**
45
57
  * This function helps you to autocomplete configuration types.
@@ -47,6 +59,6 @@ export type LoadConfigResult = {
47
59
  */ export declare function defineConfig(config: RsbuildConfig): RsbuildConfig;
48
60
  export declare function defineConfig(config: RsbuildConfigSyncFn): RsbuildConfigSyncFn;
49
61
  export declare function defineConfig(config: RsbuildConfigAsyncFn): RsbuildConfigAsyncFn;
50
- export declare function defineConfig(config: RsbuildConfigExport): RsbuildConfigExport;
62
+ export declare function defineConfig(config: RsbuildConfigDefinition): RsbuildConfigDefinition;
51
63
  export type ConfigLoader = 'auto' | 'jiti' | 'native';
52
- export declare function loadConfig({ cwd, path, envMode, meta, loader }?: LoadConfigOptions): Promise<LoadConfigResult>;
64
+ export declare function loadConfig({ cwd, path, configFileNames, envMode, meta, loader, command }?: LoadConfigOptions): Promise<LoadConfigResult>;
@@ -3,5 +3,5 @@
3
3
  * license at https://github.com/facebook/create-react-app/blob/master/LICENSE
4
4
  */ import type { InternalContext, PrintFileSizeAsset, RsbuildPlugin } from '../types';
5
5
  /** Normalize file path by removing hash for comparison across builds */ export declare function normalizeFilePath(filePath: string): string;
6
- /** Exclude source map and license files by default */ export declare const excludeAsset: (asset: PrintFileSizeAsset) => boolean;
6
+ /** Exclude source map, license, and type declaration files by default */ export declare const excludeAsset: (asset: PrintFileSizeAsset) => boolean;
7
7
  export declare const pluginFileSize: (context: InternalContext) => RsbuildPlugin;
@@ -516,7 +516,7 @@ export type PrintFileSizeOptions = {
516
516
  /**
517
517
  * A filter function to exclude static assets from the total size or detailed size.
518
518
  * If both `include` and `exclude` are set, `exclude` will take precedence.
519
- * @default (asset) => /\.(?:map|LICENSE\.txt)$/.test(asset.name)
519
+ * @default (asset) => /\.(?:map|LICENSE\.txt|d\.(?:ts|mts|cts))$/.test(asset.name)
520
520
  */ exclude?: (asset: PrintFileSizeAsset) => boolean;
521
521
  /**
522
522
  * Controls whether file size differences are displayed relative to the previous build.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsbuild/core",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
4
4
  "description": "The Rspack-based build tool.",
5
5
  "homepage": "https://rsbuild.rs",
6
6
  "bugs": {
@@ -61,6 +61,7 @@
61
61
  "css-loader": "7.1.4",
62
62
  "deepmerge": "^4.3.1",
63
63
  "dotenv-expand": "^13.0.0",
64
+ "fresh-import": "^0.2.1",
64
65
  "html-rspack-plugin": "6.1.9",
65
66
  "http-proxy-middleware": "4.1.1",
66
67
  "jiti": "^2.7.0",