Skip to content

Commit

Permalink
feat: add basic server environment api (#2714)
Browse files Browse the repository at this point in the history
  • Loading branch information
9aoy authored Jun 27, 2024
1 parent d060c6a commit f1bb814
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 1 deletion.
53 changes: 53 additions & 0 deletions e2e/cases/server/environments/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,59 @@ test('should serve multiple environments correctly', async ({ page }) => {
await rsbuild.close();
});

test('server environment api', async ({ page }) => {
let assertionsCount = 0;

const rsbuild = await dev({
cwd,
rsbuildConfig: {
dev: {
setupMiddlewares: [
(middlewares, server) => {
middlewares.unshift(async (req, _res, next) => {
if (req.url === '/') {
const webStats = await server.environments.web.getStats();

expect(webStats.toJson().name).toBe('web');

assertionsCount++;
const web1Stats = await server.environments.web1.getStats();

expect(web1Stats.toJson().name).toBe('web1');
assertionsCount++;
}

next();
});
},
],
},
environments: {
web: {},
web1: {
source: {
entry: {
main: './src/web1.js',
},
},
output: {
distPath: {
root: 'dist/web1',
html: 'html1',
},
},
},
},
},
});

await page.goto(`http://localhost:${rsbuild.port}`);

expect(assertionsCount).toBe(2);

await rsbuild.close();
});

// TODO: not support serve multiple environments when distPath different
test.skip('serve multiple environments correctly when distPath different', async ({
page,
Expand Down
42 changes: 42 additions & 0 deletions packages/core/src/server/devServer.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import fs from 'node:fs';
import type {
CreateDevServerOptions,
EnvironmentAPI,
Rspack,
StartDevServerOptions,
Stats,
} from '@rsbuild/shared';
import type Connect from 'connect';
import { ROOT_DIST_DIR } from '../constants';
Expand Down Expand Up @@ -50,6 +52,9 @@ export type RsbuildDevServer = {

/** The following APIs will be used when you use a custom server */

/** The Rsbuild server environment API */
environments: EnvironmentAPI;

/**
* The resolved port.
*
Expand Down Expand Up @@ -127,6 +132,24 @@ export async function createDevServer<

let outputFileSystem: Rspack.OutputFileSystem = fs;

let lastStats: Stats[];

// should register onDevCompileDone hook before startCompile
const waitFirstCompileDone = runCompile
? new Promise<void>((resolve) => {
options.context.hooks.onDevCompileDone.tap(
({ stats, isFirstCompile }) => {
lastStats = 'stats' in stats ? stats.stats : [stats];

if (!isFirstCompile) {
return;
}
resolve();
},
);
})
: Promise.resolve();

const startCompile: () => Promise<
RsbuildDevMiddlewareOptions['compileMiddlewareAPI']
> = async () => {
Expand Down Expand Up @@ -197,11 +220,29 @@ export async function createDevServer<
compileMiddlewareAPI,
});

const environmentAPI = Object.fromEntries(
Object.keys(options.context.environments).map((name, index) => {
return [
name,
{
getStats: async () => {
if (!runCompile) {
throw new Error("can't get stats info when runCompile is false");
}
await waitFirstCompileDone;
return lastStats[index];
},
},
];
}),
);

const devMiddlewares = await getMiddlewares({
pwd: options.context.rootPath,
compileMiddlewareAPI,
dev: devConfig,
server: config.server,
environments: environmentAPI,
output: {
distPath: options.context.distPath || ROOT_DIST_DIR,
},
Expand All @@ -223,6 +264,7 @@ export async function createDevServer<
port,
middlewares,
outputFileSystem,
environments: environmentAPI,
listen: async () => {
const httpServer = await createHttpServer({
serverConfig: config.server,
Expand Down
7 changes: 6 additions & 1 deletion packages/core/src/server/getDevMiddlewares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { isAbsolute, join } from 'node:path';
import url from 'node:url';
import type {
DevConfig,
EnvironmentAPI,
RequestHandler,
Rspack,
ServerAPIs,
Expand All @@ -27,6 +28,7 @@ export type RsbuildDevMiddlewareOptions = {
pwd: string;
dev: DevConfig;
server: ServerConfig;
environments: EnvironmentAPI;
compileMiddlewareAPI?: CompileMiddlewareAPI;
outputFileSystem: Rspack.OutputFileSystem;
output: {
Expand All @@ -36,12 +38,14 @@ export type RsbuildDevMiddlewareOptions = {

const applySetupMiddlewares = (
dev: RsbuildDevMiddlewareOptions['dev'],
environments: EnvironmentAPI,
compileMiddlewareAPI?: CompileMiddlewareAPI,
) => {
const setupMiddlewares = dev.setupMiddlewares || [];

const serverOptions: ServerAPIs = {
sockWrite: (type, data) => compileMiddlewareAPI?.sockWrite(type, data),
environments,
};

const before: RequestHandler[] = [];
Expand Down Expand Up @@ -201,7 +205,7 @@ export const getMiddlewares = async (
middlewares: Middlewares;
}> => {
const middlewares: Middlewares = [];
const { compileMiddlewareAPI } = options;
const { environments, compileMiddlewareAPI } = options;

if (logger.level === 'verbose') {
middlewares.push(await getRequestLoggerMiddleware());
Expand All @@ -210,6 +214,7 @@ export const getMiddlewares = async (
// Order: setupMiddlewares.unshift => internal middlewares => setupMiddlewares.push
const { before, after } = applySetupMiddlewares(
options.dev,
environments,
compileMiddlewareAPI,
);

Expand Down
8 changes: 8 additions & 0 deletions packages/shared/src/types/config/dev.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { IncomingMessage, ServerResponse } from 'node:http';
import type { WatchOptions } from '../../../compiled/chokidar/index.js';
import type { Rspack } from '../rspack';
import type { Stats } from '../stats';

export type ProgressBarConfig = {
id?: string;
Expand All @@ -14,11 +15,18 @@ export type RequestHandler = (
next: NextFunction,
) => void;

export type EnvironmentAPI = {
[name: string]: {
getStats: () => Promise<Stats>;
};
};

export type ServerAPIs = {
sockWrite: (
type: string,
data?: string | boolean | Record<string, any>,
) => void;
environments: EnvironmentAPI;
};

export type ClientConfig = {
Expand Down
25 changes: 25 additions & 0 deletions website/docs/en/config/dev/setup-middlewares.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ type ServerAPIs = {
type: string,
data?: string | boolean | Record<string, any>,
) => void;
environments: {
[name: string]: {
getStats: () => Promise<Stats>;
};
};
};

type SetupMiddlewares = Array<
Expand Down Expand Up @@ -63,3 +68,23 @@ export default {
},
};
```

- environments. Allow operations in the specified environment.

```ts
export default {
dev: {
setupMiddlewares: [
(middlewares, server) => {
middlewares.unshift(async (req, _res, next) => {
const webStats = await server.environments.web.getStats();

console.log(webStats.toJson({ all: false }));

next();
});
},
],
},
};
```
25 changes: 25 additions & 0 deletions website/docs/zh/config/dev/setup-middlewares.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ type ServerAPIs = {
type: string,
data?: string | boolean | Record<string, any>,
) => void;
environments: {
[name: string]: {
getStats: () => Promise<Stats>;
};
};
};

type SetupMiddlewares = Array<
Expand Down Expand Up @@ -63,3 +68,23 @@ export default {
},
};
```

- environments。允许对指定的 environment 产物进行操作。

```ts
export default {
dev: {
setupMiddlewares: [
(middlewares, server) => {
middlewares.unshift(async (req, _res, next) => {
const webStats = await server.environments.web.getStats();

console.log(webStats.toJson({ all: false }));

next();
});
},
],
},
};
```

0 comments on commit f1bb814

Please sign in to comment.