diff --git a/.gitignore b/.gitignore index bda5db4..c411c06 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ # Dist node_modules dist/ +dist-*/ test-results doc_build diff --git a/packages/rstack/src/config.ts b/packages/rstack/src/config.ts index ca479bc..dafd575 100644 --- a/packages/rstack/src/config.ts +++ b/packages/rstack/src/config.ts @@ -1,4 +1,4 @@ -import { loadConfig } from '@rstackjs/load-config'; +import { loadConfig, type LoadConfigResult } from '@rstackjs/load-config'; import type { RsbuildConfigDefinition } from '@rsbuild/core'; import type { RslibConfigDefinition } from '@rslib/core'; import type { RslintConfig } from '@rslint/core'; @@ -18,6 +18,10 @@ export type Configs = { staged?: StagedConfig; }; +type LoadedRstackConfig = Pick & { + configs: Configs; +}; + type ConfigState = { configs: Configs; configPath?: string; @@ -101,12 +105,12 @@ export const define: Define = { staged: (config) => setConfig('staged', config), }; -export const loadRstackConfig = async (): Promise => { +export const loadRstackConfig = async (): Promise => { const state = getConfigState(); state.configs = {}; try { - await loadConfig({ + const { filePath, dependencies } = await loadConfig({ loader: 'native', exportName: false, fresh: true, @@ -122,7 +126,11 @@ export const loadRstackConfig = async (): Promise => { }), }); - return state.configs; + return { + configs: state.configs, + filePath, + dependencies, + }; } finally { state.configs = {}; } diff --git a/packages/rstack/src/rsbuildConfig.ts b/packages/rstack/src/rsbuildConfig.ts index e6d32c8..1dcc716 100644 --- a/packages/rstack/src/rsbuildConfig.ts +++ b/packages/rstack/src/rsbuildConfig.ts @@ -1,4 +1,4 @@ -import type { RsbuildConfigDefinition, ConfigParams } from '@rsbuild/core'; +import { mergeRsbuildConfig, type RsbuildConfigDefinition, type ConfigParams } from '@rsbuild/core'; import { loadRstackConfig, type Configs } from './config.js'; const resolveRsbuildConfig = async (configs: Configs, params: ConfigParams) => { @@ -13,8 +13,21 @@ const resolveRsbuildConfig = async (configs: Configs, params: ConfigParams) => { }; const loadRsbuildConfig: RsbuildConfigDefinition = async (params) => { - const configs = await loadRstackConfig(); - return resolveRsbuildConfig(configs, params); + const { configs, filePath, dependencies } = await loadRstackConfig(); + const config = await resolveRsbuildConfig(configs, params); + + if (!filePath) { + return config; + } + + return mergeRsbuildConfig(config, { + dev: { + watchFiles: { + paths: [filePath, ...dependencies], + type: 'reload-server', + }, + }, + }); }; export default loadRsbuildConfig; diff --git a/packages/rstack/src/rslibConfig.ts b/packages/rstack/src/rslibConfig.ts index 4666398..4681d9d 100644 --- a/packages/rstack/src/rslibConfig.ts +++ b/packages/rstack/src/rslibConfig.ts @@ -14,7 +14,7 @@ const resolveRslibConfig = async (configs: Configs, params: ConfigParams): Promi }; const loadRslibConfig = (async (params: ConfigParams) => { - const configs = await loadRstackConfig(); + const { configs } = await loadRstackConfig(); return resolveRslibConfig(configs, params); }) as RslibConfigDefinition; diff --git a/packages/rstack/src/rslintConfig.ts b/packages/rstack/src/rslintConfig.ts index ff9851c..aea6340 100644 --- a/packages/rstack/src/rslintConfig.ts +++ b/packages/rstack/src/rslintConfig.ts @@ -1,7 +1,7 @@ import { loadRstackConfig } from './config.js'; import type { RslintConfig } from '@rslint/core'; -const configs = await loadRstackConfig(); +const { configs } = await loadRstackConfig(); const lintExports = configs.lint ?? []; let lintConfig: RslintConfig; diff --git a/packages/rstack/src/rspressConfig.ts b/packages/rstack/src/rspressConfig.ts index 65c78bc..6c97bf4 100644 --- a/packages/rstack/src/rspressConfig.ts +++ b/packages/rstack/src/rspressConfig.ts @@ -13,6 +13,6 @@ const resolveRspressConfig = async (configs: Configs): Promise => { }; export default async (): Promise => { - const configs = await loadRstackConfig(); + const { configs } = await loadRstackConfig(); return resolveRspressConfig(configs); }; diff --git a/packages/rstack/src/rstestConfig.ts b/packages/rstack/src/rstestConfig.ts index e375063..7c3ed41 100644 --- a/packages/rstack/src/rstestConfig.ts +++ b/packages/rstack/src/rstestConfig.ts @@ -56,7 +56,7 @@ const resolveRstestConfig = async (configs: Configs) => { }; const loadRstestConfig = (async (params: ConfigParams) => { - const configs = await loadRstackConfig(); + const { configs } = await loadRstackConfig(); const testConfig = await resolveRstestConfig(configs); return extendsConfig(configs, testConfig, params); }) as RstestConfigExport; diff --git a/packages/rstack/src/staged.ts b/packages/rstack/src/staged.ts index c45513a..c0af58c 100644 --- a/packages/rstack/src/staged.ts +++ b/packages/rstack/src/staged.ts @@ -65,7 +65,7 @@ export async function runStagedCLI(args: string[]): Promise { return; } - const configs = await loadRstackConfig(); + const { configs } = await loadRstackConfig(); const stagedConfig = configs.staged; if (!stagedConfig) { throw new Error( diff --git a/packages/rstack/test/config/reload-app-config/index.test.ts b/packages/rstack/test/config/reload-app-config/index.test.ts new file mode 100644 index 0000000..b3c8687 --- /dev/null +++ b/packages/rstack/test/config/reload-app-config/index.test.ts @@ -0,0 +1,50 @@ +import { rm, writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import { expectFile, getRandomPort, test } from '#test-helpers'; + +test('should restart dev server and reload config when Rstack config changes', async ({ + execCliAsync, +}) => { + const dist1 = path.join(import.meta.dirname, 'dist'); + const dist2 = path.join(import.meta.dirname, 'dist-2'); + const configFile = path.join(import.meta.dirname, 'test-temp-rstack.config.ts'); + + await rm(dist1, { recursive: true, force: true }); + await rm(dist2, { recursive: true, force: true }); + await rm(configFile, { force: true }); + + await writeFile( + configFile, + `import { define } from 'rstack'; + +define.app({ + dev: { + writeToDisk: true, + }, + server: { port: ${await getRandomPort()} }, +}); +`, + ); + + execCliAsync('dev --config test-temp-rstack.config.ts'); + + await expectFile(dist1); + + await writeFile( + configFile, + `import { define } from 'rstack'; + +define.app({ + dev: { + writeToDisk: true, + }, + output: { + distPath: 'dist-2', + }, + server: { port: ${await getRandomPort()} }, +}); +`, + ); + + await expectFile(dist2); +}, 30_000); diff --git a/packages/rstack/test/config/reload-app-config/src/index.js b/packages/rstack/test/config/reload-app-config/src/index.js new file mode 100644 index 0000000..ddc67c9 --- /dev/null +++ b/packages/rstack/test/config/reload-app-config/src/index.js @@ -0,0 +1 @@ +console.log('hello!');