From 70f1c6302baa2ded3016851b2eb23cb192a0318c Mon Sep 17 00:00:00 2001 From: neverland Date: Fri, 14 Aug 2026 11:53:06 +0800 Subject: [PATCH 1/3] fix(doc): restart dev server on config changes --- packages/rstack/src/rspressConfig.ts | 29 ++++++- .../tests/config/define-doc/index.test.ts | 80 ++++++++++++++++++- 2 files changed, 106 insertions(+), 3 deletions(-) diff --git a/packages/rstack/src/rspressConfig.ts b/packages/rstack/src/rspressConfig.ts index ed5efd59..0bf6a60d 100644 --- a/packages/rstack/src/rspressConfig.ts +++ b/packages/rstack/src/rspressConfig.ts @@ -1,3 +1,4 @@ +import type { WatchFiles } from '@rsbuild/core'; import type { UserConfig } from '@rspress/core'; import { loadRstackConfig, type Configs } from './config.ts'; @@ -13,6 +14,30 @@ const resolveRspressConfig = async (configs: Configs): Promise => { }; export default async (): Promise => { - const { configs } = await loadRstackConfig(); - return resolveRspressConfig(configs); + const { configs, filePath, dependencies } = await loadRstackConfig(); + const config = await resolveRspressConfig(configs); + + if (!filePath) { + return config; + } + + const watchFiles = config.builderConfig?.dev?.watchFiles; + const watchConfig: WatchFiles = { + paths: [filePath, ...dependencies], + type: 'restart', + }; + + return { + ...config, + builderConfig: { + ...config.builderConfig, + dev: { + ...config.builderConfig?.dev, + watchFiles: [ + ...(watchFiles ? (Array.isArray(watchFiles) ? watchFiles : [watchFiles]) : []), + watchConfig, + ], + }, + }, + }; }; diff --git a/packages/rstack/tests/config/define-doc/index.test.ts b/packages/rstack/tests/config/define-doc/index.test.ts index 58ce1fc4..e60c4453 100644 --- a/packages/rstack/tests/config/define-doc/index.test.ts +++ b/packages/rstack/tests/config/define-doc/index.test.ts @@ -1,4 +1,6 @@ -import { getDistFiles, getFileContent } from '@rstackjs/test-utils'; +import { writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import { getDistFiles, getFileContent, getRandomPort } from '@rstackjs/test-utils'; import { test } from '#test-helpers'; const expectedText = 'define.doc works'; @@ -13,3 +15,79 @@ test('should build docs with define.doc config', async ({ prepareDist, execCli, expect(output).toContain(expectedText); }, 30_000); + +test('should restart doc dev server when Rstack config changes', async ({ + execCliAsync, + logHelper, +}) => { + const configFile = path.join(import.meta.dirname, 'test-temp-rstack.config.ts'); + const userWatchFile = path.join(import.meta.dirname, 'test-temp-user-watch.txt'); + + const writeConfig = (title: string) => + writeFile( + configFile, + `import { define } from 'rstack'; + +define.doc({ + root: 'docs', + title: '${title}', + builderConfig: { + dev: { + watchFiles: { + paths: ${JSON.stringify(userWatchFile)}, + type: 'restart', + }, + }, + }, +}); +`, + ); + + await writeFile(userWatchFile, 'initial\n'); + await writeConfig('before config change'); + + execCliAsync(`doc --config test-temp-rstack.config.ts --port ${await getRandomPort()}`); + await logHelper.expectBuildEnd(); + logHelper.clearLogs(); + + await writeConfig('after config change'); + + await logHelper.expectLog('restarting server as test-temp-rstack.config.ts changed'); + await logHelper.expectBuildEnd(); + logHelper.clearLogs(); + + await writeFile(userWatchFile, 'changed\n'); + + await logHelper.expectLog('restarting server as test-temp-user-watch.txt changed'); + await logHelper.expectBuildEnd(); +}, 30_000); + +test('should restart doc dev server when an imported config file changes', async ({ + execCliAsync, + logHelper, +}) => { + const configFile = path.join(import.meta.dirname, 'test-temp-import.config.ts'); + const importedFile = path.join(import.meta.dirname, 'test-temp-imported.ts'); + + await writeFile(importedFile, "export const title = 'before import change';\n"); + await writeFile( + configFile, + `import { define } from 'rstack'; +import { title } from './test-temp-imported.ts'; + +define.doc({ + root: 'docs', + title, +}); +`, + ); + + execCliAsync(`doc --config test-temp-import.config.ts --port ${await getRandomPort()}`); + await logHelper.expectBuildEnd(); + logHelper.clearLogs(); + + await writeFile(importedFile, "export const title = 'after import change';\n"); + + await logHelper.expectLog('restarting server as test-temp-imported.ts changed'); + await logHelper.expectBuildEnd(); +}, 30_000); From aa4f381170de4d9b76128bac5929e06d67c67332 Mon Sep 17 00:00:00 2001 From: neverland Date: Fri, 14 Aug 2026 11:57:53 +0800 Subject: [PATCH 2/3] test(doc): isolate config reload fixture --- .../tests/config/define-doc/index.test.ts | 80 +------------------ .../config/reload-doc-config/docs/index.md | 1 + .../config/reload-doc-config/index.test.ts | 80 +++++++++++++++++++ 3 files changed, 82 insertions(+), 79 deletions(-) create mode 100644 packages/rstack/tests/config/reload-doc-config/docs/index.md create mode 100644 packages/rstack/tests/config/reload-doc-config/index.test.ts diff --git a/packages/rstack/tests/config/define-doc/index.test.ts b/packages/rstack/tests/config/define-doc/index.test.ts index e60c4453..58ce1fc4 100644 --- a/packages/rstack/tests/config/define-doc/index.test.ts +++ b/packages/rstack/tests/config/define-doc/index.test.ts @@ -1,6 +1,4 @@ -import { writeFile } from 'node:fs/promises'; -import path from 'node:path'; -import { getDistFiles, getFileContent, getRandomPort } from '@rstackjs/test-utils'; +import { getDistFiles, getFileContent } from '@rstackjs/test-utils'; import { test } from '#test-helpers'; const expectedText = 'define.doc works'; @@ -15,79 +13,3 @@ test('should build docs with define.doc config', async ({ prepareDist, execCli, expect(output).toContain(expectedText); }, 30_000); - -test('should restart doc dev server when Rstack config changes', async ({ - execCliAsync, - logHelper, -}) => { - const configFile = path.join(import.meta.dirname, 'test-temp-rstack.config.ts'); - const userWatchFile = path.join(import.meta.dirname, 'test-temp-user-watch.txt'); - - const writeConfig = (title: string) => - writeFile( - configFile, - `import { define } from 'rstack'; - -define.doc({ - root: 'docs', - title: '${title}', - builderConfig: { - dev: { - watchFiles: { - paths: ${JSON.stringify(userWatchFile)}, - type: 'restart', - }, - }, - }, -}); -`, - ); - - await writeFile(userWatchFile, 'initial\n'); - await writeConfig('before config change'); - - execCliAsync(`doc --config test-temp-rstack.config.ts --port ${await getRandomPort()}`); - await logHelper.expectBuildEnd(); - logHelper.clearLogs(); - - await writeConfig('after config change'); - - await logHelper.expectLog('restarting server as test-temp-rstack.config.ts changed'); - await logHelper.expectBuildEnd(); - logHelper.clearLogs(); - - await writeFile(userWatchFile, 'changed\n'); - - await logHelper.expectLog('restarting server as test-temp-user-watch.txt changed'); - await logHelper.expectBuildEnd(); -}, 30_000); - -test('should restart doc dev server when an imported config file changes', async ({ - execCliAsync, - logHelper, -}) => { - const configFile = path.join(import.meta.dirname, 'test-temp-import.config.ts'); - const importedFile = path.join(import.meta.dirname, 'test-temp-imported.ts'); - - await writeFile(importedFile, "export const title = 'before import change';\n"); - await writeFile( - configFile, - `import { define } from 'rstack'; -import { title } from './test-temp-imported.ts'; - -define.doc({ - root: 'docs', - title, -}); -`, - ); - - execCliAsync(`doc --config test-temp-import.config.ts --port ${await getRandomPort()}`); - await logHelper.expectBuildEnd(); - logHelper.clearLogs(); - - await writeFile(importedFile, "export const title = 'after import change';\n"); - - await logHelper.expectLog('restarting server as test-temp-imported.ts changed'); - await logHelper.expectBuildEnd(); -}, 30_000); diff --git a/packages/rstack/tests/config/reload-doc-config/docs/index.md b/packages/rstack/tests/config/reload-doc-config/docs/index.md new file mode 100644 index 00000000..f5a6303d --- /dev/null +++ b/packages/rstack/tests/config/reload-doc-config/docs/index.md @@ -0,0 +1 @@ +# Reload doc config diff --git a/packages/rstack/tests/config/reload-doc-config/index.test.ts b/packages/rstack/tests/config/reload-doc-config/index.test.ts new file mode 100644 index 00000000..5d821101 --- /dev/null +++ b/packages/rstack/tests/config/reload-doc-config/index.test.ts @@ -0,0 +1,80 @@ +import { writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import { getRandomPort } from '@rstackjs/test-utils'; +import { test } from '#test-helpers'; + +test('should restart doc dev server when Rstack config changes', async ({ + execCliAsync, + logHelper, +}) => { + const configFile = path.join(import.meta.dirname, 'test-temp-rstack.config.ts'); + const userWatchFile = path.join(import.meta.dirname, 'test-temp-user-watch.txt'); + + const writeConfig = (title: string) => + writeFile( + configFile, + `import { define } from 'rstack'; + +define.doc({ + root: 'docs', + title: '${title}', + builderConfig: { + dev: { + watchFiles: { + paths: ${JSON.stringify(userWatchFile)}, + type: 'restart', + }, + }, + }, +}); +`, + ); + + await writeFile(userWatchFile, 'initial\n'); + await writeConfig('before config change'); + + execCliAsync(`doc --config test-temp-rstack.config.ts --port ${await getRandomPort()}`); + await logHelper.expectBuildEnd(); + logHelper.clearLogs(); + + await writeConfig('after config change'); + + await logHelper.expectLog('restarting server as test-temp-rstack.config.ts changed'); + await logHelper.expectBuildEnd(); + logHelper.clearLogs(); + + await writeFile(userWatchFile, 'changed\n'); + + await logHelper.expectLog('restarting server as test-temp-user-watch.txt changed'); + await logHelper.expectBuildEnd(); +}, 30_000); + +test('should restart doc dev server when an imported config file changes', async ({ + execCliAsync, + logHelper, +}) => { + const configFile = path.join(import.meta.dirname, 'test-temp-import.config.ts'); + const importedFile = path.join(import.meta.dirname, 'test-temp-imported.ts'); + + await writeFile(importedFile, "export const title = 'before import change';\n"); + await writeFile( + configFile, + `import { define } from 'rstack'; +import { title } from './test-temp-imported.ts'; + +define.doc({ + root: 'docs', + title, +}); +`, + ); + + execCliAsync(`doc --config test-temp-import.config.ts --port ${await getRandomPort()}`); + await logHelper.expectBuildEnd(); + logHelper.clearLogs(); + + await writeFile(importedFile, "export const title = 'after import change';\n"); + + await logHelper.expectLog('restarting server as test-temp-imported.ts changed'); + await logHelper.expectBuildEnd(); +}, 30_000); From b6eb526df1ea62b815ac8d757fa8595fb5e1474b Mon Sep 17 00:00:00 2001 From: neverland Date: Fri, 14 Aug 2026 12:03:47 +0800 Subject: [PATCH 3/3] test: configure shared timeout --- packages/rstack/rstack.config.ts | 1 + packages/rstack/tests/config/define-doc/index.test.ts | 2 +- packages/rstack/tests/config/reload-app-config/index.test.ts | 4 ++-- packages/rstack/tests/config/reload-doc-config/index.test.ts | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/rstack/rstack.config.ts b/packages/rstack/rstack.config.ts index 650c9379..09910407 100644 --- a/packages/rstack/rstack.config.ts +++ b/packages/rstack/rstack.config.ts @@ -11,6 +11,7 @@ define.test(async () => { // Temporary projects may contain files that match Rstest's test glob. exclude: ['**/test-temp-*/**'], extends: withRslibConfig(), + testTimeout: 30_000, source: { tsconfigPath: './tests/tsconfig.json', }, diff --git a/packages/rstack/tests/config/define-doc/index.test.ts b/packages/rstack/tests/config/define-doc/index.test.ts index 58ce1fc4..464e7580 100644 --- a/packages/rstack/tests/config/define-doc/index.test.ts +++ b/packages/rstack/tests/config/define-doc/index.test.ts @@ -12,4 +12,4 @@ test('should build docs with define.doc config', async ({ prepareDist, execCli, const output = getFileContent(files, 'index.html'); expect(output).toContain(expectedText); -}, 30_000); +}); diff --git a/packages/rstack/tests/config/reload-app-config/index.test.ts b/packages/rstack/tests/config/reload-app-config/index.test.ts index cdf62067..a7f9ab93 100644 --- a/packages/rstack/tests/config/reload-app-config/index.test.ts +++ b/packages/rstack/tests/config/reload-app-config/index.test.ts @@ -45,7 +45,7 @@ define.app({ ); await waitForFile(dist2); -}, 30_000); +}); test('should reload config when an imported file changes', async ({ execCliAsync, logHelper }) => { const configFile = path.join(import.meta.dirname, 'test-temp-import.config.ts'); @@ -70,4 +70,4 @@ define.app({ await writeFile(importedFile, '// changed\n'); await logHelper.expectLog('restarting server as test-temp-imported.ts changed'); -}, 30_000); +}); diff --git a/packages/rstack/tests/config/reload-doc-config/index.test.ts b/packages/rstack/tests/config/reload-doc-config/index.test.ts index 5d821101..0b00474b 100644 --- a/packages/rstack/tests/config/reload-doc-config/index.test.ts +++ b/packages/rstack/tests/config/reload-doc-config/index.test.ts @@ -47,7 +47,7 @@ define.doc({ await logHelper.expectLog('restarting server as test-temp-user-watch.txt changed'); await logHelper.expectBuildEnd(); -}, 30_000); +}); test('should restart doc dev server when an imported config file changes', async ({ execCliAsync, @@ -77,4 +77,4 @@ define.doc({ await logHelper.expectLog('restarting server as test-temp-imported.ts changed'); await logHelper.expectBuildEnd(); -}, 30_000); +});