diff --git a/packages/core/src/cli/initConfig.ts b/packages/core/src/cli/initConfig.ts index db197cdd2..11881f905 100644 --- a/packages/core/src/cli/initConfig.ts +++ b/packages/core/src/cli/initConfig.ts @@ -2,7 +2,11 @@ import path from 'node:path'; import util from 'node:util'; import { loadEnv, type RsbuildEntry } from '@rsbuild/core'; import { loadConfig } from '../config'; -import type { RsbuildConfigOutputTarget, RslibConfig } from '../types'; +import type { + LibConfig, + RsbuildConfigOutputTarget, + RslibConfig, +} from '../types'; import { getAbsolutePath } from '../utils/helper'; import { logger } from '../utils/logger'; import type { BuildOptions, CommonOptions } from './commands'; @@ -85,16 +89,16 @@ export const applyCliOptions = ( lib.autoExtension = options.autoExtension; if (options.autoExternal !== undefined) lib.autoExternal = options.autoExternal; - const output = lib.output ?? {}; + lib.output ??= {}; if (options.target !== undefined) - output.target = options.target as RsbuildConfigOutputTarget; - if (options.minify !== undefined) output.minify = options.minify; - if (options.clean !== undefined) output.cleanDistPath = options.clean; + lib.output.target = options.target as RsbuildConfigOutputTarget; + if (options.minify !== undefined) lib.output.minify = options.minify; + if (options.clean !== undefined) lib.output.cleanDistPath = options.clean; const externals = options.externals?.filter(Boolean) ?? []; - if (externals.length > 0) output.externals = externals; + if (externals.length > 0) lib.output.externals = externals; if (options.distPath) { - output.distPath = { - ...(typeof output.distPath === 'object' ? output.distPath : {}), + lib.output.distPath = { + ...(typeof lib.output.distPath === 'object' ? lib.output.distPath : {}), root: options.distPath, }; } @@ -103,7 +107,7 @@ export const applyCliOptions = ( export async function initConfig(options: CommonOptions): Promise<{ config: RslibConfig; - configFilePath: string; + configFilePath?: string; watchFiles: string[]; }> { const cwd = process.cwd(); @@ -122,6 +126,13 @@ export async function initConfig(options: CommonOptions): Promise<{ loader: options.configLoader, }); + if (configFilePath === undefined) { + config.lib = [{} satisfies LibConfig]; + logger.debug( + 'No config file found. Falling back to CLI options for the default library.', + ); + } + config.source ||= {}; config.source.define = { ...envs.publicVars, @@ -136,6 +147,6 @@ export async function initConfig(options: CommonOptions): Promise<{ return { config, configFilePath, - watchFiles: [configFilePath, ...envs.filePaths], + watchFiles: [configFilePath, ...envs.filePaths].filter(Boolean) as string[], }; } diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index ef3fc1817..b309abc03 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -99,7 +99,10 @@ const findConfig = (basePath: string): string | undefined => { ); }; -const resolveConfigPath = (root: string, customConfig?: string): string => { +const resolveConfigPath = ( + root: string, + customConfig?: string, +): string | undefined => { if (customConfig) { const customConfigPath = isAbsolute(customConfig) ? customConfig @@ -115,8 +118,7 @@ const resolveConfigPath = (root: string, customConfig?: string): string => { if (configFilePath) { return configFilePath; } - - throw new Error(`${DEFAULT_CONFIG_NAME} not found in ${root}`); + return undefined; }; export type ConfigLoader = 'auto' | 'jiti' | 'native'; @@ -133,9 +135,17 @@ export async function loadConfig({ loader?: ConfigLoader; }): Promise<{ content: RslibConfig; - filePath: string; + filePath?: string; }> { const configFilePath = resolveConfigPath(cwd, path); + if (!configFilePath) { + return { + content: { + lib: [], + }, + filePath: undefined, + }; + } const { content } = await loadRsbuildConfig({ cwd: dirname(configFilePath), path: configFilePath, diff --git a/tests/integration/cli/build/build.test.ts b/tests/integration/cli/build/build.test.ts index 9c786a55a..1f3be98f5 100644 --- a/tests/integration/cli/build/build.test.ts +++ b/tests/integration/cli/build/build.test.ts @@ -142,15 +142,22 @@ describe('build command', async () => { `); }); - test('should throw error if config file is absent, but it should work if the future', async () => { + test('should build when config file is absent', async () => { const fixturePath = path.join(__dirname, 'no-config'); await fse.remove(path.join(fixturePath, 'dist')); - expect(() => - runCliSync('build --format cjs', { - cwd: fixturePath, - }), - ).toThrowError(/rslib\.config not found in.*cli[\\/]build[\\/]no-config/); + runCliSync('build --dist-path=dist/a --syntax=es2015', { + cwd: fixturePath, + }); + + const files = await globContentJSON(path.join(fixturePath, 'dist')); + expect(files).toMatchInlineSnapshot(` + { + "/tests/integration/cli/build/no-config/dist/a/index.js": "const withoutConfig = 1000; + export { withoutConfig }; + ", + } + `); }); test('build options', async () => { diff --git a/tests/integration/cli/build/no-config/src/index.ts b/tests/integration/cli/build/no-config/src/index.ts index 68a0993f6..36e685774 100644 --- a/tests/integration/cli/build/no-config/src/index.ts +++ b/tests/integration/cli/build/no-config/src/index.ts @@ -1 +1 @@ -export const withoutConfig = 'works'; +export const withoutConfig = 1_000; diff --git a/website/docs/en/guide/basic/cli.mdx b/website/docs/en/guide/basic/cli.mdx index 38b22586e..af3a55056 100644 --- a/website/docs/en/guide/basic/cli.mdx +++ b/website/docs/en/guide/basic/cli.mdx @@ -62,6 +62,10 @@ Options: --tsconfig use specific tsconfig (relative to project root) ``` +:::note +If the [Rslib configuration file](/guide/basic/configure-rslib#configuration-file) is not present in your project, the CLI will automatically use the default configuration containing only a single [lib](/config/lib/) and apply all build options from the command line. You can add a configuration file once you need a more complex configuration or want to build outputs in multiple formats. +::: + ### Environment variables Rslib supports injecting environment variables or expressions into the code during the build, which is helpful for distinguishing running environments or replacing constants. You can see more details in [Rsbuild - Environment variables](https://rsbuild.rs/guide/advanced/env-vars). diff --git a/website/docs/zh/guide/basic/cli.mdx b/website/docs/zh/guide/basic/cli.mdx index e30f087e2..adc91c49d 100644 --- a/website/docs/zh/guide/basic/cli.mdx +++ b/website/docs/zh/guide/basic/cli.mdx @@ -62,6 +62,10 @@ Options: --tsconfig 使用指定的 tsconfig(相对于项目根目录) ``` +:::note +如果项目中不存在 Rslib [配置文件](/guide/basic/configure-rslib#配置文件),CLI 将自动使用仅包含单个 [lib](/config/lib/) 的默认配置,并根据命令行参数完成构建。当需要更复杂的配置或构建多种格式的产物时,再补充配置文件即可。 +::: + ### 环境变量 Rslib 支持在构建过程中向代码中注入环境变量或表达式,这对于区分运行环境、替换常量值等场景很有帮助。你可以查看 [Rsbuild - 环境变量](https://rsbuild.rs/zh/guide/advanced/env-vars) 了解更多详细信息。