Skip to content

Commit

Permalink
feat: add stats to the return value of rsbuild.build (#3325)
Browse files Browse the repository at this point in the history
  • Loading branch information
chenjiahan authored Aug 30, 2024
1 parent 38f3dda commit 601f295
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 68 deletions.
4 changes: 2 additions & 2 deletions e2e/cases/plugin-api/plugin-hooks-watch/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ rspackOnlyTest(
},
});

const watching = await rsbuild.build({ watch: true });
const result = await rsbuild.build({ watch: true });

await fs.promises.writeFile(filePath, "console.log('2');");

Expand All @@ -113,6 +113,6 @@ rspackOnlyTest(
'AfterBuild',
]);

await watching?.close();
await result.close?.();
},
);
50 changes: 25 additions & 25 deletions packages/compat/webpack/src/build.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { logger } from '@rsbuild/core';
import type { BuildOptions, Rspack } from '@rsbuild/core';
import type { Build, BuildOptions, Rspack } from '@rsbuild/core';
import type { Configuration as WebpackConfig } from 'webpack';
import WebpackMultiStats from 'webpack/lib/MultiStats.js';
import { createCompiler } from './createCompiler';
Expand All @@ -9,9 +9,7 @@ import { registerBuildHook } from './shared';
export const build = async (
initOptions: InitConfigsOptions,
{ watch, compiler: customCompiler }: BuildOptions = {},
): Promise<void | {
close: () => Promise<void>;
}> => {
): Promise<ReturnType<Build>> => {
const { context } = initOptions;

let compiler: Rspack.Compiler | Rspack.MultiCompiler;
Expand Down Expand Up @@ -47,26 +45,28 @@ export const build = async (
};
}

await new Promise<{ stats: Rspack.Stats | Rspack.MultiStats }>(
(resolve, reject) => {
compiler.run((err, stats) => {
if (err || stats?.hasErrors()) {
const buildError = err || new Error('Webpack build failed!');
reject(buildError);
}
// If there is a compilation error, the close method should not be called.
// Otherwise bundler may generate an invalid cache.
else {
// When using run or watch, call close and wait for it to finish before calling run or watch again.
// Concurrent compilations will corrupt the output files.
compiler.close((closeErr) => {
closeErr && logger.error(closeErr);
const { stats } = await new Promise<{
stats?: Rspack.Stats | Rspack.MultiStats;
}>((resolve, reject) => {
compiler.run((err, stats) => {
if (err) {
reject(err);
} else if (stats?.hasErrors()) {
reject(new Error('Rspack build failed!'));
}
// If there is a compilation error, the close method should not be called.
// Otherwise bundler may generate an invalid cache.
else {
// When using run or watch, call close and wait for it to finish before calling run or watch again.
// Concurrent compilations will corrupt the output files.
compiler.close((closeErr) => {
closeErr && logger.error(closeErr);

resolve({ stats });
});
}
});
});

// Assert type of stats must align to compiler.
resolve({ stats: stats as any });
});
}
});
},
);
return { stats };
};
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type {
AppIcon,
AppIconItem,
AliasStrategy,
Build,
BuildOptions,
BundlerPluginInstance,
CacheGroup,
Expand Down
54 changes: 27 additions & 27 deletions packages/core/src/provider/build.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { rspack } from '@rspack/core';
import { registerBuildHook } from '../hooks';
import { logger } from '../logger';
import type { BuildOptions, Rspack } from '../types';
import type { Build, BuildOptions, Rspack } from '../types';
import { createCompiler } from './createCompiler';
import type { InitConfigsOptions } from './initConfigs';

export const build = async (
initOptions: InitConfigsOptions,
{ watch, compiler: customCompiler }: BuildOptions = {},
): Promise<void | {
close: () => Promise<void>;
}> => {
): Promise<ReturnType<Build>> => {
const { context } = initOptions;

let compiler: Rspack.Compiler | Rspack.MultiCompiler;
Expand Down Expand Up @@ -46,28 +44,30 @@ export const build = async (
};
}

await new Promise<{ stats?: Rspack.Stats | Rspack.MultiStats }>(
(resolve, reject) => {
compiler.run((err, stats?: Rspack.Stats | Rspack.MultiStats) => {
if (err || stats?.hasErrors()) {
const buildError = err || new Error('Rspack build failed!');
reject(buildError);
}
// If there is a compilation error, the close method should not be called.
// Otherwise the bundler may generate an invalid cache.
else {
// When using run or watch, call close and wait for it to finish before calling run or watch again.
// Concurrent compilations will corrupt the output files.
compiler.close((closeErr) => {
if (closeErr) {
logger.error(closeErr);
}
const { stats } = await new Promise<{
stats?: Rspack.Stats | Rspack.MultiStats;
}>((resolve, reject) => {
compiler.run((err, stats) => {
if (err) {
reject(err);
} else if (stats?.hasErrors()) {
reject(new Error('Rspack build failed!'));
}
// If there is a compilation error, the close method should not be called.
// Otherwise the bundler may generate an invalid cache.
else {
// When using run or watch, call close and wait for it to finish before calling run or watch again.
// Concurrent compilations will corrupt the output files.
compiler.close((closeErr) => {
if (closeErr) {
logger.error(closeErr);
}

resolve({ stats });
});
}
});
});

// Assert type of stats must align to compiler.
resolve({ stats });
});
}
});
},
);
return { stats };
};
9 changes: 5 additions & 4 deletions packages/core/src/types/rsbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ export type BuildOptions = {
compiler?: Compiler | MultiCompiler;
};

