diff --git a/packages/rspack-cli/src/cli.ts b/packages/rspack-cli/src/cli.ts index 501ce04cea17..f1c38faacbeb 100644 --- a/packages/rspack-cli/src/cli.ts +++ b/packages/rspack-cli/src/cli.ts @@ -1,3 +1,4 @@ +import fs from 'node:fs'; import path from 'node:path'; import util from 'node:util'; import type { @@ -71,6 +72,11 @@ function createAnsiFormatter( }; } +const hasDefaultEntry = (context: string) => + ['./src', './src.js', './src.json'].some((request) => + fs.existsSync(path.resolve(context, request)), + ); + export class RspackCLI { colors: RspackCLIColors; program: CAC; @@ -207,6 +213,7 @@ export class RspackCLI { const isServe = command === 'serve'; const internalBuildConfig = async (item: RspackOptions) => { + const configPaths = pathMap.get(item); if (options.entry) { item.entry = { main: options.entry.map((x) => path.resolve(process.cwd(), x))[0], // Fix me when entry supports array @@ -248,6 +255,17 @@ export class RspackCLI { } if (isServe) { + if ( + !configPaths && + !options.entry && + !item.entry && + !hasDefaultEntry(item.context ?? process.cwd()) + ) { + this.getLogger().warn( + "No rspack config found and default entry './src' does not exist. `rspack serve` starts a development compilation. To serve production build output, use `rspack preview [dir]`.", + ); + } + const installed = (item.plugins ||= []).find( (item) => item instanceof rspack.ProgressPlugin, ); @@ -262,7 +280,6 @@ export class RspackCLI { typeof cacheOptions === 'object' && cacheOptions.type === 'persistent' ) { - const configPaths = pathMap.get(item); if (configPaths) { // for persistent cache cacheOptions.buildDependencies = [ diff --git a/packages/rspack-cli/tests/serve/missing-default-entry/index.test.ts b/packages/rspack-cli/tests/serve/missing-default-entry/index.test.ts new file mode 100644 index 000000000000..245a865ece7e --- /dev/null +++ b/packages/rspack-cli/tests/serve/missing-default-entry/index.test.ts @@ -0,0 +1,20 @@ +import { + normalizeStderr, + runWatch, + uniqueDirectoryForTest, +} from '../../utils/test-utils'; + +describe('serve without a config or default entry', () => { + it('suggests preview when serving build output may be intended', async () => { + const cwd = await uniqueDirectoryForTest(); + const { stdout, stderr } = await runWatch(cwd, ['serve'], { + killString: /Module not found|rspack preview \[dir\]/, + }); + + const output = normalizeStderr(`${stdout}\n${stderr}`); + expect(output).toContain( + "No rspack config found and default entry './src' does not exist.", + ); + expect(output).toContain('use `rspack preview [dir]`'); + }); +});