From 0c2d4f53e57606991c081531dbdff3a3ec17a372 Mon Sep 17 00:00:00 2001 From: easy1090 Date: Thu, 29 Aug 2024 19:13:16 +0800 Subject: [PATCH 1/4] feature: add brief configs --- e2e/cases/doctor-rspack/brief.test.ts | 167 ++++++++++++++++++ .../DiffServerAPIProvider/index.tsx | 1 - .../core/src/inner-plugins/utils/config.ts | 8 + packages/core/src/types/plugin.ts | 42 +++-- packages/rspack-plugin/src/plugin.ts | 15 +- packages/sdk/src/sdk/sdk/core.ts | 5 +- packages/sdk/src/sdk/sdk/webpack.ts | 8 +- packages/types/src/sdk/instance.ts | 6 + packages/webpack-plugin/src/plugin.ts | 8 +- 9 files changed, 240 insertions(+), 20 deletions(-) create mode 100644 e2e/cases/doctor-rspack/brief.test.ts diff --git a/e2e/cases/doctor-rspack/brief.test.ts b/e2e/cases/doctor-rspack/brief.test.ts new file mode 100644 index 00000000..77dfcd87 --- /dev/null +++ b/e2e/cases/doctor-rspack/brief.test.ts @@ -0,0 +1,167 @@ +import { expect, test, webkit } from '@playwright/test'; +import { getSDK, setSDK } from '@rsdoctor/core/plugins'; +import { compileByRspack } from '@scripts/test-helper'; +import { Compiler } from '@rspack/core'; +import path from 'path'; +import fs from 'fs'; +import { createRsdoctorPlugin } from './test-utils'; + +let reportLoaderStartOrEndTimes = 0; + +async function rspackCompile( + _tapName: string, + compile: typeof compileByRspack, +) { + const file = path.resolve(__dirname, './fixtures/a.js'); + const loader = path.resolve(__dirname, './fixtures/loaders/comment.js'); + + const esmLoader = path.resolve( + __dirname, + './fixtures/loaders/esm-serialize-query-to-comment.mjs', + ); + + const res = await compile(file, { + resolve: { + extensions: ['.ts', '.js'], + }, + output: { + path: path.join(__dirname, '../doctor-rspack/dist'), + }, + module: { + rules: [ + { + test: /\.js/, + use: loader, + }, + { + test: /\.js/, + use: esmLoader, + }, + { + test: /\.[jt]s$/, + use: { + loader: 'builtin:swc-loader', + options: { + sourceMap: true, + jsc: { + parser: { + syntax: 'typescript', + }, + externalHelpers: true, + preserveAllComments: false, + }, + }, + }, + type: 'javascript/auto', + }, + ], + }, + plugins: [ + // @ts-ignore + createRsdoctorPlugin({ + mode: 'brief', + }), + { + name: 'XXX', + apply(compiler: Compiler) { + compiler.hooks.beforeRun.tapPromise( + { name: 'XXX', stage: 99999 }, + async () => { + const sdk = getSDK(); + setSDK( + new Proxy(sdk, { + get(target, key, receiver) { + switch (key) { + case 'reportLoader': + return null; + case 'reportLoaderStartOrEnd': + return (_data: any) => { + reportLoaderStartOrEndTimes += 1; + }; + default: + return Reflect.get(target, key, receiver); + } + }, + set(target, key, value, receiver) { + return Reflect.set(target, key, value, receiver); + }, + defineProperty(target, p, attrs) { + return Reflect.defineProperty(target, p, attrs); + }, + }), + ); + }, + ); + }, + }, + ], + }); + + return res; +} + +test('rspack banner plugin', async () => { + const tapName = 'XXX'; + await rspackCompile(tapName, compileByRspack); + + const reportPath = path.join( + __dirname, + './dist/.rsdoctor/rsdoctor-report.html', + ); + + fileExists(reportPath); + + const browser = await webkit.launch(); + + // Create a new browser context + const context = await browser.newContext(); + + // Open a new page + const page = await context.newPage(); + + // Navigate to a URL + await page.goto(`file:///${reportPath}`); + + // Perform actions on the page + const title = await page.title(); + expect(title).toBe('Rsdoctor'); + + const titleContent = 'Bundle Overall'; + + const bundleTitleExists = await page + .locator(`text=${titleContent}`) + .first() + .isVisible(); + + const compileTabExists = await page + .locator(`text='Compile Analysis'`) + .first() + .isVisible(); + + const bundleTabExists = await page + .locator(`text='Bundle Size'`) + .first() + .isVisible(); + + expect(bundleTitleExists).toBe(true); + expect(compileTabExists).toBe(true); + expect(bundleTabExists).toBe(true); + + // Close the page + await page.close(); + + // Close the browser context + await context.close(); + + // Close the browser + await browser.close(); +}); + +async function fileExists(filePath: string) { + try { + await fs.existsSync(filePath); + return true; + } catch { + return false; + } +} diff --git a/packages/components/src/components/BundleDiff/DiffServerAPIProvider/index.tsx b/packages/components/src/components/BundleDiff/DiffServerAPIProvider/index.tsx index 10e5617d..cbfa6646 100644 --- a/packages/components/src/components/BundleDiff/DiffServerAPIProvider/index.tsx +++ b/packages/components/src/components/BundleDiff/DiffServerAPIProvider/index.tsx @@ -37,7 +37,6 @@ export const DiffServerAPIProvider = < } > {(current) => { - // TODO:: need check return current ? children(baseline, current) : ; }} diff --git a/packages/core/src/inner-plugins/utils/config.ts b/packages/core/src/inner-plugins/utils/config.ts index 00c98b51..db7ecdb9 100644 --- a/packages/core/src/inner-plugins/utils/config.ts +++ b/packages/core/src/inner-plugins/utils/config.ts @@ -38,6 +38,12 @@ export function normalizeUserConfig( port, printLog = { serverUrls: true }, mode = 'normal', + brief = { + reportHtmlDir: undefined, + reportHtmlName: undefined, + writeDataJson: false, + }, + reportDir = '', } = config; assert(linter && typeof linter === 'object'); @@ -100,6 +106,8 @@ export function normalizeUserConfig( port, printLog, mode, + brief, + reportDir, }; return res; diff --git a/packages/core/src/types/plugin.ts b/packages/core/src/types/plugin.ts index 09563465..c898aa5f 100644 --- a/packages/core/src/types/plugin.ts +++ b/packages/core/src/types/plugin.ts @@ -16,6 +16,8 @@ export type IReportCodeType = { noCode?: boolean; }; +export type IOutput = {}; + export interface RsdoctorWebpackPluginOptions< Rules extends LinterType.ExtendRuleData[], > { @@ -57,26 +59,21 @@ export interface RsdoctorWebpackPluginOptions< * sdk instance of outside */ sdkInstance?: RsdoctorWebpackSDK; - /** - * control the Rsdoctor reporter codes records. - */ - reportCodeType?: IReportCodeType | undefined; /** * Whether to turn on some characteristic analysis capabilities, such as: the support for the BannerPlugin. */ supports?: ISupport; + /** - * control the Rsdoctor upload data to TOS, used by inner-rsdoctor. - * @default false + * The directory where the report files will be output. */ - disableTOSUpload?: boolean; + reportDir?: string; /** - * The name of inner rsdoctor's client package, used by inner-rsdoctor. - * @default false + * Control the Rsdoctor reporter codes records. */ - innerClientPath?: string; + reportCodeType?: IReportCodeType | undefined; /** * The port of the Rsdoctor server. @@ -87,6 +84,23 @@ export interface RsdoctorWebpackPluginOptions< * Options to control the log printing. */ printLog?: SDK.IPrintLog; + + /** + * Options to control brief mode reports. + */ + brief?: SDK.BriefConfig; + + /** + * control the Rsdoctor upload data to TOS, used by inner-rsdoctor. + * @default false + */ + disableTOSUpload?: boolean; + + /** + * The name of inner rsdoctor's client package, used by inner-rsdoctor. + * @default false + */ + innerClientPath?: string; } export interface RsdoctorMultiplePluginOptions< @@ -110,7 +124,12 @@ export interface RsdoctorPluginOptionsNormalized< > extends Common.DeepRequired< Omit< RsdoctorWebpackPluginOptions, - 'sdkInstance' | 'linter' | 'reportCodeType' | 'supports' | 'port' + | 'sdkInstance' + | 'linter' + | 'reportCodeType' + | 'supports' + | 'port' + | 'brief' > > { features: Common.DeepRequired; @@ -119,6 +138,7 @@ export interface RsdoctorPluginOptionsNormalized< port?: number; reportCodeType: SDK.ToDataType; supports: ISupport; + brief: SDK.BriefConfig; } export interface BasePluginInstance { diff --git a/packages/rspack-plugin/src/plugin.ts b/packages/rspack-plugin/src/plugin.ts index e7b75b2a..ad294e83 100644 --- a/packages/rspack-plugin/src/plugin.ts +++ b/packages/rspack-plugin/src/plugin.ts @@ -80,6 +80,7 @@ export class RsdoctorRspackPlugin innerClientPath: this.options.innerClientPath, printLog: this.options.printLog, mode: this.options.mode ? this.options.mode : undefined, + brief: this.options.brief, }, }); this.outsideInstance = Boolean(this.options.sdkInstance); @@ -171,21 +172,24 @@ export class RsdoctorRspackPlugin if (this.outsideInstance && 'parent' in this.sdk) { this.sdk.parent.master.setOutputDir( path.resolve( - compiler.outputPath, + this.options.reportDir || compiler.outputPath, `./${Constants.RsdoctorOutputFolder}`, ), ); } this.sdk.setOutputDir( - path.resolve(compiler.outputPath, `./${Constants.RsdoctorOutputFolder}`), + path.resolve( + this.options.reportDir || compiler.outputPath, + `./${Constants.RsdoctorOutputFolder}`, + ), ); await this.sdk.writeStore(); if (!this.options.disableClientServer) { if (this.options.mode === SDK.IMode[SDK.IMode.brief]) { const outputFilePath = path.resolve( this.sdk.outputDir, - 'rsdoctor-report.html', + this.options.brief.reportHtmlName || 'rsdoctor-report.html', ); console.log( @@ -227,7 +231,10 @@ export class RsdoctorRspackPlugin }); this.sdk.setOutputDir( - path.resolve(compiler.outputPath, `./${Constants.RsdoctorOutputFolder}`), + path.resolve( + this.options.reportDir || compiler.outputPath, + `./${Constants.RsdoctorOutputFolder}`, + ), ); } } diff --git a/packages/sdk/src/sdk/sdk/core.ts b/packages/sdk/src/sdk/sdk/core.ts index 01af4888..3d59a458 100644 --- a/packages/sdk/src/sdk/sdk/core.ts +++ b/packages/sdk/src/sdk/sdk/core.ts @@ -42,7 +42,10 @@ export abstract class SDKCore this._name = name; this.root = root; this.pid = process.pid; - this._outputDir = path.join(this.root, Constants.RsdoctorOutputFolder); + this._outputDir = path.join( + this.outputDir || this.root, + Constants.RsdoctorOutputFolder, + ); } get outputDir() { diff --git a/packages/sdk/src/sdk/sdk/webpack.ts b/packages/sdk/src/sdk/sdk/webpack.ts index 747fa98d..1dff59aa 100644 --- a/packages/sdk/src/sdk/sdk/webpack.ts +++ b/packages/sdk/src/sdk/sdk/webpack.ts @@ -380,6 +380,9 @@ export class RsdoctorWebpackSDK< ? this.extraConfig.innerClientPath : require.resolve('@rsdoctor/client'); + if (this.extraConfig.brief?.writeDataJson) { + this.saveManifest(this.getStoreData(), options || {}); + } return this.inlineScriptsAndStyles(clientHtmlPath); } return this.saveManifest(this.getStoreData(), options || {}); @@ -593,7 +596,10 @@ export class RsdoctorWebpackSDK< htmlContent = this.addRsdoctorDataToHTML(this.getStoreData(), htmlContent); // Output the processed HTML content - const outputFilePath = path.resolve(this.outputDir, 'rsdoctor-report.html'); + const outputFilePath = path.resolve( + this.outputDir, + this.extraConfig?.brief?.reportHtmlName || 'rsdoctor-report.html', + ); fse.outputFileSync(outputFilePath, htmlContent, { encoding: 'utf-8', diff --git a/packages/types/src/sdk/instance.ts b/packages/types/src/sdk/instance.ts index 9c6b6a17..39d7d9d1 100644 --- a/packages/types/src/sdk/instance.ts +++ b/packages/types/src/sdk/instance.ts @@ -115,6 +115,11 @@ export interface IPrintLog { serverUrls: boolean; } +export interface BriefConfig { + reportHtmlName?: string | undefined; + writeDataJson: boolean; +} + export type SDKOptionsType = { disableTOSUpload: boolean; innerClientPath?: string; @@ -122,6 +127,7 @@ export type SDKOptionsType = { noServer?: boolean; printLog?: IPrintLog; mode?: keyof typeof IMode; + brief?: BriefConfig; }; /** diff --git a/packages/webpack-plugin/src/plugin.ts b/packages/webpack-plugin/src/plugin.ts index 83e22a26..87ff2fbf 100644 --- a/packages/webpack-plugin/src/plugin.ts +++ b/packages/webpack-plugin/src/plugin.ts @@ -65,6 +65,7 @@ export class RsdoctorWebpackPlugin innerClientPath: this.options.innerClientPath, printLog: this.options.printLog, mode: this.options.mode ? this.options.mode : undefined, + brief: this.options.brief, }, }); this.outsideInstance = Boolean(this.options.sdkInstance); @@ -156,7 +157,10 @@ export class RsdoctorWebpackPlugin }); this.sdk.setOutputDir( - path.resolve(compiler.outputPath, `./${Constants.RsdoctorOutputFolder}`), + path.resolve( + this.options.reportDir || compiler.outputPath, + `./${Constants.RsdoctorOutputFolder}`, + ), ); if (configuration.name) { @@ -203,7 +207,7 @@ export class RsdoctorWebpackPlugin ) { const outputFilePath = path.resolve( this.sdk.outputDir, - 'rsdoctor-report.html', + this.options.brief.reportHtmlName || 'rsdoctor-report.html', ); console.log( `${chalk.green('[RSDOCTOR] generated brief report')}: ${outputFilePath}`, From de355287d52b712e8e12d428ecded65cbb4b864b Mon Sep 17 00:00:00 2001 From: easy1090 Date: Thu, 29 Aug 2024 19:30:34 +0800 Subject: [PATCH 2/4] feature: add brief configs --- e2e/cases/doctor-rspack/brief.test.ts | 2 +- e2e/playwright.config.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/e2e/cases/doctor-rspack/brief.test.ts b/e2e/cases/doctor-rspack/brief.test.ts index 77dfcd87..7dc96c0e 100644 --- a/e2e/cases/doctor-rspack/brief.test.ts +++ b/e2e/cases/doctor-rspack/brief.test.ts @@ -100,7 +100,7 @@ async function rspackCompile( return res; } -test('rspack banner plugin', async () => { +test('rspack brief mode', async () => { const tapName = 'XXX'; await rspackCompile(tapName, compileByRspack); diff --git a/e2e/playwright.config.ts b/e2e/playwright.config.ts index e1b05271..c2b53e73 100644 --- a/e2e/playwright.config.ts +++ b/e2e/playwright.config.ts @@ -1,5 +1,9 @@ -import { defineConfig } from '@playwright/test'; +import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ testMatch: ['/cases/**/**.test.ts'], -}); \ No newline at end of file + name: 'chrome', + use: { + ...devices.DesktopChrome, + }, +}); From d5bc500cffa5c8e974af93089f03456bdb7548da Mon Sep 17 00:00:00 2001 From: easy1090 Date: Thu, 29 Aug 2024 20:32:30 +0800 Subject: [PATCH 3/4] feature: add brief configs --- e2e/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e/package.json b/e2e/package.json index 80816df7..238536f9 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -3,7 +3,8 @@ "name": "@rsdoctor/e2e", "version": "0.0.1", "scripts": { - "test": "playwright test" + "test": "pnpm run i:webkit && playwright test", + "i:webkit": "playwright install webkit" }, "dependencies": { "devcert": "1.2.2", From e8f7f6b0836e7fcd64f9301407c3d0d01a3a22d5 Mon Sep 17 00:00:00 2001 From: easy1090 Date: Thu, 29 Aug 2024 20:43:05 +0800 Subject: [PATCH 4/4] feature: add brief configs --- e2e/package.json | 2 +- e2e/playwright.config.ts | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/e2e/package.json b/e2e/package.json index 238536f9..65068a42 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -4,7 +4,7 @@ "version": "0.0.1", "scripts": { "test": "pnpm run i:webkit && playwright test", - "i:webkit": "playwright install webkit" + "i:webkit": "playwright install-deps" }, "dependencies": { "devcert": "1.2.2", diff --git a/e2e/playwright.config.ts b/e2e/playwright.config.ts index c2b53e73..353f9164 100644 --- a/e2e/playwright.config.ts +++ b/e2e/playwright.config.ts @@ -1,9 +1,5 @@ -import { defineConfig, devices } from '@playwright/test'; +import { defineConfig } from '@playwright/test'; export default defineConfig({ testMatch: ['/cases/**/**.test.ts'], - name: 'chrome', - use: { - ...devices.DesktopChrome, - }, });