Skip to content

Commit

Permalink
feat: allow to use port placeholder in client.port (#2641)
Browse files Browse the repository at this point in the history
  • Loading branch information
chenjiahan authored Jun 20, 2024
1 parent b4ed6c1 commit 552facf
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 38 deletions.
79 changes: 47 additions & 32 deletions e2e/cases/server/hmr/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ import fs from 'node:fs';
import { join } from 'node:path';
import { dev, getRandomPort, gotoPage, rspackOnlyTest } from '@e2e/helper';
import { expect, test } from '@playwright/test';
import { pluginReact } from '@rsbuild/plugin-react';

const cwd = __dirname;

// hmr test will timeout in CI
rspackOnlyTest('default & hmr (default true)', async ({ page }) => {
rspackOnlyTest('HMR should work by default', async ({ page }) => {
// HMR cases will fail in Windows
if (process.platform === 'win32') {
test.skip();
Expand All @@ -19,18 +17,12 @@ rspackOnlyTest('default & hmr (default true)', async ({ page }) => {

const rsbuild = await dev({
cwd,
plugins: [pluginReact()],
rsbuildConfig: {
source: {
entry: {
index: join(cwd, 'test-temp-src/index.ts'),
},
},
output: {
distPath: {
root: 'dist-hmr',
},
},
dev: {
client: {
host: '',
Expand Down Expand Up @@ -58,7 +50,7 @@ rspackOnlyTest('default & hmr (default true)', async ({ page }) => {

await expect(locator).toHaveText('Hello Test!');

// #test-keep should unchanged when app.tsx hmr
// #test-keep should unchanged when app.tsx HMR
await expect(locatorKeep.innerHTML()).resolves.toBe(keepNum);

const cssPath = join(cwd, 'test-temp-src/App.css');
Expand All @@ -71,20 +63,6 @@ rspackOnlyTest('default & hmr (default true)', async ({ page }) => {
);

await expect(locator).toHaveCSS('color', 'rgb(0, 0, 255)');

// restore
await fs.promises.writeFile(
appPath,
fs.readFileSync(appPath, 'utf-8').replace('Hello Test', 'Hello Rsbuild'),
);

await fs.promises.writeFile(
cssPath,
`#test {
color: rgb(255, 0, 0);
}`,
);

await rsbuild.close();
});

Expand All @@ -103,18 +81,12 @@ rspackOnlyTest(
const port = await getRandomPort();
const rsbuild = await dev({
cwd,
plugins: [pluginReact()],
rsbuildConfig: {
source: {
entry: {
index: join(cwd, 'test-temp-src-1/index.ts'),
},
},
output: {
distPath: {
root: 'dist-hmr-1',
},
},
server: {
port,
},
Expand All @@ -140,13 +112,56 @@ rspackOnlyTest(
);

await expect(locator).toHaveText('Hello Test!');
await rsbuild.close();
},
);

rspackOnlyTest(
'hmr should work when dev.port is `<port>`',
async ({ page }) => {
// HMR cases will fail in Windows
if (process.platform === 'win32') {
test.skip();
}

await fs.promises.cp(join(cwd, 'src'), join(cwd, 'test-temp-src-2'), {
recursive: true,
});

const port = await getRandomPort();
const rsbuild = await dev({
cwd,
rsbuildConfig: {
source: {
entry: {
index: join(cwd, 'test-temp-src-2/index.ts'),
},
},
server: {
port,
},
dev: {
client: {
port: '<port>',
},
},
},
});

await gotoPage(page, rsbuild);
expect(rsbuild.port).toBe(port);

const appPath = join(cwd, 'test-temp-src-2/App.tsx');

const locator = page.locator('#test');
await expect(locator).toHaveText('Hello Rsbuild!');

// restore
await fs.promises.writeFile(
appPath,
fs.readFileSync(appPath, 'utf-8').replace('Hello Test', 'Hello Rsbuild'),
fs.readFileSync(appPath, 'utf-8').replace('Hello Rsbuild', 'Hello Test'),
);

await expect(locator).toHaveText('Hello Test!');
await rsbuild.close();
},
);
21 changes: 17 additions & 4 deletions packages/core/src/server/devServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import { ROOT_DIST_DIR } from '../constants';
import { getNodeEnv, isMultiCompiler, setNodeEnv } from '../helpers';
import { logger } from '../logger';
import type { CreateDevMiddlewareReturns } from '../provider/createCompiler';
import type { InternalContext, NormalizedConfig } from '../types';
import type {
InternalContext,
NormalizedConfig,
NormalizedDevConfig,
} from '../types';
import {
type RsbuildDevMiddlewareOptions,
getMiddlewares,
Expand Down Expand Up @@ -72,6 +76,14 @@ export type RsbuildDevServer = {
close: () => Promise<void>;
};

const formatDevConfig = (config: NormalizedDevConfig, port: number) => {
// replace port placeholder
if (config.client.port === '<port>') {
config.client.port = String(port);
}
return config;
};

export async function createDevServer<
Options extends {
context: InternalContext;
Expand Down Expand Up @@ -99,6 +111,7 @@ export async function createDevServer<
config,
getPortSilently,
});
const devConfig = formatDevConfig(config.dev, port);

const routes = formatRoutes(
options.context.entry,
Expand Down Expand Up @@ -129,7 +142,7 @@ export async function createDevServer<

// create dev middleware instance
const compilerDevMiddleware = new CompilerDevMiddleware({
dev: config.dev,
dev: devConfig,
server: config.server,
publicPaths: publicPaths,
devMiddleware,
Expand Down Expand Up @@ -179,15 +192,15 @@ export async function createDevServer<
const compileMiddlewareAPI = runCompile ? await startCompile() : undefined;

const fileWatcher = await setupWatchFiles({
dev: config.dev,
dev: devConfig,
server: config.server,
compileMiddlewareAPI,
});

const devMiddlewares = await getMiddlewares({
pwd: options.context.rootPath,
compileMiddlewareAPI,
dev: config.dev,
dev: devConfig,
server: config.server,
output: {
distPath: config.output.distPath.root || ROOT_DIST_DIR,
Expand Down
20 changes: 20 additions & 0 deletions website/docs/en/config/dev/client.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,26 @@ export default {
protocol: 'ws',
// Usually `127.0.0.1` is used to avoid cross-origin requests being blocked by the browser
host: '127.0.0.1',
port: 3000,
},
},
};
```

### Port placeholder

The port number that Rsbuild server listens on may change. For example, if the port is in use, Rsbuild will automatically increment the port number until it finds an available port.

To avoid `client.port` becoming invalid due to port changes, you can use one of the following methods:

- Enable [server.strictPort](/config/server/strict-port).
- Use the `<port>` placeholder to refer to the current port number. Rsbuild will replace the placeholder with the actual port number it is listening on.

```js title="rsbuild.config.ts"
export default {
dev: {
client: {
port: '<port>',
},
},
};
Expand Down
7 changes: 6 additions & 1 deletion website/docs/en/config/server/open.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ export default {

### Port placeholder

Since the port number may change, you can use the `<port>` placeholder to refer to the current port number, and Rsbuild will automatically replace the placeholder with the actual listening port number.
The port number that Rsbuild server listens on may change. For example, if the port is in use, Rsbuild will automatically increment the port number until it finds an available port.

To avoid `server.open` becoming invalid due to port changes, you can use one of the following methods:

- Enable [server.strictPort](/config/server/strict-port).
- Use the `<port>` placeholder to refer to the current port number. Rsbuild will replace the placeholder with the actual port number it is listening on.

```js
export default {
Expand Down
20 changes: 20 additions & 0 deletions website/docs/zh/config/dev/client.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,26 @@ export default {
protocol: 'ws',
// 通常使用 `127.0.0.1`,可以避免跨域请求被浏览器拦截
host: '127.0.0.1',
port: 3000,
},
},
};
```

### 端口号占位符

Rsbuild server 监听的端口号可能会发生变更。比如,当端口被占用时,Rsbuild 会自动递增端口号,直至找到一个可用端口。

为了避免端口变化导致 `client.port` 失效,你可以使用以下方法之一:

- 开启 [server.strictPort](/config/server/strict-port)
- 使用 `<port>` 占位符来指代当前端口号,Rsbuild 会将占位符替换为实际监听的端口号。

```js title="rsbuild.config.ts"
export default {
dev: {
client: {
port: '<port>',
},
},
};
Expand Down
7 changes: 6 additions & 1 deletion website/docs/zh/config/server/open.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ export default {

### 端口号占位符

由于端口号可能会发生变动,你可以使用 `<port>` 占位符来指代当前端口号,Rsbuild 会自动将占位符替换为实际监听的端口号。
Rsbuild server 监听的端口号可能会发生变更。比如,当端口被占用时,Rsbuild 会自动递增端口号,直至找到一个可用端口。

为了避免端口变化导致 `server.open` 失效,你可以使用以下方法之一:

- 开启 [server.strictPort](/config/server/strict-port)
- 使用 `<port>` 占位符来指代当前端口号,Rsbuild 会将占位符替换为实际监听的端口号。

```js
export default {
Expand Down

0 comments on commit 552facf

Please sign in to comment.