From fef864e0bcb2eb7b47759374ca4d142864f00a09 Mon Sep 17 00:00:00 2001 From: Qingyu Wang <40660121+colinaaa@users.noreply.github.com> Date: Wed, 2 Apr 2025 21:57:46 +0800 Subject: [PATCH 1/2] feat(rspeedy/core): add `dev.hmr` and `dev.liveReload` --- .changeset/sweet-crabs-travel.md | 5 ++ packages/rspeedy/core/etc/rspeedy.api.md | 2 + packages/rspeedy/core/src/config/dev/index.ts | 82 +++++++++++++++++++ .../rspeedy/core/src/plugins/dev.plugin.ts | 2 +- .../rspeedy/core/test/config/dev.test-d.ts | 10 +++ .../core/test/plugins/dev.plugin.test.ts | 82 +++++++++++++++++++ 6 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 .changeset/sweet-crabs-travel.md diff --git a/.changeset/sweet-crabs-travel.md b/.changeset/sweet-crabs-travel.md new file mode 100644 index 0000000000..dc73d6ca94 --- /dev/null +++ b/.changeset/sweet-crabs-travel.md @@ -0,0 +1,5 @@ +--- +"@lynx-js/rspeedy": patch +--- + +Support `dev.hmr` and `dev.liveReload`. diff --git a/packages/rspeedy/core/etc/rspeedy.api.md b/packages/rspeedy/core/etc/rspeedy.api.md index 3aea6d9872..b40a69f2d9 100644 --- a/packages/rspeedy/core/etc/rspeedy.api.md +++ b/packages/rspeedy/core/etc/rspeedy.api.md @@ -134,6 +134,8 @@ export function defineConfig(config: Config): Config; export interface Dev { assetPrefix?: string | boolean | undefined; client?: DevClient | undefined; + hmr?: boolean | undefined; + liveReload?: boolean | undefined; progressBar?: boolean | { id?: string; } | undefined; diff --git a/packages/rspeedy/core/src/config/dev/index.ts b/packages/rspeedy/core/src/config/dev/index.ts index d32d35235a..6764ce0bb2 100644 --- a/packages/rspeedy/core/src/config/dev/index.ts +++ b/packages/rspeedy/core/src/config/dev/index.ts @@ -75,6 +75,88 @@ export interface Dev { */ client?: Client | undefined + /** + * Whether to enable Hot Module Replacement (HMR). + * + * @remarks + * + * Defaults to `true`. + * + * By default, Rspeedy uses HMR as the preferred method to update modules. If HMR is disabled or cannot be used in certain scenarios, it will automatically fallback to {@link Dev.liveReload}. + * + * To completely disable both HMR and live reload, set both `dev.hmr` and `dev.liveReload` to `false`. Then, no WebSocket requests will be made to the dev server on the page, and the page will not automatically refresh when file change. + * + * @example + * + * Disable HMR: + * + * ```js + * import { defineConfig } from '@lynx-js/rspeedy' + * + * export default defineConfig({ + * dev: { + * hmr: false, + * }, + * }) + * ``` + * + * @example + * + * Disable both HMR and live reload: + * + * ```js + * import { defineConfig } from '@lynx-js/rspeedy' + * + * export default defineConfig({ + * dev: { + * hmr: false, + * liveReload: false, + * }, + * }) + * ``` + */ + hmr?: boolean | undefined + + /** + * Whether to enable live reload functionality. + * + * Defaults to `true`. + * + * Live reload is used as a fallback when {@link Dev.hmr} is disabled or cannot be used in certain scenarios. When enabled, the page will automatically refresh when source files are changed. + * + * To completely disable both HMR and live reload, set both `dev.hmr` and `dev.liveReload` to `false`. Then, no WebSocket requests will be made to the dev server on the page, and the page will not automatically refresh when file change. + * + * @example + * + * Disable live reload: + * + * ```js + * import { defineConfig } from '@lynx-js/rspeedy' + * + * export default defineConfig({ + * dev: { + * liveReload: false, + * }, + * }) + * ``` + * + * @example + * + * Disable both HMR and live reload: + * + * ```js + * import { defineConfig } from '@lynx-js/rspeedy' + * + * export default defineConfig({ + * dev: { + * hmr: false, + * liveReload: false, + * }, + * }) + * ``` + */ + liveReload?: boolean | undefined + /** * Watch specified files and directories for changes. When a file change is detected, it can trigger a page reload or restart the dev server. * diff --git a/packages/rspeedy/core/src/plugins/dev.plugin.ts b/packages/rspeedy/core/src/plugins/dev.plugin.ts index b35b56d76c..1374f60056 100644 --- a/packages/rspeedy/core/src/plugins/dev.plugin.ts +++ b/packages/rspeedy/core/src/plugins/dev.plugin.ts @@ -116,7 +116,7 @@ export function pluginDev( hostname }&port=${ api.context.devServer?.port - }&pathname=/rsbuild-hmr&hot=true&live-reload=true&protocol=ws` + }&pathname=/rsbuild-hmr&hot=${options?.hmr ?? true}&live-reload=${options?.liveReload ?? true}&protocol=ws` ) .set( '@rspack/core/hot/dev-server', diff --git a/packages/rspeedy/core/test/config/dev.test-d.ts b/packages/rspeedy/core/test/config/dev.test-d.ts index a73b9de685..428b6ada3b 100644 --- a/packages/rspeedy/core/test/config/dev.test-d.ts +++ b/packages/rspeedy/core/test/config/dev.test-d.ts @@ -34,6 +34,16 @@ describe('Config - Dev', () => { }) }) + test('hmr', () => { + assertType({ hmr: true }) + assertType({ hmr: false }) + }) + + test('liveReload', () => { + assertType({ liveReload: true }) + assertType({ liveReload: false }) + }) + test('watchFiles', () => { assertType({ watchFiles: { paths: '' } }) assertType({ watchFiles: { paths: [] } }) diff --git a/packages/rspeedy/core/test/plugins/dev.plugin.test.ts b/packages/rspeedy/core/test/plugins/dev.plugin.test.ts index a6bbb30b24..ab2a7486bd 100644 --- a/packages/rspeedy/core/test/plugins/dev.plugin.test.ts +++ b/packages/rspeedy/core/test/plugins/dev.plugin.test.ts @@ -356,6 +356,88 @@ describe('Plugins - Dev', () => { expect(config.output?.publicPath).not.toBe(`http://example.com:${port}`) }) + test('dev.hmr default', async () => { + const rsbuild = await createStubRspeedy({}) + + const config = await rsbuild.unwrapConfig() + + expect(config.resolve?.alias).toHaveProperty( + '@lynx-js/webpack-dev-transport/client', + expect.stringContaining('hot=true'), + ) + }) + + test('dev.hmr: false', async () => { + const rsbuild = await createStubRspeedy({ + dev: { + hmr: false, + }, + }) + + const config = await rsbuild.unwrapConfig() + + expect(config.resolve?.alias).toHaveProperty( + '@lynx-js/webpack-dev-transport/client', + expect.stringContaining('hot=false'), + ) + }) + + test('dev.hmr: true', async () => { + const rsbuild = await createStubRspeedy({ + dev: { + hmr: true, + }, + }) + + const config = await rsbuild.unwrapConfig() + + expect(config.resolve?.alias).toHaveProperty( + '@lynx-js/webpack-dev-transport/client', + expect.stringContaining('hot=true'), + ) + }) + + test('dev.liveReload default', async () => { + const rsbuild = await createStubRspeedy({}) + + const config = await rsbuild.unwrapConfig() + + expect(config.resolve?.alias).toHaveProperty( + '@lynx-js/webpack-dev-transport/client', + expect.stringContaining('live-reload=true'), + ) + }) + + test('dev.liveReload: false', async () => { + const rsbuild = await createStubRspeedy({ + dev: { + liveReload: false, + }, + }) + + const config = await rsbuild.unwrapConfig() + + expect(config.resolve?.alias).toHaveProperty( + '@lynx-js/webpack-dev-transport/client', + expect.stringContaining('live-reload=false'), + ) + }) + + test('dev.liveReload: true', async () => { + const rsbuild = await createStubRspeedy({ + dev: { + liveReload: true, + }, + }) + + const config = await rsbuild.unwrapConfig() + + expect(config.resolve?.alias).toHaveProperty( + '@lynx-js/webpack-dev-transport/client', + expect.stringContaining('live-reload=true'), + ) + }) + test('websocketTransport', async () => { const rsbuild = await createStubRspeedy({ dev: { From 683e0080912f0693487789e6565aef4a31e209fd Mon Sep 17 00:00:00 2001 From: Qingyu Wang <40660121+colinaaa@users.noreply.github.com> Date: Thu, 3 Apr 2025 11:52:46 +0800 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Yradex <11014207+Yradex@users.noreply.github.com> Signed-off-by: Qingyu Wang <40660121+colinaaa@users.noreply.github.com> --- packages/rspeedy/core/src/config/dev/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rspeedy/core/src/config/dev/index.ts b/packages/rspeedy/core/src/config/dev/index.ts index 6764ce0bb2..8fbf122975 100644 --- a/packages/rspeedy/core/src/config/dev/index.ts +++ b/packages/rspeedy/core/src/config/dev/index.ts @@ -84,7 +84,7 @@ export interface Dev { * * By default, Rspeedy uses HMR as the preferred method to update modules. If HMR is disabled or cannot be used in certain scenarios, it will automatically fallback to {@link Dev.liveReload}. * - * To completely disable both HMR and live reload, set both `dev.hmr` and `dev.liveReload` to `false`. Then, no WebSocket requests will be made to the dev server on the page, and the page will not automatically refresh when file change. + * To completely disable both HMR and live reload, set both `dev.hmr` and `dev.liveReload` to `false`. Then, no WebSocket requests will be made to the dev server on the page, and the page will not automatically refresh when file changes. * * @example * @@ -124,7 +124,7 @@ export interface Dev { * * Live reload is used as a fallback when {@link Dev.hmr} is disabled or cannot be used in certain scenarios. When enabled, the page will automatically refresh when source files are changed. * - * To completely disable both HMR and live reload, set both `dev.hmr` and `dev.liveReload` to `false`. Then, no WebSocket requests will be made to the dev server on the page, and the page will not automatically refresh when file change. + * To completely disable both HMR and live reload, set both `dev.hmr` and `dev.liveReload` to `false`. Then, no WebSocket requests will be made to the dev server on the page, and the page will not automatically refresh when file changes. * * @example *