From 601f2955006ebe55698e30a4dac8e36d2438a55f Mon Sep 17 00:00:00 2001 From: neverland Date: Fri, 30 Aug 2024 20:14:10 +0800 Subject: [PATCH] feat: add stats to the return value of `rsbuild.build` (#3325) --- .../plugin-hooks-watch/index.test.ts | 4 +- packages/compat/webpack/src/build.ts | 50 ++++++++--------- packages/core/src/index.ts | 1 + packages/core/src/provider/build.ts | 54 +++++++++---------- packages/core/src/types/rsbuild.ts | 9 ++-- .../docs/en/api/javascript-api/instance.mdx | 21 ++++++-- .../docs/zh/api/javascript-api/instance.mdx | 21 ++++++-- 7 files changed, 92 insertions(+), 68 deletions(-) diff --git a/e2e/cases/plugin-api/plugin-hooks-watch/index.test.ts b/e2e/cases/plugin-api/plugin-hooks-watch/index.test.ts index 02938d0b09..7230c321ec 100644 --- a/e2e/cases/plugin-api/plugin-hooks-watch/index.test.ts +++ b/e2e/cases/plugin-api/plugin-hooks-watch/index.test.ts @@ -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');"); @@ -113,6 +113,6 @@ rspackOnlyTest( 'AfterBuild', ]); - await watching?.close(); + await result.close?.(); }, ); diff --git a/packages/compat/webpack/src/build.ts b/packages/compat/webpack/src/build.ts index 7f1bc33ad6..099e264366 100644 --- a/packages/compat/webpack/src/build.ts +++ b/packages/compat/webpack/src/build.ts @@ -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'; @@ -9,9 +9,7 @@ import { registerBuildHook } from './shared'; export const build = async ( initOptions: InitConfigsOptions, { watch, compiler: customCompiler }: BuildOptions = {}, -): Promise Promise; -}> => { +): Promise> => { const { context } = initOptions; let compiler: Rspack.Compiler | Rspack.MultiCompiler; @@ -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 }; }; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 600a8f6615..9206c433cb 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -31,6 +31,7 @@ export type { AppIcon, AppIconItem, AliasStrategy, + Build, BuildOptions, BundlerPluginInstance, CacheGroup, diff --git a/packages/core/src/provider/build.ts b/packages/core/src/provider/build.ts index 53b737b628..ddc29f8547 100644 --- a/packages/core/src/provider/build.ts +++ b/packages/core/src/provider/build.ts @@ -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 Promise; -}> => { +): Promise> => { const { context } = initOptions; let compiler: Rspack.Compiler | Rspack.MultiCompiler; @@ -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 }; }; diff --git a/packages/core/src/types/rsbuild.ts b/packages/core/src/types/rsbuild.ts index 42da2bcd8d..53d263fb34 100644 --- a/packages/core/src/types/rsbuild.ts +++ b/packages/core/src/types/rsbuild.ts @@ -35,6 +35,11 @@ export type BuildOptions = { compiler?: Compiler | MultiCompiler; }; +export type Build = (options?: BuildOptions) => Promise<{ + close?: () => Promise; + stats?: Rspack.Stats | Rspack.MultiStats; +}>; + export type InspectConfigOptions = { mode?: RsbuildMode; verbose?: boolean; @@ -86,10 +91,6 @@ export type StartDevServer = ( options?: StartDevServerOptions, ) => Promise; -export type Build = (options?: BuildOptions) => Promise Promise; -}>; - export type ProviderInstance = { readonly bundler: Bundler; diff --git a/website/docs/en/api/javascript-api/instance.mdx b/website/docs/en/api/javascript-api/instance.mdx index b0edc82842..a3ef613939 100644 --- a/website/docs/en/api/javascript-api/instance.mdx +++ b/website/docs/en/api/javascript-api/instance.mdx @@ -88,8 +88,9 @@ type BuildOptions = { compiler?: Compiler | MultiCompiler; }; -function Build(options?: BuildOptions): Promise Promise; +function Build(options?: BuildOptions): Promise<{ + stats?: Rspack.Stats | Rspack.MultiStats; + close?: () => Promise; }>; ``` @@ -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 diff --git a/website/docs/zh/api/javascript-api/instance.mdx b/website/docs/zh/api/javascript-api/instance.mdx index 2016f4f1be..8bd7f685f4 100644 --- a/website/docs/zh/api/javascript-api/instance.mdx +++ b/website/docs/zh/api/javascript-api/instance.mdx @@ -110,8 +110,9 @@ type BuildOptions = { compiler?: Compiler | MultiCompiler; }; -function Build(options?: BuildOptions): Promise Promise; +function Build(options?: BuildOptions): Promise<{ + stats?: Rspack.Stats | Rspack.MultiStats; + close?: () => Promise; }>; ``` @@ -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