export type Build = (options?: BuildOptions) => Promise<{
close?: () => Promise<void>;
stats?: Rspack.Stats | Rspack.MultiStats;
}>;

export type InspectConfigOptions = {
mode?: RsbuildMode;
verbose?: boolean;
Expand Down Expand Up @@ -86,10 +91,6 @@ export type StartDevServer = (
options?: StartDevServerOptions,
) => Promise<StartServerResult>;

export type Build = (options?: BuildOptions) => Promise<void | {
close: () => Promise<void>;
}>;

export type ProviderInstance<B extends 'rspack' | 'webpack' = 'rspack'> = {
readonly bundler: Bundler;

Expand Down
21 changes: 16 additions & 5 deletions website/docs/en/api/javascript-api/instance.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@ type BuildOptions = {
compiler?: Compiler | MultiCompiler;
};

function Build(options?: BuildOptions): Promise<void | {
close: () => Promise<void>;
function Build(options?: BuildOptions): Promise<{
stats?: Rspack.Stats | Rspack.MultiStats;
close?: () => Promise<void>;
}>;
```

Expand Down Expand Up @@ -121,14 +122,24 @@ await rsbuild.build({
});
```

The build method returns a `Watching` instance in watch mode that exposes `.close(callback)` method. Calling this method will end watching:
In watch mode, the `rsbuild.build()` returns a `close` method, which can be used to stop watching:

```ts
const watching = await rsbuild.build({
const result = await rsbuild.build({
watch: true,
});

await watching?.close();
await result.close?.();
```

### Stats Object

In non-watch mode, the `rsbuild.build() returns an Rspack [stats](https://rspack.dev/api/javascript-api/stats) object:

```ts
const result = await rsbuild.build();

console.log(result.stats);
```

### Custom Compiler
Expand Down
21 changes: 16 additions & 5 deletions website/docs/zh/api/javascript-api/instance.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,9 @@ type BuildOptions = {
compiler?: Compiler | MultiCompiler;
};

function Build(options?: BuildOptions): Promise<void | {
close: () => Promise<void>;
function Build(options?: BuildOptions): Promise<{
stats?: Rspack.Stats | Rspack.MultiStats;
close?: () => Promise<void>;
}>;
```

Expand Down Expand Up @@ -143,14 +144,24 @@ await rsbuild.build({
});
```

watch 模式下 build 方法会返回一个 `Watching` 实例,该实例会暴露一个 `.close(callback)` 方法调用该方法将会结束监听:
watch 模式下`rsbuild.build()` 会返回一个 `close` 方法调用该方法将会结束监听:

```ts
const watching = await rsbuild.build({
const result = await rsbuild.build({
watch: true,
});

await watching?.close();
await result.close?.();
```

### Stats 对象

在非 watch 模式下,`rsbuild.build()` 会返回一个 Rspack 的 [stats](https://rspack.dev/api/javascript-api/stats) 对象:

```ts
const result = await rsbuild.build();

console.log(result.stats);
```

### 自定义 Compiler
Expand Down

0 comments on commit 601f295

Please sign in to comment.