├── .changeset └── config.json ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── 1-bug-report.en-US.yml │ ├── 2-feature-request.en-US.yml │ └── config.yml ├── PULL_REQUEST_TEMPLATE.md ├── pr-labeler.yml ├── release.yml ├── renovate.json5 └── workflows │ ├── lint.yml │ ├── pr-label.yaml │ ├── release.yml │ ├── test-ubuntu.yml │ └── test-windows.yml ├── .gitignore ├── .husky ├── post-checkout └── pre-commit ├── .npmrc ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── .vscode ├── extensions.json └── settings.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── README.zh-CN.md ├── SECURITY.md ├── biome.json ├── cspell.config.cjs ├── e2e ├── README.md ├── cases │ ├── doctor-rsbuild │ │ ├── fixtures │ │ │ ├── a.js │ │ │ ├── b.js │ │ │ ├── loaders │ │ │ │ ├── comment.js │ │ │ │ ├── serialize-query-to-comment.js │ │ │ │ └── serialize-resource-query-to-comment.js │ │ │ └── port.js │ │ ├── loaders │ │ │ └── loader.test.ts │ │ └── test-utils.ts │ ├── doctor-rspack │ │ ├── banner-plugin.test.ts │ │ ├── brief.test.ts │ │ ├── bundle-diff.test.ts │ │ ├── fixtures │ │ │ ├── a.js │ │ │ ├── b.js │ │ │ ├── c.js │ │ │ ├── index.css │ │ │ ├── index.ts │ │ │ ├── loaders │ │ │ │ ├── comment.js │ │ │ │ ├── esm-serialize-query-to-comment.mjs │ │ │ │ ├── esm │ │ │ │ │ ├── esm-serialize-query-to-comment.js │ │ │ │ │ └── package.json │ │ │ │ └── serialize-query-to-comment.js │ │ │ ├── port.js │ │ │ └── rspack-banner-plugin.js │ │ ├── layer-plugin.test.ts │ │ ├── linter-rule-render.test.ts │ │ ├── plugin.test.ts │ │ ├── tag-plugin-without-banner.test.ts │ │ └── test-utils.ts │ └── doctor-webpack │ │ ├── experiments.test.ts │ │ ├── fixtures │ │ ├── a.js │ │ ├── b.js │ │ ├── loaders │ │ │ ├── comment.js │ │ │ ├── serialize-query-to-comment.js │ │ │ └── serialize-resource-query-to-comment.js │ │ └── port.js │ │ ├── fixtures2 │ │ ├── a.js │ │ ├── b.js │ │ ├── index.less │ │ ├── loaders │ │ │ ├── comment.js │ │ │ ├── serialize-query-to-comment.js │ │ │ └── serialize-resource-query-to-comment.js │ │ └── port.js │ │ ├── loaders │ │ ├── loader.test.ts │ │ ├── proxy.test.ts │ │ ├── query.test.ts │ │ └── resourceQuery.test.ts │ │ ├── plugins │ │ ├── loader-mini-css-extract.test.ts │ │ ├── loader.test.ts │ │ ├── multi-plugin-brief.test.ts │ │ ├── plugin.test.ts │ │ ├── rules.test.ts │ │ └── treeShaking.test.ts │ │ ├── summary.test.ts │ │ └── test-utils.ts ├── fixtures │ ├── manifests │ │ └── empty-manifest.json │ └── rsdoctor │ │ ├── chunkGraph │ │ └── 0 │ │ ├── configs │ │ └── 0 │ │ ├── envinfo │ │ └── 0 │ │ ├── errors │ │ └── 0 │ │ ├── loader │ │ └── 0 │ │ ├── manifest.json │ │ ├── moduleCodeMap │ │ └── 0 │ │ ├── moduleGraph │ │ └── 0 │ │ ├── otherReports │ │ └── 0 │ │ ├── packageGraph │ │ └── 0 │ │ ├── plugin │ │ └── 0 │ │ ├── resolver │ │ └── 0 │ │ └── summary │ │ └── 0 ├── package.json ├── playwright.config.ts ├── test-kit │ ├── index.ts │ ├── launch.ts │ └── path.ts └── tsconfig.json ├── examples ├── modern-minimal │ ├── modern.config.ts │ ├── package.json │ ├── src │ │ ├── myapp │ │ │ └── routes │ │ │ │ ├── index.css │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ ├── myapp2 │ │ │ └── routes │ │ │ │ ├── index.css │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ └── utils │ │ │ └── utils.ts │ └── tsconfig.json ├── multiple-minimal │ ├── build.ts │ ├── package.json │ ├── src │ │ ├── app.tsx │ │ ├── declaration.d.ts │ │ ├── index.module.less │ │ └── index.ts │ └── tsconfig.json ├── rsbuild-minimal │ ├── package.json │ ├── rsbuild.config.ts │ ├── rules │ │ └── assets-count-limit.ts │ ├── src │ │ ├── App.css │ │ ├── App.tsx │ │ ├── button.css │ │ ├── env.d.ts │ │ ├── index.tsx │ │ ├── semver.ts │ │ └── semver7.ts │ └── tsconfig.json ├── rspack-banner-minimal │ ├── index.html │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── logo192.png │ │ ├── logo512.png │ │ └── manifest.json │ ├── rspack.config.js │ ├── src │ │ ├── App.css │ │ ├── App.tsx │ │ ├── Footer │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ └── index.module.less │ │ ├── app1.tsx │ │ ├── declaration.d.ts │ │ ├── index.css │ │ ├── index.module.less │ │ ├── index.ts │ │ ├── index.tsx │ │ ├── logo.svg │ │ ├── react-app-env.d.ts │ │ ├── reportWebVitals.ts │ │ ├── setupTests.ts │ │ └── typings │ │ │ └── assetsDefinition.d.ts │ └── tsconfig.json ├── rspack-layers-minimal │ ├── build.ts │ ├── index.html │ ├── legacy-loader.js │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── rspack.config.js │ ├── src │ │ ├── App.css │ │ ├── App.tsx │ │ ├── Footer │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ └── index.module.less │ │ ├── app1.tsx │ │ ├── declaration.d.ts │ │ ├── index.css │ │ ├── index.module.less │ │ ├── index.ts │ │ ├── index.tsx │ │ ├── logo.svg │ │ ├── react-app-env.d.ts │ │ ├── reportWebVitals.ts │ │ ├── setupTests.ts │ │ └── typings │ │ │ └── assetsDefinition.d.ts │ └── tsconfig.json ├── rspack-minimal │ ├── build.ts │ ├── index.html │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── rspack.config.js │ ├── src │ │ ├── App.css │ │ ├── App.tsx │ │ ├── Footer │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ └── index.module.less │ │ ├── app1.tsx │ │ ├── declaration.d.ts │ │ ├── index.css │ │ ├── index.module.less │ │ ├── index.ts │ │ ├── index.tsx │ │ ├── logo.svg │ │ ├── react-app-env.d.ts │ │ ├── reportWebVitals.ts │ │ ├── setupTests.ts │ │ └── typings │ │ │ └── assetsDefinition.d.ts │ └── tsconfig.json ├── rspress-minimal │ ├── .gitignore │ ├── README.md │ ├── docs │ │ ├── _meta.json │ │ ├── guide │ │ │ ├── _meta.json │ │ │ └── index.md │ │ ├── hello.md │ │ ├── index.md │ │ └── public │ │ │ ├── rspress-dark-logo.png │ │ │ ├── rspress-icon.png │ │ │ └── rspress-light-logo.png │ ├── package.json │ ├── rspress.config.ts │ └── tsconfig.json └── webpack-minimal │ ├── package.json │ ├── src │ ├── html.ts │ ├── images │ │ └── file.svg │ ├── index.ts │ ├── style.css │ ├── types.ts │ ├── typings │ │ └── assetsDefinition.d.ts │ ├── utils.ts │ ├── utils │ │ ├── index.ts │ │ └── utils.js │ ├── utils2.ts │ ├── utils3.ts │ ├── utils4.ts │ ├── utils5.ts │ └── utils6.ts │ ├── tsconfig.json │ └── webpack.config.ts ├── nx.json ├── package.json ├── packages ├── ai │ ├── .env.sample │ ├── .gitignore │ ├── README.md │ ├── README.zh-CN.md │ ├── bin │ │ └── rsdoctor-mcp │ ├── package.json │ ├── resources │ │ ├── rsdoctor-config.md │ │ └── rsdoctor-context.md │ ├── rslib.config.ts │ ├── src │ │ ├── index.ts │ │ ├── prompt │ │ │ ├── assets.ts │ │ │ ├── bundle.ts │ │ │ ├── code.ts │ │ │ ├── deps.ts │ │ │ ├── functions.ts │ │ │ ├── index.ts │ │ │ └── schema.ts │ │ ├── schema.ts │ │ ├── server │ │ │ ├── index.ts │ │ │ ├── prompt.ts │ │ │ ├── resource.ts │ │ │ ├── server.ts │ │ │ ├── socket.ts │ │ │ └── tools.ts │ │ ├── types │ │ │ └── index.d.ts │ │ └── utils │ │ │ ├── chunks.ts │ │ │ ├── env.ts │ │ │ └── index.ts │ ├── tests │ │ ├── chunks.test.ts │ │ ├── code.test.ts │ │ ├── fixtures │ │ │ ├── chunks_client.json │ │ │ ├── deps.json │ │ │ ├── group.json │ │ │ ├── result.json │ │ │ └── test.cjs │ │ ├── index.test.ts │ │ ├── model │ │ │ ├── coze.ts │ │ │ ├── index.ts │ │ │ └── openai.ts │ │ ├── socket.test.ts │ │ ├── tsconfig.json │ │ └── utils.test.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ └── vitest.config.ts ├── cli │ ├── LICENSE │ ├── README.md │ ├── bin │ │ └── rsdoctor │ ├── modern.config.ts │ ├── package.json │ ├── src │ │ ├── commands │ │ │ ├── analyze.ts │ │ │ ├── bundle-diff.ts │ │ │ └── index.ts │ │ ├── constants.ts │ │ ├── index.ts │ │ ├── types.ts │ │ └── utils.ts │ └── tsconfig.json ├── client │ ├── LICENSE │ ├── README.md │ ├── config │ │ └── constants.ts │ ├── package.json │ ├── rsbuild.config.ts │ ├── src │ │ ├── App.tsx │ │ ├── common │ │ │ ├── imgs │ │ │ │ └── connection-point.svg │ │ │ └── styles │ │ │ │ ├── base.scss │ │ │ │ └── theme.scss │ │ ├── index.tsx │ │ ├── router.tsx │ │ └── typings │ │ │ └── assetsDefinition.d.ts │ └── tsconfig.json ├── components │ ├── LICENSE │ ├── README.md │ ├── modern.config.ts │ ├── package.json │ ├── src │ │ ├── common │ │ │ ├── imgs │ │ │ │ ├── connection-point.svg │ │ │ │ ├── rsdoctor-navbar.png │ │ │ │ └── webpack.svg │ │ │ └── svg │ │ │ │ ├── bundle-size.svg │ │ │ │ ├── error.svg │ │ │ │ ├── file-css.svg │ │ │ │ ├── file-html.svg │ │ │ │ ├── file-image.svg │ │ │ │ ├── file-js.svg │ │ │ │ ├── file-unknown.svg │ │ │ │ ├── file.svg │ │ │ │ ├── files │ │ │ │ ├── css.svg │ │ │ │ ├── html.svg │ │ │ │ ├── image.svg │ │ │ │ ├── js.svg │ │ │ │ └── unkown-file.svg │ │ │ │ ├── loader │ │ │ │ ├── input.svg │ │ │ │ ├── output.svg │ │ │ │ └── step.svg │ │ │ │ ├── navbar │ │ │ │ ├── bundle-size-active.svg │ │ │ │ ├── bundle-size-inactive.svg │ │ │ │ ├── compile-analysis-active.svg │ │ │ │ ├── compile-analysis-inactive.svg │ │ │ │ ├── overall-active.svg │ │ │ │ └── overall-inactive.svg │ │ │ │ ├── output.svg │ │ │ │ ├── source-size.svg │ │ │ │ ├── source.svg │ │ │ │ ├── total-size.svg │ │ │ │ └── version.svg │ │ ├── components │ │ │ ├── Alert │ │ │ │ ├── change.tsx │ │ │ │ ├── ecma-version-check.module.scss │ │ │ │ ├── ecma-version-check.tsx │ │ │ │ ├── file-relation.tsx │ │ │ │ ├── index.scss │ │ │ │ ├── package-relation.module.scss │ │ │ │ ├── package-relation.tsx │ │ │ │ ├── types.ts │ │ │ │ └── view.tsx │ │ │ ├── Alerts │ │ │ │ ├── bundle-alert.module.scss │ │ │ │ ├── bundle-alert.tsx │ │ │ │ ├── bundle.tsx │ │ │ │ ├── collapse-cross-chunks.tsx │ │ │ │ ├── collapse.module.scss │ │ │ │ ├── collapse.tsx │ │ │ │ ├── compile.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── list.module.scss │ │ │ │ ├── list.tsx │ │ │ │ ├── overlay.module.scss │ │ │ │ └── overlay.tsx │ │ │ ├── Badge │ │ │ │ └── index.tsx │ │ │ ├── Card │ │ │ │ ├── diff.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── size.module.scss │ │ │ │ ├── size.tsx │ │ │ │ └── statistic.tsx │ │ │ ├── Charts │ │ │ │ ├── TimelineCharts │ │ │ │ │ └── index.tsx │ │ │ │ ├── bootstrap.tsx │ │ │ │ ├── common.tsx │ │ │ │ ├── constants.ts │ │ │ │ ├── done.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── loader.scss │ │ │ │ ├── loader.tsx │ │ │ │ ├── minify.tsx │ │ │ │ ├── tooltips.scss │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ │ ├── Configuration │ │ │ │ ├── builder.module.scss │ │ │ │ ├── builder.tsx │ │ │ │ └── index.tsx │ │ │ ├── FileTree │ │ │ │ ├── css.svg │ │ │ │ ├── html.svg │ │ │ │ ├── image.svg │ │ │ │ ├── index.scss │ │ │ │ ├── index.tsx │ │ │ │ ├── js.svg │ │ │ │ └── unkown-file.svg │ │ │ ├── Form │ │ │ │ └── keyword.tsx │ │ │ ├── Keyword │ │ │ │ ├── index.tsx │ │ │ │ └── style.module.scss │ │ │ ├── Layout │ │ │ │ ├── builder-select.tsx │ │ │ │ ├── bundle-size-icon.svg │ │ │ │ ├── compile-icon.svg │ │ │ │ ├── constants.ts │ │ │ │ ├── header.scss │ │ │ │ ├── header.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── menus.tsx │ │ │ │ ├── overall-icon.svg │ │ │ │ └── progress.tsx │ │ │ ├── Loader │ │ │ │ ├── Analysis │ │ │ │ │ ├── files.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── input.svg │ │ │ │ │ ├── output.svg │ │ │ │ │ └── style.module.scss │ │ │ │ ├── executions.tsx │ │ │ │ └── step.svg │ │ │ ├── Manifest │ │ │ │ ├── api.tsx │ │ │ │ ├── data.tsx │ │ │ │ └── index.tsx │ │ │ ├── Opener │ │ │ │ ├── code.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── vscode.tsx │ │ │ ├── Overall │ │ │ │ ├── DataSummary.module.scss │ │ │ │ ├── DataSummary.tsx │ │ │ │ ├── bundle.module.scss │ │ │ │ ├── bundle.tsx │ │ │ │ ├── card.module.scss │ │ │ │ ├── compile.module.scss │ │ │ │ ├── compile.tsx │ │ │ │ ├── help-center.module.scss │ │ │ │ ├── help-center.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── list.module.scss │ │ │ │ ├── overview.module.scss │ │ │ │ ├── overview.tsx │ │ │ │ ├── project.module.scss │ │ │ │ └── project.tsx │ │ │ ├── Plugins │ │ │ │ └── webpack.tsx │ │ │ ├── Resolver │ │ │ │ └── analysis.tsx │ │ │ ├── Select │ │ │ │ ├── index.scss │ │ │ │ └── index.tsx │ │ │ ├── Status │ │ │ │ ├── failed.tsx │ │ │ │ └── index.tsx │ │ │ ├── TextDrawer │ │ │ │ ├── duplicate.tsx │ │ │ │ └── index.tsx │ │ │ ├── Title │ │ │ │ └── index.tsx │ │ │ ├── base │ │ │ │ ├── CodeViewer │ │ │ │ │ ├── index.module.scss │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── interface.ts │ │ │ │ │ ├── useCodeDrawer.tsx │ │ │ │ │ └── utils.ts │ │ │ │ ├── DiffViewer │ │ │ │ │ ├── index.module.scss │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── interface.ts │ │ │ │ │ ├── useDiffDrawer.tsx │ │ │ │ │ └── utils.ts │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ ├── config.tsx │ │ ├── constants.tsx │ │ ├── index.ts │ │ ├── modern-app-env.d.ts │ │ ├── pages │ │ │ ├── BundleSize │ │ │ │ ├── components │ │ │ │ │ ├── asset.tsx │ │ │ │ │ ├── card.module.scss │ │ │ │ │ ├── cards.tsx │ │ │ │ │ ├── index.module.scss │ │ │ │ │ ├── index.scss │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── search-modal.tsx │ │ │ │ ├── config.tsx │ │ │ │ ├── constants.ts │ │ │ │ └── index.tsx │ │ │ ├── ModuleAnalyze │ │ │ │ ├── chunks.tsx │ │ │ │ ├── components │ │ │ │ │ ├── fileTreeCom.scss │ │ │ │ │ └── fileTreeCom.tsx │ │ │ │ ├── constants.ts │ │ │ │ ├── dependency.tsx │ │ │ │ ├── fileTree.tsx │ │ │ │ ├── index.scss │ │ │ │ ├── index.tsx │ │ │ │ └── utils │ │ │ │ │ ├── hooks.tsx │ │ │ │ │ └── index.ts │ │ │ ├── ModuleResolve │ │ │ │ ├── constants.ts │ │ │ │ └── index.tsx │ │ │ ├── Overall │ │ │ │ ├── constants.ts │ │ │ │ ├── index.module.scss │ │ │ │ ├── index.tsx │ │ │ │ └── responsiveLayout.tsx │ │ │ ├── Resources │ │ │ │ ├── BundleDiff │ │ │ │ │ ├── DiffContainer │ │ │ │ │ │ ├── assets.tsx │ │ │ │ │ │ ├── cards.tsx │ │ │ │ │ │ ├── changes.tsx │ │ │ │ │ │ ├── constants.ts │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ ├── modules.tsx │ │ │ │ │ │ ├── overview.tsx │ │ │ │ │ │ ├── packages.tsx │ │ │ │ │ │ ├── row.tsx │ │ │ │ │ │ ├── types.ts │ │ │ │ │ │ └── utils.tsx │ │ │ │ │ ├── DiffServerAPIProvider │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── constants.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── RuleIndex │ │ │ │ │ ├── constants.ts │ │ │ │ │ └── index.tsx │ │ │ ├── TreeShaking │ │ │ │ ├── constants.ts │ │ │ │ ├── editor.tsx │ │ │ │ ├── index.scss │ │ │ │ ├── index.tsx │ │ │ │ ├── open-tag.ts │ │ │ │ ├── range.ts │ │ │ │ ├── space.tsx │ │ │ │ ├── table.tsx │ │ │ │ ├── types.ts │ │ │ │ └── utils.tsx │ │ │ ├── WebpackLoaders │ │ │ │ ├── Analysis │ │ │ │ │ ├── constants.ts │ │ │ │ │ └── index.tsx │ │ │ │ ├── Overall │ │ │ │ │ ├── constants.ts │ │ │ │ │ └── index.tsx │ │ │ │ └── constants.ts │ │ │ ├── WebpackPlugins │ │ │ │ ├── constants.ts │ │ │ │ ├── index.scss │ │ │ │ └── index.tsx │ │ │ └── index.ts │ │ ├── typings │ │ │ ├── assetsDefinition.d.ts │ │ │ └── index.d.ts │ │ └── utils │ │ │ ├── data │ │ │ ├── base.ts │ │ │ ├── brief.ts │ │ │ ├── index.ts │ │ │ ├── local.ts │ │ │ └── remote.ts │ │ │ ├── file.tsx │ │ │ ├── hooks.ts │ │ │ ├── i18n │ │ │ ├── cn.ts │ │ │ ├── en.ts │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── loader.ts │ │ │ ├── locale.ts │ │ │ ├── manifest.tsx │ │ │ ├── request.ts │ │ │ ├── routes.ts │ │ │ ├── size.ts │ │ │ ├── socket.ts │ │ │ ├── storage.tsx │ │ │ ├── string.ts │ │ │ ├── time.ts │ │ │ ├── url.ts │ │ │ └── worker │ │ │ ├── index.ts │ │ │ ├── master.ts │ │ │ ├── types.ts │ │ │ ├── utils.ts │ │ │ └── worker.ts │ └── tsconfig.json ├── core │ ├── LICENSE │ ├── README.md │ ├── modern.config.ts │ ├── package.json │ ├── src │ │ ├── build-utils │ │ │ ├── build │ │ │ │ ├── chunks │ │ │ │ │ ├── assetsModules.ts │ │ │ │ │ ├── chunkTransform.ts │ │ │ │ │ ├── generateTileGraph.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── rspack │ │ │ │ │ │ └── transform.ts │ │ │ │ ├── index.ts │ │ │ │ ├── loader │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── probeLoader.ts │ │ │ │ │ └── probeLoaderPlugin.ts │ │ │ │ ├── module-graph │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── parser.ts │ │ │ │ │ ├── rspack │ │ │ │ │ │ └── transform.ts │ │ │ │ │ ├── transform.ts │ │ │ │ │ ├── treeShaking.ts │ │ │ │ │ ├── utils.ts │ │ │ │ │ └── webpack │ │ │ │ │ │ └── transform.ts │ │ │ │ └── utils │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── loader.ts │ │ │ │ │ ├── parseBundle.ts │ │ │ │ │ └── plugin.ts │ │ │ ├── common │ │ │ │ ├── chunks │ │ │ │ │ ├── assetsContent.ts │ │ │ │ │ ├── assetsModules.ts │ │ │ │ │ ├── chunkTransform.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── module-graph │ │ │ │ │ ├── compatible.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── transform.ts │ │ │ │ │ └── utils.ts │ │ │ │ ├── trans-utils │ │ │ │ │ ├── index.ts │ │ │ │ │ └── transStats.ts │ │ │ │ └── webpack │ │ │ │ │ └── compatible.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── inner-plugins │ │ │ ├── constants.ts │ │ │ ├── index.ts │ │ │ ├── loaders │ │ │ │ └── proxy.ts │ │ │ ├── plugins │ │ │ │ ├── base.ts │ │ │ │ ├── bundle.ts │ │ │ │ ├── bundleTagPlugin.ts │ │ │ │ ├── ensureModulesChunkGraph.ts │ │ │ │ ├── errors.ts │ │ │ │ ├── index.ts │ │ │ │ ├── loader.ts │ │ │ │ ├── plugins.ts │ │ │ │ ├── progress.ts │ │ │ │ ├── rspack.ts │ │ │ │ ├── rules.ts │ │ │ │ └── summary.ts │ │ │ └── utils │ │ │ │ ├── circleDetect.ts │ │ │ │ ├── config.ts │ │ │ │ ├── index.ts │ │ │ │ ├── loader.ts │ │ │ │ ├── plugin.ts │ │ │ │ └── sdk.ts │ │ ├── rules │ │ │ ├── index.ts │ │ │ ├── linter.ts │ │ │ ├── rule.ts │ │ │ ├── rules │ │ │ │ ├── cross-chunks-package │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── utils.ts │ │ │ │ ├── default-import-check │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── utils.ts │ │ │ │ ├── duplicate-package │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── utils.ts │ │ │ │ ├── ecma-version-check │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── utils.ts │ │ │ │ ├── index.ts │ │ │ │ └── loader-performance-optimization │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── utils.ts │ │ │ └── utils.ts │ │ └── types │ │ │ ├── chunks.ts │ │ │ ├── declare.d.ts │ │ │ ├── index.ts │ │ │ ├── loader.ts │ │ │ ├── plugin.ts │ │ │ ├── rules.ts │ │ │ └── webpack.ts │ ├── tests │ │ ├── build │ │ │ ├── utils.ts │ │ │ └── utils │ │ │ │ ├── bundles │ │ │ │ ├── validBundleWithArrowFunction.js │ │ │ │ ├── validBundleWithArrowFunction.modules.json │ │ │ │ ├── validBundleWithEsNextFeatures.js │ │ │ │ ├── validBundleWithEsNextFeatures.modules.json │ │ │ │ ├── validCommonBundleWithModulesAsArray.js │ │ │ │ ├── validCommonBundleWithModulesAsArray.modules.json │ │ │ │ ├── validCommonBundleWithModulesAsObject.js │ │ │ │ └── validCommonBundleWithModulesAsObject.modules.json │ │ │ │ ├── loader │ │ │ │ ├── __snapshots__ │ │ │ │ │ ├── changeBuiltinLoader.test.ts.snap │ │ │ │ │ └── changeBuiltinLoaderVue.test.ts.snap │ │ │ │ ├── basic.test.ts │ │ │ │ ├── changeBuiltinLoader.test.ts │ │ │ │ ├── changeBuiltinLoaderVue.test.ts │ │ │ │ ├── createLoaderContextTrap.test.ts │ │ │ │ ├── loadLoaderModule.test.ts │ │ │ │ └── mapEachRules.test.ts │ │ │ │ ├── parseBundle.test.ts │ │ │ │ └── plugin.test.ts │ │ ├── common │ │ │ ├── module-graph │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── transform.test.ts.snap │ │ │ │ └── transform.test.ts │ │ │ └── utils.ts │ │ ├── fixtures │ │ │ ├── assets │ │ │ │ └── webpack-stats.json │ │ │ ├── default-export │ │ │ │ ├── expression │ │ │ │ │ ├── index.js │ │ │ │ │ └── utils.js │ │ │ │ ├── literal │ │ │ │ │ ├── index.js │ │ │ │ │ └── utils.js │ │ │ │ └── variable │ │ │ │ │ ├── index.js │ │ │ │ │ └── utils.js │ │ │ ├── loaders │ │ │ │ ├── basic-loader-esm.js │ │ │ │ ├── basic-loader.js │ │ │ │ ├── pitch-loader-esm.js │ │ │ │ ├── pitch-loader.js │ │ │ │ ├── raw-loader-esm.js │ │ │ │ └── raw-loader.js │ │ │ └── normal-module-in-multi-concatenation │ │ │ │ ├── common.js │ │ │ │ ├── entry1.js │ │ │ │ └── entry2.js │ │ ├── plugins │ │ │ ├── __snapshots__ │ │ │ │ ├── circle-check.test.ts.snap │ │ │ │ └── config.test.ts.snap │ │ │ ├── circle-check.test.ts │ │ │ ├── config.test.ts │ │ │ ├── fixtures │ │ │ │ ├── a.js │ │ │ │ ├── b.js │ │ │ │ └── loaders │ │ │ │ │ ├── comment.js │ │ │ │ │ └── serialize-query-to-comment.js │ │ │ └── loader.test.ts │ │ └── tsconfig.json │ └── tsconfig.json ├── document │ ├── README.md │ ├── docs │ │ ├── en │ │ │ ├── _meta.json │ │ │ ├── blog │ │ │ │ ├── _meta.json │ │ │ │ ├── release │ │ │ │ │ ├── _meta.json │ │ │ │ │ ├── release-note-0_1.mdx │ │ │ │ │ ├── release-note-0_3.mdx │ │ │ │ │ ├── release-note-0_4.mdx │ │ │ │ │ └── release-note-1_0.mdx │ │ │ │ └── topic │ │ │ │ │ ├── _meta.json │ │ │ │ │ ├── duplicate-pkg-problem.mdx │ │ │ │ │ └── loader-optimization.mdx │ │ │ ├── config │ │ │ │ ├── _meta.json │ │ │ │ └── options │ │ │ │ │ ├── _meta.json │ │ │ │ │ ├── options-shared.mdx │ │ │ │ │ ├── options.mdx │ │ │ │ │ └── term.mdx │ │ │ ├── guide │ │ │ │ ├── _meta.json │ │ │ │ ├── more │ │ │ │ │ ├── _meta.json │ │ │ │ │ ├── faq.mdx │ │ │ │ │ └── rules.mdx │ │ │ │ ├── rules │ │ │ │ │ ├── _meta.json │ │ │ │ │ ├── rule-custom.mdx │ │ │ │ │ ├── rules.mdx │ │ │ │ │ └── upload-data.mdx │ │ │ │ ├── start │ │ │ │ │ ├── _meta.json │ │ │ │ │ ├── cicd.mdx │ │ │ │ │ ├── cli.mdx │ │ │ │ │ ├── features.mdx │ │ │ │ │ ├── intro.mdx │ │ │ │ │ ├── quick-start-shared.mdx │ │ │ │ │ └── quick-start.mdx │ │ │ │ └── usage │ │ │ │ │ ├── _meta.json │ │ │ │ │ ├── bundle-alerts.mdx │ │ │ │ │ ├── bundle-diff.mdx │ │ │ │ │ ├── bundle-overall.mdx │ │ │ │ │ ├── bundle-size.mdx │ │ │ │ │ ├── compile-alerts.mdx │ │ │ │ │ ├── compile-overall.mdx │ │ │ │ │ ├── loaders-analysis.mdx │ │ │ │ │ ├── loaders-timeline.mdx │ │ │ │ │ ├── module-analysis.mdx │ │ │ │ │ ├── plugins-analysis.mdx │ │ │ │ │ ├── project-overall.mdx │ │ │ │ │ ├── resolver.mdx │ │ │ │ │ └── rule-config.mdx │ │ │ ├── index.md │ │ │ └── shared │ │ │ │ ├── features-rspack.md │ │ │ │ ├── features.md │ │ │ │ └── mode-intro.md │ │ ├── public │ │ │ └── netlify.toml │ │ └── zh │ │ │ ├── _meta.json │ │ │ ├── blog │ │ │ ├── _meta.json │ │ │ ├── release │ │ │ │ ├── _meta.json │ │ │ │ ├── release-note-0_1.mdx │ │ │ │ ├── release-note-0_3.mdx │ │ │ │ ├── release-note-0_4.mdx │ │ │ │ └── release-note-1_0.mdx │ │ │ └── topic │ │ │ │ ├── _meta.json │ │ │ │ ├── duplicate-pkg-problem.mdx │ │ │ │ └── loader-optimization.mdx │ │ │ ├── config │ │ │ ├── _meta.json │ │ │ └── options │ │ │ │ ├── _meta.json │ │ │ │ ├── options-shared.mdx │ │ │ │ ├── options.mdx │ │ │ │ └── term.mdx │ │ │ ├── guide │ │ │ ├── _meta.json │ │ │ ├── more │ │ │ │ ├── _meta.json │ │ │ │ ├── faq.mdx │ │ │ │ └── rules.mdx │ │ │ ├── rules │ │ │ │ ├── _meta.json │ │ │ │ ├── rule-custom.mdx │ │ │ │ ├── rules.mdx │ │ │ │ └── upload-data.mdx │ │ │ ├── start │ │ │ │ ├── _meta.json │ │ │ │ ├── cicd.mdx │ │ │ │ ├── cli.mdx │ │ │ │ ├── features.mdx │ │ │ │ ├── intro.mdx │ │ │ │ ├── quick-start-shared.mdx │ │ │ │ └── quick-start.mdx │ │ │ └── usage │ │ │ │ ├── _meta.json │ │ │ │ ├── bundle-alerts.mdx │ │ │ │ ├── bundle-diff.mdx │ │ │ │ ├── bundle-overall.mdx │ │ │ │ ├── bundle-size.mdx │ │ │ │ ├── compile-alerts.mdx │ │ │ │ ├── compile-overall.mdx │ │ │ │ ├── loaders-analysis.mdx │ │ │ │ ├── loaders-timeline.mdx │ │ │ │ ├── module-analysis.mdx │ │ │ │ ├── plugins-analysis.mdx │ │ │ │ ├── project-overall.mdx │ │ │ │ ├── resolver.mdx │ │ │ │ └── rule-config.mdx │ │ │ ├── index.md │ │ │ └── shared │ │ │ ├── features-rspack.md │ │ │ ├── features.md │ │ │ └── mode-intro.md │ ├── i18n.json │ ├── package.json │ ├── rspress.config.ts │ ├── theme │ │ ├── components │ │ │ ├── Copyright.module.scss │ │ │ ├── Copyright.tsx │ │ │ ├── Features.module.scss │ │ │ ├── Features.tsx │ │ │ ├── Hero.module.scss │ │ │ ├── Hero.tsx │ │ │ ├── NextSteps.module.scss │ │ │ ├── NextSteps.tsx │ │ │ ├── Overview.module.scss │ │ │ ├── Overview.tsx │ │ │ ├── RuleIndex.module.scss │ │ │ ├── RuleIndex.tsx │ │ │ ├── Step.module.scss │ │ │ ├── Step.tsx │ │ │ ├── ToolStack.tsx │ │ │ └── utils.ts │ │ ├── global.d.ts │ │ ├── index.css │ │ ├── index.tsx │ │ ├── pages │ │ │ └── index.tsx │ │ ├── types.d.ts │ │ └── utils.ts │ └── tsconfig.json ├── graph │ ├── LICENSE │ ├── README.md │ ├── modern.config.ts │ ├── package.json │ ├── src │ │ ├── graph │ │ │ ├── chunk-graph │ │ │ │ ├── asset.ts │ │ │ │ ├── chunk.ts │ │ │ │ ├── entrypoint.ts │ │ │ │ ├── graph.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── module-graph │ │ │ │ ├── dependency.ts │ │ │ │ ├── graph.ts │ │ │ │ ├── index.ts │ │ │ │ ├── module.ts │ │ │ │ ├── statement.ts │ │ │ │ ├── tree-shaking │ │ │ │ │ ├── export.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── module.ts │ │ │ │ │ ├── sideEffect.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── variable.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ │ └── package-graph │ │ │ │ ├── dependency.ts │ │ │ │ ├── graph.ts │ │ │ │ ├── index.ts │ │ │ │ ├── package.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ └── index.ts │ ├── tests │ │ ├── __snapshots__ │ │ │ ├── module-graph.test.ts.snap │ │ │ └── utils.test.ts.snap │ │ ├── fixture │ │ │ ├── index │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── module-graph-basic.json │ │ │ └── package.json │ │ ├── module-graph.test.ts │ │ ├── utils.test.ts │ │ └── utils.ts │ └── tsconfig.json ├── rspack-plugin │ ├── LICENSE │ ├── README.md │ ├── modern.config.ts │ ├── package.json │ ├── src │ │ ├── constants.ts │ │ ├── index.ts │ │ ├── multiple.ts │ │ ├── plugin.ts │ │ └── types │ │ │ └── index.ts │ ├── tsconfig.build.json │ └── tsconfig.json ├── sdk │ ├── LICENSE │ ├── README.md │ ├── modern.config.ts │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── sdk │ │ │ ├── index.ts │ │ │ ├── multiple │ │ │ ├── controller.ts │ │ │ ├── index.ts │ │ │ ├── primary.ts │ │ │ └── server.ts │ │ │ ├── sdk │ │ │ ├── core.ts │ │ │ ├── index.ts │ │ │ └── types.ts │ │ │ ├── server │ │ │ ├── apis │ │ │ │ ├── alerts.ts │ │ │ │ ├── base.ts │ │ │ │ ├── bundle-diff.ts │ │ │ │ ├── data.ts │ │ │ │ ├── fs.ts │ │ │ │ ├── graph.ts │ │ │ │ ├── index.ts │ │ │ │ ├── loader.ts │ │ │ │ ├── plugin.ts │ │ │ │ ├── project.ts │ │ │ │ ├── renderer.ts │ │ │ │ └── resolver.ts │ │ │ ├── fakeServer.ts │ │ │ ├── index.ts │ │ │ ├── router.ts │ │ │ ├── socket │ │ │ │ ├── api.ts │ │ │ │ └── index.ts │ │ │ └── utils.ts │ │ │ └── utils │ │ │ ├── constant.ts │ │ │ ├── index.ts │ │ │ ├── openBrowser.ts │ │ │ └── upload.ts │ ├── static │ │ └── openChrome.applescript │ ├── tests │ │ ├── __snapshots__ │ │ │ └── module-graph.test.ts.snap │ │ ├── fixture │ │ │ └── module-graph-basic.json │ │ ├── module-graph.test.ts │ │ ├── sdk │ │ │ └── core │ │ │ │ └── hooks.test.ts │ │ ├── server │ │ │ ├── apis │ │ │ │ ├── data.test.ts │ │ │ │ ├── fs.test.ts │ │ │ │ ├── index.test.ts │ │ │ │ ├── project.test.ts │ │ │ │ └── renderer.test.ts │ │ │ └── utils.test.ts │ │ └── utils.ts │ └── tsconfig.json ├── types │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ ├── babel.ts │ │ ├── client.ts │ │ ├── common.ts │ │ ├── constants.ts │ │ ├── emo.ts │ │ ├── error.ts │ │ ├── esbuild.ts │ │ ├── index.ts │ │ ├── linter │ │ │ ├── diagnostic.ts │ │ │ ├── index.ts │ │ │ └── rule.ts │ │ ├── logger.ts │ │ ├── manifest.ts │ │ ├── modules.ts │ │ ├── plugin │ │ │ ├── baseCompiler.ts │ │ │ ├── baseLoader.ts │ │ │ ├── baseStats.ts │ │ │ ├── index.ts │ │ │ ├── plugin.ts │ │ │ └── rspack.ts │ │ ├── rule │ │ │ ├── code │ │ │ │ ├── E1001.ts │ │ │ │ ├── E1002.ts │ │ │ │ ├── E1003.ts │ │ │ │ ├── E1004.ts │ │ │ │ ├── E1005.ts │ │ │ │ ├── index.ts │ │ │ │ └── type.ts │ │ │ ├── data.ts │ │ │ └── index.ts │ │ ├── sdk │ │ │ ├── chunk.ts │ │ │ ├── config.ts │ │ │ ├── context.ts │ │ │ ├── envinfo.ts │ │ │ ├── hooks.ts │ │ │ ├── index.ts │ │ │ ├── instance.ts │ │ │ ├── loader.ts │ │ │ ├── module.ts │ │ │ ├── package.ts │ │ │ ├── plugin.ts │ │ │ ├── process.ts │ │ │ ├── resolver.ts │ │ │ ├── result.ts │ │ │ ├── server │ │ │ │ ├── apis │ │ │ │ │ ├── alerts.ts │ │ │ │ │ ├── graph.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── loader.ts │ │ │ │ │ ├── pagination.ts │ │ │ │ │ ├── plugin.ts │ │ │ │ │ ├── project.ts │ │ │ │ │ └── resolver.ts │ │ │ │ └── index.ts │ │ │ ├── statement.ts │ │ │ ├── summary.ts │ │ │ └── treeShaking.ts │ │ └── thirdparty.ts │ └── tsconfig.json ├── utils │ ├── LICENSE │ ├── README.md │ ├── modern.config.ts │ ├── package.json │ ├── src │ │ ├── build │ │ │ ├── envinfo.ts │ │ │ ├── file │ │ │ │ ├── cache.ts │ │ │ │ ├── index.ts │ │ │ │ └── sharding.ts │ │ │ ├── index.ts │ │ │ ├── json.ts │ │ │ ├── process.ts │ │ │ └── server.ts │ │ ├── common │ │ │ ├── alerts.ts │ │ │ ├── algorithm.ts │ │ │ ├── bundle.ts │ │ │ ├── crypto.ts │ │ │ ├── data │ │ │ │ └── index.ts │ │ │ ├── global-config.ts │ │ │ ├── graph │ │ │ │ ├── assets.ts │ │ │ │ ├── chunk.ts │ │ │ │ ├── dependency.ts │ │ │ │ ├── entrypoints.ts │ │ │ │ ├── index.ts │ │ │ │ └── modules.ts │ │ │ ├── index.ts │ │ │ ├── loader.ts │ │ │ ├── lodash.ts │ │ │ ├── manifest.ts │ │ │ ├── package.ts │ │ │ ├── plugin.ts │ │ │ ├── resolver.ts │ │ │ ├── rspack.ts │ │ │ ├── summary.ts │ │ │ ├── time.ts │ │ │ └── url.ts │ │ ├── error │ │ │ ├── error.ts │ │ │ ├── index.ts │ │ │ ├── transform.ts │ │ │ └── utils.ts │ │ ├── index.ts │ │ ├── logger.ts │ │ ├── rule-utils │ │ │ ├── document │ │ │ │ ├── document.ts │ │ │ │ ├── index.ts │ │ │ │ ├── server.ts │ │ │ │ └── types.ts │ │ │ ├── index.ts │ │ │ └── parser │ │ │ │ ├── asserts.ts │ │ │ │ ├── index.ts │ │ │ │ ├── parser.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ └── typings │ │ │ └── index.d.ts │ ├── tests │ │ ├── __snapshots__ │ │ │ ├── crypto.test.ts.snap │ │ │ └── json.test.ts.snap │ │ ├── build │ │ │ └── time.test.ts │ │ ├── common │ │ │ ├── algorithm.test.ts │ │ │ ├── bundle.test.ts │ │ │ ├── data.test.ts │ │ │ ├── graph.test.ts │ │ │ ├── manifest.test.ts │ │ │ ├── plugin.test.ts │ │ │ ├── resolver.test.ts │ │ │ ├── time.test.ts │ │ │ └── url.test.ts │ │ ├── crypto.test.ts │ │ ├── file │ │ │ └── sharding.test.ts │ │ ├── json.test.ts │ │ ├── parser │ │ │ └── parser.test.ts │ │ └── server.test.ts │ └── tsconfig.json └── webpack-plugin │ ├── LICENSE │ ├── README.md │ ├── modern.config.ts │ ├── package.json │ ├── src │ ├── constants.ts │ ├── index.ts │ ├── multiple.ts │ ├── plugin.ts │ └── plugins │ │ └── resolver.ts │ ├── tests │ ├── multiple.test.ts │ ├── multipleWithStage.test.ts │ ├── test-utils.ts │ └── tsconfig.json │ ├── tsconfig.build.json │ └── tsconfig.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── scripts ├── dictionary.txt ├── modern.base.config.ts ├── requireShims.js ├── skipCI.js ├── test-helper │ ├── modern.config.ts │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── path.ts │ │ ├── pathSerializer.ts │ │ ├── rsbuild.ts │ │ ├── rspack.ts │ │ └── webpack.ts │ └── tsconfig.json ├── tsconfig │ ├── base.json │ └── package.json └── vitest.setup.ts └── vitest.workspace.ts /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json", 3 | "changelog": false, 4 | "commit": false, 5 | "linked": [], 6 | "access": "restricted", 7 | "baseBranch": "main", 8 | "fixed": [["@rsdoctor/*", "!@rsdoctor/mcp-server"]], 9 | "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { 10 | "onlyUpdatePeerDependentsWhenOutOfRange": true, 11 | "updateInternalDependents": "always" 12 | }, 13 | "updateInternalDependencies": "patch", 14 | "ignore": [] 15 | } 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | pnpm-lock.yaml merge=ours -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Ask a question 4 | url: https://github.com/web-infra-dev/rsdoctor/discussions 5 | about: Ask a question about Rsdoctor 6 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Summary 2 | 3 | ## Related Links 4 | 5 | 6 | -------------------------------------------------------------------------------- /.github/pr-labeler.yml: -------------------------------------------------------------------------------- 1 | "change: feat": 2 | - "/^(feat|types|style)/" 3 | "change: fix": 4 | - "/^fix/" 5 | "change: perf": 6 | - "/^perf/" 7 | "change: breaking": 8 | - "/^breaking change/" 9 | "change: docs": 10 | - "/^docs/" 11 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | # .github/release.yml 2 | 3 | changelog: 4 | exclude: 5 | authors: 6 | # Ignore the release PR created by github-actions 7 | - github-actions 8 | categories: 9 | - title: Breaking Changes 🍭 10 | labels: 11 | - "change: breaking" 12 | - title: New Features 🎉 13 | labels: 14 | - "change: feat" 15 | - title: Performance 🚀 16 | labels: 17 | - "change: perf" 18 | - title: Bug Fixes 🐞 19 | labels: 20 | - "change: fix" 21 | - title: Document 📖 22 | labels: 23 | - "change: docs" 24 | - title: Other Changes 25 | labels: 26 | - "*" 27 | -------------------------------------------------------------------------------- /.github/workflows/pr-label.yaml: -------------------------------------------------------------------------------- 1 | name: PR Labeler 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | 9 | permissions: 10 | pull-requests: write 11 | contents: read 12 | 13 | jobs: 14 | change-labeling: 15 | name: Labeling for changes 16 | runs-on: ubuntu-latest 17 | if: github.repository == 'web-infra-dev/rsdoctor' 18 | steps: 19 | - uses: github/issue-labeler@c1b0f9f52a63158c4adc09425e858e87b32e9685 # v3.4 20 | with: 21 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 22 | configuration-path: .github/pr-labeler.yml 23 | enable-versioned-regex: 0 24 | include-title: 1 25 | sync-labels: 1 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.log* 3 | *.cpuprofile 4 | node_modules/ 5 | *.tsbuildinfo 6 | 7 | dist/ 8 | dist-* 9 | !**/rslog/dist 10 | coverage/ 11 | doc_build/ 12 | playwright-report/ 13 | tsconfig.tsbuildinfo 14 | 15 | .vscode/**/* 16 | !.vscode/settings.json 17 | !.vscode/extensions.json 18 | .idea/ 19 | .nx/ 20 | .history/ 21 | .env.local 22 | .env.*.local 23 | 24 | log/ 25 | 26 | .cursor/ 27 | -------------------------------------------------------------------------------- /.husky/post-checkout: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -f "$HUSKY_SCRIPT" ]; then 4 | . "$HUSKY_SCRIPT" 5 | # avoid conflicts in pnpm lock 6 | # https://7tonshark.com/posts/avoid-conflicts-in-pnpm-lock/ 7 | git config merge.ours.driver true 8 | else 9 | exit 0 10 | fi 11 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | npx --no-install nano-staged 4 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry = 'https://registry.npmjs.org/' 2 | strict-peer-dependencies=false 3 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/jod 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore artifacts: 2 | dist 3 | compiled 4 | doc_build 5 | pnpm-lock.yaml 6 | 7 | **/doctor-core/**/tests 8 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "biomejs.biome", 4 | "esbenp.prettier-vscode", 5 | "streetsidesoftware.code-spell-checker" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "search.useIgnoreFiles": true, 3 | "search.exclude": { 4 | "**/.git": true, 5 | "**/dist": true, 6 | "**/coverage": true, 7 | "**/compiled": true, 8 | "**/doc_build": true, 9 | "**/node_modules": true, 10 | "**/tsconfig.tsbuildinfo": true 11 | }, 12 | "files.exclude": { 13 | "**/.DS_Store": true 14 | }, 15 | "editor.defaultFormatter": "biomejs.biome", 16 | "editor.defaultFoldingRangeProvider": "biomejs.biome", 17 | "[yaml]": { 18 | "editor.defaultFormatter": "esbenp.prettier-vscode" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security 2 | 3 | ## Reporting a vulnerability in Rsdoctor 4 | 5 | Report a security vulnerability in Rsdoctor via web-infra-security@bytedance.com. 6 | 7 | Normally, your report will be acknowledged within 24 hours, and you'll receive a more detailed response to your report within 5 days indicating the next steps in handling your submission. 8 | 9 | After the initial reply to your report, the security team will endeavor to keep you informed of the progress being made towards a fix and full announcement, and may ask for additional information or guidance surrounding the reported issue. 10 | -------------------------------------------------------------------------------- /cspell.config.cjs: -------------------------------------------------------------------------------- 1 | const { banWords } = require('cspell-ban-words'); 2 | 3 | module.exports = { 4 | version: '0.2', 5 | language: 'en', 6 | files: ['**/*.{ts,tsx,js,jsx,md,mdx}'], 7 | enableFiletypes: ['mdx'], 8 | ignoreRegExpList: [ 9 | // ignore markdown anchors such as [fooBar](#foobar) 10 | '#.*?\\)', 11 | ], 12 | ignorePaths: [ 13 | 'dist', 14 | 'dist-*', 15 | 'compiled', 16 | 'coverage', 17 | 'doc_build', 18 | 'node_modules', 19 | 'pnpm-lock.yaml', 20 | ], 21 | flagWords: banWords, 22 | dictionaries: ['dictionary'], 23 | dictionaryDefinitions: [ 24 | { 25 | name: 'dictionary', 26 | path: './scripts/dictionary.txt', 27 | addWords: true, 28 | }, 29 | ], 30 | }; 31 | -------------------------------------------------------------------------------- /e2e/cases/doctor-rsbuild/fixtures/a.js: -------------------------------------------------------------------------------- 1 | console.log('a'); 2 | -------------------------------------------------------------------------------- /e2e/cases/doctor-rsbuild/fixtures/b.js: -------------------------------------------------------------------------------- 1 | const ll = 1; 2 | 3 | console.log('a'); 4 | 5 | function kk() { 6 | console.log('hhe: ', ll); 7 | return '111'; 8 | } 9 | 10 | kk(); 11 | -------------------------------------------------------------------------------- /e2e/cases/doctor-rsbuild/fixtures/loaders/serialize-query-to-comment.js: -------------------------------------------------------------------------------- 1 | const { parseQuery } = require('loader-utils'); 2 | 3 | /** 4 | * @type {import("webpack").LoaderDefinitionFunction<{}, {}>} 5 | */ 6 | module.exports = function (input) { 7 | const res = [input, `// ${JSON.stringify(this.query)}`]; 8 | 9 | // Based on https://github.com/windicss/windicss-webpack-plugin/blob/main/src/loaders/windicss-template.ts#L42 10 | // test the loader query 11 | if (this.query !== '') { 12 | res.push(`// ${JSON.stringify(parseQuery(this.query))}`); 13 | } 14 | 15 | return res.join('\n'); 16 | }; 17 | -------------------------------------------------------------------------------- /e2e/cases/doctor-rsbuild/fixtures/loaders/serialize-resource-query-to-comment.js: -------------------------------------------------------------------------------- 1 | const { parseQuery } = require('loader-utils'); 2 | 3 | /** 4 | * @type {import("webpack").LoaderDefinitionFunction<{}, {}>} 5 | */ 6 | module.exports = function (input) { 7 | const res = [input, `// ${JSON.stringify(this.resourceQuery)}`]; 8 | 9 | // Based on https://github.com/windicss/windicss-webpack-plugin/blob/main/src/loaders/windicss-template.ts#L42 10 | // test the loader query 11 | if (this.resourceQuery !== '') { 12 | res.push(`// ${JSON.stringify(parseQuery(this.resourceQuery))}`); 13 | } 14 | 15 | return res.join('\n'); 16 | }; 17 | -------------------------------------------------------------------------------- /e2e/cases/doctor-rsbuild/fixtures/port.js: -------------------------------------------------------------------------------- 1 | const { RsdoctorWebpackPlugin } = require('../../dist/index'); 2 | 3 | const plugin = new RsdoctorWebpackPlugin({}); 4 | 5 | plugin.sdk.bootstrap().then(() => { 6 | console.log(plugin.sdk.server.port); 7 | }); 8 | -------------------------------------------------------------------------------- /e2e/cases/doctor-rspack/fixtures/a.js: -------------------------------------------------------------------------------- 1 | console.log('a'); 2 | 3 | const { a } = require('./index'); 4 | console.log(a); -------------------------------------------------------------------------------- /e2e/cases/doctor-rspack/fixtures/b.js: -------------------------------------------------------------------------------- 1 | const ll = 1; 2 | 3 | console.log('a'); 4 | 5 | function kk() { 6 | console.log('hhe: ', ll); 7 | return '111'; 8 | } 9 | 10 | kk(); 11 | -------------------------------------------------------------------------------- /e2e/cases/doctor-rspack/fixtures/c.js: -------------------------------------------------------------------------------- 1 | const c = 1; 2 | -------------------------------------------------------------------------------- /e2e/cases/doctor-rspack/fixtures/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 18; 3 | } 4 | -------------------------------------------------------------------------------- /e2e/cases/doctor-rspack/fixtures/index.ts: -------------------------------------------------------------------------------- 1 | export const a = 1; -------------------------------------------------------------------------------- /e2e/cases/doctor-rspack/fixtures/loaders/esm-serialize-query-to-comment.mjs: -------------------------------------------------------------------------------- 1 | import { parseQuery } from 'loader-utils'; 2 | 3 | /** 4 | * @type {import("webpack").LoaderDefinitionFunction<{}, {}>} 5 | */ 6 | const loader = (input) => { 7 | const res = [input, `// ${JSON.stringify(this?.query || '')}`]; 8 | 9 | // Based on https://github.com/windicss/windicss-webpack-plugin/blob/main/src/loaders/windicss-template.ts#L42 10 | // test the loader query 11 | if (this?.query && this?.query !== '') { 12 | res.push(`// ${JSON.stringify(parseQuery(this?.query))}`); 13 | } 14 | 15 | return res.join('\n'); 16 | }; 17 | 18 | export default loader; 19 | -------------------------------------------------------------------------------- /e2e/cases/doctor-rspack/fixtures/loaders/esm/esm-serialize-query-to-comment.js: -------------------------------------------------------------------------------- 1 | import { parseQuery } from 'loader-utils'; 2 | 3 | /** 4 | * @type {import("webpack").LoaderDefinitionFunction<{}, {}>} 5 | */ 6 | const loader = (input) => { 7 | const res = [input, `// ${JSON.stringify(this?.query || '')}`]; 8 | 9 | // Based on https://github.com/windicss/windicss-webpack-plugin/blob/main/src/loaders/windicss-template.ts#L42 10 | // test the loader query 11 | if (this?.query && this?.query !== '') { 12 | res.push(`// ${JSON.stringify(parseQuery(this?.query))}`); 13 | } 14 | 15 | return res.join('\n'); 16 | }; 17 | 18 | export default loader; 19 | -------------------------------------------------------------------------------- /e2e/cases/doctor-rspack/fixtures/loaders/esm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "@test/rsdoctor-rspack", 4 | "version": "0.1.0", 5 | "type": "module" 6 | } 7 | -------------------------------------------------------------------------------- /e2e/cases/doctor-rspack/fixtures/loaders/serialize-query-to-comment.js: -------------------------------------------------------------------------------- 1 | const { parseQuery } = require('loader-utils'); 2 | 3 | /** 4 | * @type {import("webpack").LoaderDefinitionFunction<{}, {}>} 5 | */ 6 | module.exports = function (input) { 7 | const res = [input, `// ${JSON.stringify(this.query)}`]; 8 | 9 | // Based on https://github.com/windicss/windicss-webpack-plugin/blob/main/src/loaders/windicss-template.ts#L42 10 | // test the loader query 11 | if (this.query !== '') { 12 | res.push(`// ${JSON.stringify(parseQuery(this.query))}`); 13 | } 14 | 15 | return res.join('\n'); 16 | }; 17 | -------------------------------------------------------------------------------- /e2e/cases/doctor-rspack/fixtures/port.js: -------------------------------------------------------------------------------- 1 | const { RsdoctorRspackPlugin } = require('../../../dist/index'); 2 | 3 | const plugin = new RsdoctorRspackPlugin({}); 4 | 5 | plugin.sdk.bootstrap().then(() => { 6 | console.log(plugin.sdk.server.port); 7 | }); 8 | -------------------------------------------------------------------------------- /e2e/cases/doctor-webpack/fixtures/a.js: -------------------------------------------------------------------------------- 1 | console.log('a'); 2 | -------------------------------------------------------------------------------- /e2e/cases/doctor-webpack/fixtures/b.js: -------------------------------------------------------------------------------- 1 | const ll = 1; 2 | 3 | console.log('a'); 4 | 5 | function kk() { 6 | console.log('hhe: ', ll); 7 | return '111'; 8 | } 9 | 10 | kk(); 11 | -------------------------------------------------------------------------------- /e2e/cases/doctor-webpack/fixtures/loaders/serialize-query-to-comment.js: -------------------------------------------------------------------------------- 1 | const { parseQuery } = require('loader-utils'); 2 | 3 | /** 4 | * @type {import("webpack").LoaderDefinitionFunction<{}, {}>} 5 | */ 6 | module.exports = function (input) { 7 | const res = [input, `// ${JSON.stringify(this.query)}`]; 8 | 9 | // Based on https://github.com/windicss/windicss-webpack-plugin/blob/main/src/loaders/windicss-template.ts#L42 10 | // test the loader query 11 | if (this.query !== '') { 12 | res.push(`// ${JSON.stringify(parseQuery(this.query))}`); 13 | } 14 | 15 | return res.join('\n'); 16 | }; 17 | -------------------------------------------------------------------------------- /e2e/cases/doctor-webpack/fixtures/loaders/serialize-resource-query-to-comment.js: -------------------------------------------------------------------------------- 1 | const { parseQuery } = require('loader-utils'); 2 | 3 | /** 4 | * @type {import("webpack").LoaderDefinitionFunction<{}, {}>} 5 | */ 6 | module.exports = function (input) { 7 | const res = [input, `// ${JSON.stringify(this.resourceQuery)}`]; 8 | 9 | // Based on https://github.com/windicss/windicss-webpack-plugin/blob/main/src/loaders/windicss-template.ts#L42 10 | // test the loader query 11 | if (this.resourceQuery !== '') { 12 | res.push(`// ${JSON.stringify(parseQuery(this.resourceQuery))}`); 13 | } 14 | 15 | return res.join('\n'); 16 | }; 17 | -------------------------------------------------------------------------------- /e2e/cases/doctor-webpack/fixtures/port.js: -------------------------------------------------------------------------------- 1 | const { RsdoctorWebpackPlugin } = require('../../dist/index'); 2 | 3 | const plugin = new RsdoctorWebpackPlugin({}); 4 | 5 | plugin.sdk.bootstrap().then(() => { 6 | console.log(plugin.sdk.server.port); 7 | }); 8 | -------------------------------------------------------------------------------- /e2e/cases/doctor-webpack/fixtures2/a.js: -------------------------------------------------------------------------------- 1 | console.log('a'); 2 | -------------------------------------------------------------------------------- /e2e/cases/doctor-webpack/fixtures2/b.js: -------------------------------------------------------------------------------- 1 | import './index.less'; 2 | 3 | const ll = 1; 4 | 5 | console.log('a'); 6 | 7 | function kk() { 8 | console.log('hhe: ', ll); 9 | return '111'; 10 | } 11 | 12 | kk(); 13 | -------------------------------------------------------------------------------- /e2e/cases/doctor-webpack/fixtures2/index.less: -------------------------------------------------------------------------------- 1 | .nav { 2 | color: antiquewhite; 3 | } 4 | -------------------------------------------------------------------------------- /e2e/cases/doctor-webpack/fixtures2/loaders/serialize-query-to-comment.js: -------------------------------------------------------------------------------- 1 | const { parseQuery } = require('loader-utils'); 2 | 3 | /** 4 | * @type {import("webpack").LoaderDefinitionFunction<{}, {}>} 5 | */ 6 | module.exports = function (input) { 7 | const res = [input, `// ${JSON.stringify(this.query)}`]; 8 | 9 | // Based on https://github.com/windicss/windicss-webpack-plugin/blob/main/src/loaders/windicss-template.ts#L42 10 | // test the loader query 11 | if (this.query !== '') { 12 | res.push(`// ${JSON.stringify(parseQuery(this.query))}`); 13 | } 14 | 15 | return res.join('\n'); 16 | }; 17 | -------------------------------------------------------------------------------- /e2e/cases/doctor-webpack/fixtures2/loaders/serialize-resource-query-to-comment.js: -------------------------------------------------------------------------------- 1 | const { parseQuery } = require('loader-utils'); 2 | 3 | /** 4 | * @type {import("webpack").LoaderDefinitionFunction<{}, {}>} 5 | */ 6 | module.exports = function (input) { 7 | const res = [input, `// ${JSON.stringify(this.resourceQuery)}`]; 8 | 9 | // Based on https://github.com/windicss/windicss-webpack-plugin/blob/main/src/loaders/windicss-template.ts#L42 10 | // test the loader query 11 | if (this.resourceQuery !== '') { 12 | res.push(`// ${JSON.stringify(parseQuery(this.resourceQuery))}`); 13 | } 14 | 15 | return res.join('\n'); 16 | }; 17 | -------------------------------------------------------------------------------- /e2e/cases/doctor-webpack/fixtures2/port.js: -------------------------------------------------------------------------------- 1 | const { RsdoctorWebpackPlugin } = require('../../dist/index'); 2 | 3 | const plugin = new RsdoctorWebpackPlugin({}); 4 | 5 | plugin.sdk.bootstrap().then(() => { 6 | console.log(plugin.sdk.server.port); 7 | }); 8 | -------------------------------------------------------------------------------- /e2e/fixtures/rsdoctor/envinfo/0: -------------------------------------------------------------------------------- 1 | eJxVy70KwjAUBtBXuXyTQrgmoaZpNjvoFEf3YjMI5ofUQov47uKkrgfOE9cyw2Gj9JYW09ChlHsgr8kPCwRiiLmucDC6ZduS72lHpmEp6dRDIOUxXEKdbjnBQVlWHUsIrENNXz/nBx3znMbPKPEnSLasIVD+2LLac4fXG5saLO4= -------------------------------------------------------------------------------- /e2e/fixtures/rsdoctor/errors/0: -------------------------------------------------------------------------------- 1 | eJyLjgUAARUAuQ== -------------------------------------------------------------------------------- /e2e/fixtures/rsdoctor/loader/0: -------------------------------------------------------------------------------- 1 | eJyLjgUAARUAuQ== -------------------------------------------------------------------------------- /e2e/fixtures/rsdoctor/moduleCodeMap/0: -------------------------------------------------------------------------------- 1 | eJyLjgUAARUAuQ== -------------------------------------------------------------------------------- /e2e/fixtures/rsdoctor/moduleGraph/0: -------------------------------------------------------------------------------- 1 | eJyLjgUAARUAuQ== -------------------------------------------------------------------------------- /e2e/fixtures/rsdoctor/otherReports/0: -------------------------------------------------------------------------------- 1 | eJyLjgUAARUAuQ== -------------------------------------------------------------------------------- /e2e/fixtures/rsdoctor/packageGraph/0: -------------------------------------------------------------------------------- 1 | eJyLjgUAARUAuQ== -------------------------------------------------------------------------------- /e2e/fixtures/rsdoctor/plugin/0: -------------------------------------------------------------------------------- 1 | eJyLjgUAARUAuQ== -------------------------------------------------------------------------------- /e2e/fixtures/rsdoctor/resolver/0: -------------------------------------------------------------------------------- 1 | eJyLjgUAARUAuQ== -------------------------------------------------------------------------------- /e2e/fixtures/rsdoctor/summary/0: -------------------------------------------------------------------------------- 1 | eJx90E0KwjAQBeC7ZKXQQtK/NFkUxGOIi7ROMWibkBkRrb27CNVWELdveB+PGVjjkJDp3cB60wHTrHaOkILxcVVD6wJsXeftGVjEkEygDTEtZFKIlPMiL7MsehtCFEqM0Swt63FlWoLwB5MyT4sPlohSJQts2Y6rg+t/GkplSTkbnKcLorO9bW+rK9TeNKdMO0+2s3fYHi/9aYMIhI/pmGsfXAOIUxzwlX6H658DBJfzR6SSfNyPTzUAdNU= -------------------------------------------------------------------------------- /e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@playwright/test'; 2 | 3 | export default defineConfig({ 4 | testMatch: ['/cases/**/**.test.ts'], 5 | timeout: 60000, 6 | }); 7 | -------------------------------------------------------------------------------- /e2e/test-kit/launch.ts: -------------------------------------------------------------------------------- 1 | import { chromium } from '@playwright/test'; 2 | 3 | export async function launchPlaywright() { 4 | const browser = await chromium.launch(); 5 | 6 | const page = await browser.newPage(); 7 | 8 | return { 9 | browser, 10 | page, 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /e2e/test-kit/path.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path'; 2 | 3 | export function getFixtures(name: string) { 4 | return resolve(__dirname, '../fixtures', name); 5 | } 6 | 7 | export function getRsdoctorManifestPath() { 8 | const testManifestUrl = getFixtures('rsdoctor/manifest.json'); 9 | return testManifestUrl; 10 | } 11 | -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "compilerOptions": { 4 | "jsx": "react-jsx", 5 | "baseUrl": "./", 6 | "outDir": "./dist", 7 | "paths": { 8 | "@/*": ["./src/*"], 9 | "@scripts/*": ["./scripts/*"] 10 | } 11 | }, 12 | "include": ["src", "scripts", "cases", "playwright.config.ts", "test-kit"] 13 | } 14 | -------------------------------------------------------------------------------- /examples/modern-minimal/src/myapp/routes/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | } 6 | -------------------------------------------------------------------------------- /examples/modern-minimal/src/myapp/routes/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Outlet } from '@modern-js/runtime/router'; 2 | 3 | const { Radio } = await import('antd'); 4 | 5 | const Layout = (): JSX.Element => ( 6 |
7 | 8 | Radio 9 |
10 | ); 11 | 12 | export default Layout; 13 | -------------------------------------------------------------------------------- /examples/modern-minimal/src/myapp/routes/page.tsx: -------------------------------------------------------------------------------- 1 | import { Helmet } from '@modern-js/runtime/head'; 2 | import './index.css'; 3 | 4 | const Index = (): JSX.Element => ( 5 |
6 | 7 | Hello world 8 |
9 | ); 10 | 11 | export default Index; 12 | -------------------------------------------------------------------------------- /examples/modern-minimal/src/myapp2/routes/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | } 6 | -------------------------------------------------------------------------------- /examples/modern-minimal/src/myapp2/routes/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Outlet } from '@modern-js/runtime/router'; 2 | 3 | const { Radio } = await import('antd'); 4 | 5 | const Layout = (): JSX.Element => ( 6 |
7 | 8 | Radio 9 |
10 | ); 11 | 12 | export default Layout; 13 | -------------------------------------------------------------------------------- /examples/modern-minimal/src/myapp2/routes/page.tsx: -------------------------------------------------------------------------------- 1 | import { Helmet } from '@modern-js/runtime/head'; 2 | import './index.css'; 3 | 4 | const Index = (): JSX.Element => ( 5 |
6 | 7 | Hello world 8 |
9 | ); 10 | 11 | export default Index; 12 | -------------------------------------------------------------------------------- /examples/modern-minimal/src/utils/utils.ts: -------------------------------------------------------------------------------- 1 | export const key1 = '123'; 2 | export const key2 = '123'; 3 | 4 | console.log(key2); 5 | -------------------------------------------------------------------------------- /examples/modern-minimal/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "outDir": "dist", 6 | "baseUrl": ".", 7 | "module": "ESNext" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/multiple-minimal/src/app.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from '@arco-design/web-react'; 3 | import '@arco-design/web-react/dist/css/arco.css'; 4 | import styles from './index.module.less'; 5 | 6 | export function App({ name }: any) { 7 | return ( 8 | <> 9 | Hello {name}. Welcome! 10 | <> 11 |

标题{name}

12 |

内容

13 | , 14 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /examples/multiple-minimal/src/declaration.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | const content: React.FunctionComponent>; 3 | export default content; 4 | } 5 | 6 | declare module '*.less' { 7 | const classes: { [className: string]: string }; 8 | export default classes; 9 | } 10 | 11 | declare module '*/settings.json' { 12 | const value: { 13 | colorWeek: boolean; 14 | navbar: boolean; 15 | menu: boolean; 16 | footer: boolean; 17 | themeColor: string; 18 | menuWidth: number; 19 | }; 20 | 21 | export default value; 22 | } 23 | 24 | declare module '*.png' { 25 | const value: string; 26 | export default value; 27 | } 28 | -------------------------------------------------------------------------------- /examples/multiple-minimal/src/index.module.less: -------------------------------------------------------------------------------- 1 | .header { 2 | background: var(--color-bg-2); 3 | padding: 20px; 4 | } 5 | -------------------------------------------------------------------------------- /examples/multiple-minimal/src/index.ts: -------------------------------------------------------------------------------- 1 | import { render } from 'react-dom'; 2 | import { createElement } from 'react'; 3 | 4 | import { App } from './app'; 5 | 6 | render( 7 | createElement(App, { name: 'Taylor' }), 8 | document.getElementById('root')!, 9 | ); 10 | -------------------------------------------------------------------------------- /examples/multiple-minimal/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "include": ["src", "webpack.config.ts"], 4 | "compilerOptions": { 5 | "moduleResolution": "NodeNext", 6 | "outDir": "dist", 7 | "baseUrl": ".", 8 | "module": "NodeNext", 9 | "jsx": "react", 10 | "lib": ["DOM"] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/rsbuild-minimal/src/App.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | color: #fff; 4 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif; 5 | background-image: linear-gradient(to bottom, #020917, #101725); 6 | } 7 | 8 | .content { 9 | display: flex; 10 | min-height: 100vh; 11 | line-height: 1.1; 12 | text-align: center; 13 | flex-direction: column; 14 | justify-content: center; 15 | } 16 | 17 | .content h1 { 18 | font-size: 3.6rem; 19 | font-weight: 700; 20 | } 21 | 22 | .content p { 23 | font-size: 1.2rem; 24 | font-weight: 400; 25 | opacity: 0.5; 26 | } 27 | -------------------------------------------------------------------------------- /examples/rsbuild-minimal/src/App.tsx: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import './semver'; 3 | import './semver7'; 4 | 5 | const App = () => { 6 | return ( 7 | <> 8 |
9 |

Rsbuild with React

10 |

Start building amazing things with Rsbuild.

11 |
12 | 15 | 16 | ); 17 | }; 18 | 19 | export default App; 20 | -------------------------------------------------------------------------------- /examples/rsbuild-minimal/src/button.css: -------------------------------------------------------------------------------- 1 | .button { 2 | display: flex; 3 | min-height: 100vh; 4 | line-height: 1.1; 5 | text-align: center; 6 | flex-direction: column; 7 | justify-content: center; 8 | } 9 | 10 | -------------------------------------------------------------------------------- /examples/rsbuild-minimal/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/rsbuild-minimal/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import App from './App'; 4 | 5 | const root = ReactDOM.createRoot(document.getElementById('root')!); 6 | root.render( 7 | 8 | 9 | , 10 | ); 11 | -------------------------------------------------------------------------------- /examples/rsbuild-minimal/src/semver.ts: -------------------------------------------------------------------------------- 1 | import semver from 'semver6'; 2 | 3 | semver.valid('1.2.3') // '1.2.3' 4 | semver.valid('a.b.c') // null 5 | semver.clean(' =v1.2.3 ') // '1.2.3' 6 | semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true 7 | semver.gt('1.2.3', '9.8.7') // false 8 | semver.lt('1.2.3', '9.8.7') // true 9 | semver.minVersion('>=1.0.0') // '1.0.0' 10 | semver.valid(semver.coerce('v2')) // '2.0.0' 11 | semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7' -------------------------------------------------------------------------------- /examples/rsbuild-minimal/src/semver7.ts: -------------------------------------------------------------------------------- 1 | import semver from 'semver7'; 2 | 3 | semver.valid('1.2.3') // '1.2.3' 4 | semver.valid('a.b.c') // null 5 | semver.clean(' =v1.2.3 ') // '1.2.3' 6 | semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true 7 | semver.gt('1.2.3', '9.8.7') // false 8 | semver.lt('1.2.3', '9.8.7') // true 9 | semver.minVersion('>=1.0.0') // '1.0.0' 10 | semver.valid(semver.coerce('v2')) // '2.0.0' 11 | semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7' -------------------------------------------------------------------------------- /examples/rsbuild-minimal/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "outDir": "dist", 6 | "baseUrl": ".", 7 | "module": "ESNext" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/examples/rspack-banner-minimal/public/favicon.ico -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/examples/rspack-banner-minimal/public/logo192.png -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/examples/rspack-banner-minimal/public/logo512.png -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from '@arco-design/web-react'; 3 | import '@arco-design/web-react/dist/css/arco.css'; 4 | import styles from './index.module.less'; 5 | 6 | export function App({ name }: any) { 7 | return ( 8 | <> 9 | Hello {name}. Welcome! 10 | <> 11 |

Title:{name}

12 |

Content

13 | , 14 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/src/Footer/index.tsx: -------------------------------------------------------------------------------- 1 | import { Layout } from '@arco-design/web-react'; 2 | import { FooterProps } from '@arco-design/web-react/es/Layout/interface'; 3 | import cs from 'classnames'; 4 | import React from 'react'; 5 | import styles from './style/index.module.less'; 6 | 7 | function Footer(props: FooterProps = {}) { 8 | const { className, ...restProps } = props; 9 | return ( 10 | 11 | Arco Design Pro 12 | 13 | ); 14 | } 15 | 16 | export default Footer; 17 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/src/Footer/style/index.module.less: -------------------------------------------------------------------------------- 1 | .footer { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | height: 40px; 6 | text-align: center; 7 | color: var(--color-text-2); 8 | } 9 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/src/app1.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from '@arco-design/web-react'; 3 | import '@arco-design/web-react/dist/css/arco.css'; 4 | import styles from './index.module.less'; 5 | 6 | export function App({ name }: any) { 7 | return ( 8 | <> 9 | Hello {name}. Welcome! 10 | <> 11 |

标题{name}

12 |

内容

13 | , 14 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/src/declaration.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | const content: React.FunctionComponent>; 3 | export default content; 4 | } 5 | 6 | declare module '*.less' { 7 | const classes: { [className: string]: string }; 8 | export default classes; 9 | } 10 | 11 | declare module '*/settings.json' { 12 | const value: { 13 | colorWeek: boolean; 14 | navbar: boolean; 15 | menu: boolean; 16 | footer: boolean; 17 | themeColor: string; 18 | menuWidth: number; 19 | }; 20 | 21 | export default value; 22 | } 23 | 24 | declare module '*.png' { 25 | const value: string; 26 | export default value; 27 | } 28 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/src/index.module.less: -------------------------------------------------------------------------------- 1 | .header { 2 | background: var(--color-bg-2); 3 | padding: 20px; 4 | } 5 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/src/index.ts: -------------------------------------------------------------------------------- 1 | import { render } from 'react-dom'; 2 | import { createElement } from 'react'; 3 | 4 | import { App } from './app1'; 5 | 6 | render( 7 | createElement(App, { name: 'Taylor' }), 8 | document.getElementById('root')!, 9 | ); 10 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import { App } from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot( 8 | document.getElementById('root') as HTMLElement, 9 | ); 10 | root.render( 11 | 12 | 13 | , 14 | ); 15 | 16 | // If you want to start measuring performance in your app, pass a function 17 | // to log results (for example: reportWebVitals(console.log)) 18 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 19 | reportWebVitals(); 20 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/src/typings/assetsDefinition.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.png'; 2 | declare module '*.jpg'; 3 | declare module '*.svg'; 4 | declare module '*.jpeg'; 5 | declare module '*.gif'; 6 | declare module '*.webp'; 7 | declare module '*.ttf'; 8 | declare module '*.woff'; 9 | declare module '*.woff2'; 10 | declare module '*.scss'; 11 | declare module '*.less'; 12 | declare module '*.css'; 13 | declare module '*?__inline'; 14 | declare module '*?__inline=true'; 15 | declare module '*?__inline=false'; 16 | -------------------------------------------------------------------------------- /examples/rspack-banner-minimal/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "outDir": "dist", 6 | "baseUrl": ".", 7 | "module": "ESNext" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/legacy-loader.js: -------------------------------------------------------------------------------- 1 | module.exports = function legacyLoader(content) { 2 | return `// legacy!\n${content}`; 3 | }; 4 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/examples/rspack-layers-minimal/public/favicon.ico -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/examples/rspack-layers-minimal/public/logo192.png -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/examples/rspack-layers-minimal/public/logo512.png -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from '@arco-design/web-react'; 3 | import '@arco-design/web-react/dist/css/arco.css'; 4 | import styles from './index.module.less'; 5 | 6 | export function App({ name }: any) { 7 | return ( 8 | <> 9 | Hello {name}. Welcome! 10 | <> 11 |

标题{name}

12 |

内容

13 | , 14 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/src/Footer/index.tsx: -------------------------------------------------------------------------------- 1 | import { Layout } from '@arco-design/web-react'; 2 | import { FooterProps } from '@arco-design/web-react/es/Layout/interface'; 3 | import cs from 'classnames'; 4 | import React from 'react'; 5 | import styles from './style/index.module.less'; 6 | 7 | function Footer(props: FooterProps = {}) { 8 | const { className, ...restProps } = props; 9 | return ( 10 | 11 | Arco Design Pro 12 | 13 | ); 14 | } 15 | 16 | export default Footer; 17 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/src/Footer/style/index.module.less: -------------------------------------------------------------------------------- 1 | .footer { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | height: 40px; 6 | text-align: center; 7 | color: var(--color-text-2); 8 | } 9 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/src/app1.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from '@arco-design/web-react'; 3 | import '@arco-design/web-react/dist/css/arco.css'; 4 | import styles from './index.module.less'; 5 | 6 | export function App({ name }: any) { 7 | return ( 8 | <> 9 | Hello {name}. Welcome! 10 | <> 11 |

标题{name}

12 |

内容

13 | , 14 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/src/declaration.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | const content: React.FunctionComponent>; 3 | export default content; 4 | } 5 | 6 | declare module '*.less' { 7 | const classes: { [className: string]: string }; 8 | export default classes; 9 | } 10 | 11 | declare module '*/settings.json' { 12 | const value: { 13 | colorWeek: boolean; 14 | navbar: boolean; 15 | menu: boolean; 16 | footer: boolean; 17 | themeColor: string; 18 | menuWidth: number; 19 | }; 20 | 21 | export default value; 22 | } 23 | 24 | declare module '*.png' { 25 | const value: string; 26 | export default value; 27 | } 28 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/src/index.module.less: -------------------------------------------------------------------------------- 1 | .header { 2 | background: var(--color-bg-2); 3 | padding: 20px; 4 | } 5 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/src/index.ts: -------------------------------------------------------------------------------- 1 | import { render } from 'react-dom'; 2 | import { createElement } from 'react'; 3 | 4 | import { App } from './app1'; 5 | 6 | render( 7 | createElement(App, { name: 'Taylor' }), 8 | document.getElementById('root')!, 9 | ); 10 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import { App } from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot( 8 | document.getElementById('root') as HTMLElement, 9 | ); 10 | root.render( 11 | 12 | 13 | , 14 | ); 15 | 16 | // If you want to start measuring performance in your app, pass a function 17 | // to log results (for example: reportWebVitals(console.log)) 18 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 19 | reportWebVitals(); 20 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/src/typings/assetsDefinition.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.png'; 2 | declare module '*.jpg'; 3 | declare module '*.svg'; 4 | declare module '*.jpeg'; 5 | declare module '*.gif'; 6 | declare module '*.webp'; 7 | declare module '*.ttf'; 8 | declare module '*.woff'; 9 | declare module '*.woff2'; 10 | declare module '*.scss'; 11 | declare module '*.less'; 12 | declare module '*.css'; 13 | declare module '*?__inline'; 14 | declare module '*?__inline=true'; 15 | declare module '*?__inline=false'; 16 | -------------------------------------------------------------------------------- /examples/rspack-layers-minimal/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "declaration": true, 6 | "declarationMap": true, 7 | "outDir": "dist", 8 | "baseUrl": ".", 9 | "module": "ESNext" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/rspack-minimal/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/examples/rspack-minimal/public/favicon.ico -------------------------------------------------------------------------------- /examples/rspack-minimal/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/examples/rspack-minimal/public/logo192.png -------------------------------------------------------------------------------- /examples/rspack-minimal/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/examples/rspack-minimal/public/logo512.png -------------------------------------------------------------------------------- /examples/rspack-minimal/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/rspack-minimal/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/rspack-minimal/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from '@arco-design/web-react'; 3 | import '@arco-design/web-react/dist/css/arco.css'; 4 | import styles from './index.module.less'; 5 | 6 | export function App({ name }: any) { 7 | return ( 8 | <> 9 | Hello {name}. Welcome! 10 | <> 11 |

标题{name}

12 |

内容

13 | , 14 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /examples/rspack-minimal/src/Footer/index.tsx: -------------------------------------------------------------------------------- 1 | import { Layout } from '@arco-design/web-react' 2 | import { FooterProps } from '@arco-design/web-react/es/Layout/interface' 3 | import cs from 'classnames' 4 | import React from 'react' 5 | import styles from './style/index.module.less' 6 | 7 | function Footer(props: FooterProps = {}) { 8 | const { className, ...restProps } = props 9 | return ( 10 | 11 | Arco Design Pro 12 | 13 | ) 14 | } 15 | 16 | export default Footer 17 | -------------------------------------------------------------------------------- /examples/rspack-minimal/src/Footer/style/index.module.less: -------------------------------------------------------------------------------- 1 | .footer { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | height: 40px; 6 | text-align: center; 7 | color: var(--color-text-2); 8 | } 9 | -------------------------------------------------------------------------------- /examples/rspack-minimal/src/app1.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from '@arco-design/web-react'; 3 | import '@arco-design/web-react/dist/css/arco.css'; 4 | import styles from './index.module.less'; 5 | 6 | export function App({ name }: any) { 7 | return ( 8 | <> 9 | Hello {name}. Welcome! 10 | <> 11 |

标题{name}

12 |

内容

13 | , 14 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /examples/rspack-minimal/src/declaration.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | const content: React.FunctionComponent>; 3 | export default content; 4 | } 5 | 6 | declare module '*.less' { 7 | const classes: { [className: string]: string }; 8 | export default classes; 9 | } 10 | 11 | declare module '*/settings.json' { 12 | const value: { 13 | colorWeek: boolean; 14 | navbar: boolean; 15 | menu: boolean; 16 | footer: boolean; 17 | themeColor: string; 18 | menuWidth: number; 19 | }; 20 | 21 | export default value; 22 | } 23 | 24 | declare module '*.png' { 25 | const value: string; 26 | export default value; 27 | } 28 | -------------------------------------------------------------------------------- /examples/rspack-minimal/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/rspack-minimal/src/index.module.less: -------------------------------------------------------------------------------- 1 | .header { 2 | background: var(--color-bg-2); 3 | padding: 20px; 4 | } 5 | -------------------------------------------------------------------------------- /examples/rspack-minimal/src/index.ts: -------------------------------------------------------------------------------- 1 | import { render } from 'react-dom'; 2 | import { createElement } from 'react'; 3 | 4 | import { App } from './app1'; 5 | 6 | render( 7 | createElement(App, { name: 'Taylor' }), 8 | document.getElementById('root')!, 9 | ); 10 | -------------------------------------------------------------------------------- /examples/rspack-minimal/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import { App } from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot( 8 | document.getElementById('root') as HTMLElement, 9 | ); 10 | root.render( 11 | 12 | 13 | , 14 | ); 15 | 16 | // If you want to start measuring performance in your app, pass a function 17 | // to log results (for example: reportWebVitals(console.log)) 18 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 19 | reportWebVitals(); 20 | -------------------------------------------------------------------------------- /examples/rspack-minimal/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/rspack-minimal/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from "web-vitals"; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /examples/rspack-minimal/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import "@testing-library/jest-dom"; 6 | -------------------------------------------------------------------------------- /examples/rspack-minimal/src/typings/assetsDefinition.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.png'; 2 | declare module '*.jpg'; 3 | declare module '*.svg'; 4 | declare module '*.jpeg'; 5 | declare module '*.gif'; 6 | declare module '*.webp'; 7 | declare module '*.ttf'; 8 | declare module '*.woff'; 9 | declare module '*.woff2'; 10 | declare module '*.scss'; 11 | declare module '*.less'; 12 | declare module '*.css'; 13 | declare module '*?__inline'; 14 | declare module '*?__inline=true'; 15 | declare module '*?__inline=false'; 16 | 17 | -------------------------------------------------------------------------------- /examples/rspack-minimal/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "declaration": true, 6 | "declarationMap": true, 7 | "outDir": "dist", 8 | "baseUrl": ".", 9 | "module": "ESNext" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/rspress-minimal/.gitignore: -------------------------------------------------------------------------------- 1 | # Local 2 | .DS_Store 3 | *.local 4 | *.log* 5 | 6 | # Dist 7 | node_modules 8 | dist/ 9 | doc_build/ 10 | 11 | # IDE 12 | .vscode/* 13 | !.vscode/extensions.json 14 | .idea 15 | -------------------------------------------------------------------------------- /examples/rspress-minimal/README.md: -------------------------------------------------------------------------------- 1 | # Rspress website 2 | 3 | ## Setup 4 | 5 | Install the dependencies: 6 | 7 | ```bash 8 | npm install 9 | ``` 10 | 11 | ## Get started 12 | 13 | Start the dev server: 14 | 15 | ```bash 16 | npm run dev 17 | ``` 18 | 19 | Build the website for production: 20 | 21 | ```bash 22 | npm run build 23 | ``` 24 | 25 | Preview the production build locally: 26 | 27 | ```bash 28 | npm run preview 29 | ``` 30 | -------------------------------------------------------------------------------- /examples/rspress-minimal/docs/_meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "text": "Guide", 4 | "link": "/guide/", 5 | "activeMatch": "/guide/" 6 | }, 7 | { 8 | "text": "Hello world", 9 | "link": "/hello/", 10 | "activeMatch": "/hello/" 11 | }, 12 | { 13 | "text": "API", 14 | "link": "https://rspress.rs/api/index.html" 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /examples/rspress-minimal/docs/guide/_meta.json: -------------------------------------------------------------------------------- 1 | ["index"] 2 | -------------------------------------------------------------------------------- /examples/rspress-minimal/docs/hello.md: -------------------------------------------------------------------------------- 1 | # Hello world! 2 | 3 | ## Start 4 | 5 | Write something to build your own docs! 🎁 6 | -------------------------------------------------------------------------------- /examples/rspress-minimal/docs/public/rspress-dark-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/examples/rspress-minimal/docs/public/rspress-dark-logo.png -------------------------------------------------------------------------------- /examples/rspress-minimal/docs/public/rspress-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/examples/rspress-minimal/docs/public/rspress-icon.png -------------------------------------------------------------------------------- /examples/rspress-minimal/docs/public/rspress-light-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/examples/rspress-minimal/docs/public/rspress-light-logo.png -------------------------------------------------------------------------------- /examples/rspress-minimal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rspress-minimal", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "rspress build", 7 | "build:analysis": "RSDOCTOR=true rspress build", 8 | "dev": "rspress dev", 9 | "preview": "rspress preview" 10 | }, 11 | "dependencies": { 12 | "rspress": "2.0.0-alpha.3" 13 | }, 14 | "devDependencies": { 15 | "@rsdoctor/rspack-plugin": "workspace:*", 16 | "@types/node": "^22.8.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/rspress-minimal/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "lib": ["DOM", "ES2020"], 5 | "module": "ESNext", 6 | "jsx": "react-jsx", 7 | "noEmit": true, 8 | "strict": true, 9 | "skipLibCheck": true, 10 | "isolatedModules": true, 11 | "resolveJsonModule": true, 12 | "moduleResolution": "bundler", 13 | "useDefineForClassFields": true, 14 | "allowImportingTsExtensions": true 15 | }, 16 | "include": ["docs", "theme", "rspress.config.ts"], 17 | "mdx": { 18 | "checkMdx": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/webpack-minimal/src/html.ts: -------------------------------------------------------------------------------- 1 | import Parser from 'htmlparser2'; 2 | import svg from "./images/file.svg"; 3 | import { createImageElement } from './utils/utils'; 4 | 5 | 6 | export function getHtmlText(code: string) { 7 | let context = ''; 8 | 9 | const parser = new Parser.Parser({ 10 | ontext(data) { 11 | context += data; 12 | }, 13 | }); 14 | [svg].forEach(src => { 15 | createImageElement(src.split(".").pop(), src); 16 | }); 17 | parser.write(code); 18 | 19 | return context; 20 | } -------------------------------------------------------------------------------- /examples/webpack-minimal/src/images/file.svg: -------------------------------------------------------------------------------- 1 | icon-square-small 2 | -------------------------------------------------------------------------------- /examples/webpack-minimal/src/index.ts: -------------------------------------------------------------------------------- 1 | import { Chalk } from 'chalk'; 2 | import { highlight } from './utils'; 3 | import { getHtmlText } from './html'; 4 | import { key6 } from './utils2'; 5 | import './style.css'; 6 | 7 | const print = new Chalk(); 8 | 9 | print(key6); 10 | print(getHtmlText('
Test Text
')); 11 | print(highlight?.('const abc = 123;')); 12 | -------------------------------------------------------------------------------- /examples/webpack-minimal/src/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: green; 3 | font-family: "Open Sans"; 4 | } -------------------------------------------------------------------------------- /examples/webpack-minimal/src/types.ts: -------------------------------------------------------------------------------- 1 | declare module '@babel/highlight'; 2 | -------------------------------------------------------------------------------- /examples/webpack-minimal/src/typings/assetsDefinition.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.png'; 2 | declare module '*.jpg'; 3 | declare module '*.svg'; 4 | declare module '*.jpeg'; 5 | declare module '*.gif'; 6 | declare module '*.webp'; 7 | declare module '*.ttf'; 8 | declare module '*.woff'; 9 | declare module '*.woff2'; 10 | declare module '*.scss'; 11 | declare module '*.less'; 12 | declare module '*.css'; 13 | declare module '*?__inline'; 14 | declare module '*?__inline=true'; 15 | declare module '*?__inline=false'; 16 | 17 | -------------------------------------------------------------------------------- /examples/webpack-minimal/src/utils.ts: -------------------------------------------------------------------------------- 1 | import highlight from '@babel/highlight'; 2 | 3 | export { highlight }; 4 | export const key1 = '123'; 5 | export const key2 = '123'; 6 | 7 | console.log(key2); 8 | -------------------------------------------------------------------------------- /examples/webpack-minimal/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | import { Linter } from '@rsdoctor/types'; 2 | 3 | export function toSeverity(input: Linter.SeverityInput, defaultLevel: Linter.Severity): Linter.Severity { 4 | if (input === 'off') { 5 | return Linter.Severity.Ignore; 6 | } 7 | 8 | if (input === 'on') { 9 | return defaultLevel; 10 | } 11 | 12 | const key = `${input[0].toUpperCase()}${input.slice(1)}` as Linter.SeverityString; 13 | return Linter.Severity[key] as Linter.Severity; 14 | } 15 | -------------------------------------------------------------------------------- /examples/webpack-minimal/src/utils/utils.js: -------------------------------------------------------------------------------- 1 | const container = document.createElement("div"); 2 | Object.assign(container.style, { 3 | display: "flex", 4 | justifyContent: "center" 5 | }); 6 | document.body.appendChild(container); 7 | 8 | export function createImageElement(title, src) { 9 | const div = document.createElement("div"); 10 | div.style.textAlign = "center"; 11 | 12 | const h2 = document.createElement("h2"); 13 | h2.textContent = title; 14 | div.appendChild(h2); 15 | 16 | const img = document.createElement("img"); 17 | img.setAttribute("src", src); 18 | img.setAttribute("width", "150"); 19 | div.appendChild(img); 20 | 21 | container.appendChild(div); 22 | } -------------------------------------------------------------------------------- /examples/webpack-minimal/src/utils2.ts: -------------------------------------------------------------------------------- 1 | export * as utils6 from './utils6'; 2 | 3 | export * from './utils'; 4 | export * from './utils4'; 5 | export * from './html'; 6 | -------------------------------------------------------------------------------- /examples/webpack-minimal/src/utils3.ts: -------------------------------------------------------------------------------- 1 | import { key1 } from './utils'; 2 | 3 | export const key3 = key1 + 1; 4 | -------------------------------------------------------------------------------- /examples/webpack-minimal/src/utils4.ts: -------------------------------------------------------------------------------- 1 | export * from './utils5'; 2 | -------------------------------------------------------------------------------- /examples/webpack-minimal/src/utils5.ts: -------------------------------------------------------------------------------- 1 | export * from './utils6'; 2 | -------------------------------------------------------------------------------- /examples/webpack-minimal/src/utils6.ts: -------------------------------------------------------------------------------- 1 | export const key6 = 'key6'; 2 | -------------------------------------------------------------------------------- /examples/webpack-minimal/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "include": ["src", "webpack.config.ts"], 4 | "compilerOptions": { 5 | "outDir": "dist", 6 | "baseUrl": ".", 7 | "module": "ESNext" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/nx/schemas/nx-schema.json", 3 | "namedInputs": { 4 | "default": ["{projectRoot}/src/**/*"], 5 | "build": [ 6 | "default", 7 | "!{projectRoot}/**/*.{md,mdx}", 8 | "{projectRoot}/tsconfig.json", 9 | "{projectRoot}/package.json", 10 | "{projectRoot}/modern.config.*", 11 | "{projectRoot}/scripts/**/*" 12 | ] 13 | }, 14 | "targetDefaults": { 15 | "build": { 16 | "cache": true, 17 | "dependsOn": ["^build"], 18 | "inputs": ["build", "^build"] 19 | } 20 | }, 21 | "defaultBase": "main" 22 | } 23 | -------------------------------------------------------------------------------- /packages/ai/.env.sample: -------------------------------------------------------------------------------- 1 | ## openai 2 | OPENAI_API_KEY="xxx" 3 | OPENAI_BASE_URL="xxx" 4 | OPENAI_MODEL_NAME="gpt-4o-2024-08-06" 5 | 6 | ## coze 7 | COZE_API_TOKEN="yyy" 8 | COZE_BOT_ID="yyy" 9 | COZE_COM_BASE_URL="yyy" -------------------------------------------------------------------------------- /packages/ai/.gitignore: -------------------------------------------------------------------------------- 1 | # Local 2 | .DS_Store 3 | *.local 4 | *.log* 5 | logs/ 6 | 7 | # Dist 8 | node_modules 9 | dist/ 10 | 11 | # IDE 12 | .vscode/* 13 | !.vscode/extensions.json 14 | .idea 15 | 16 | # env 17 | .env 18 | .env.* 19 | !.env.sample 20 | -------------------------------------------------------------------------------- /packages/ai/bin/rsdoctor-mcp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { runServer } from '../dist/index.js'; 4 | 5 | 6 | runServer().catch((error) => { 7 | console.error('Fatal error running server:', error); 8 | process.exit(1); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/ai/rslib.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@rslib/core'; 2 | 3 | export default defineConfig({ 4 | lib: [ 5 | { 6 | source: { 7 | entry: { 8 | index: './src/server/server.ts', 9 | }, 10 | tsconfigPath: './tsconfig.build.json', 11 | }, 12 | output: { 13 | distPath: { 14 | root: './dist/', 15 | }, 16 | }, 17 | bundle: true, 18 | dts: false, 19 | format: 'esm', 20 | syntax: 'es2021', 21 | }, 22 | ], 23 | output: { 24 | copy: { 25 | patterns: [{ from: 'resources', to: 'resources' }], 26 | }, 27 | }, 28 | }); 29 | -------------------------------------------------------------------------------- /packages/ai/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './server/index.js'; 2 | -------------------------------------------------------------------------------- /packages/ai/src/prompt/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/packages/ai/src/prompt/index.ts -------------------------------------------------------------------------------- /packages/ai/src/schema.ts: -------------------------------------------------------------------------------- 1 | import z from 'zod'; 2 | 3 | export const SizeSchema = z.object({ 4 | sourceSize: z.number(), 5 | transformedSize: z.number(), 6 | parsedSize: z.number(), 7 | }); 8 | 9 | export const DependenciesSchema = z.object({ 10 | name: z.string(), 11 | root: z.string(), 12 | version: z.string(), 13 | size: SizeSchema, 14 | }); 15 | -------------------------------------------------------------------------------- /packages/ai/src/server/index.ts: -------------------------------------------------------------------------------- 1 | import { runServer } from './server.js'; 2 | 3 | runServer().catch((error) => { 4 | console.error('Fatal error running server:', error); 5 | process.exit(1); 6 | }); 7 | -------------------------------------------------------------------------------- /packages/ai/src/utils/env.ts: -------------------------------------------------------------------------------- 1 | export const OPENAI_API_KEY = process.env.OPENAI_API_KEY ?? undefined; 2 | export const OPENAI_BASE_URL = process.env.OPENAI_BASE_URL ?? undefined; 3 | export const OPENAI_MODEL_NAME = process.env.OPENAI_MODEL_NAME ?? undefined; 4 | export const OPENAI_INIT_OPTIONS = JSON.parse( 5 | process.env.OPENAI_INIT_OPTIONS ?? '{}', 6 | ); 7 | -------------------------------------------------------------------------------- /packages/ai/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './chunks.js'; 2 | -------------------------------------------------------------------------------- /packages/ai/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from 'vitest'; 2 | import { ChatGPT } from './model/openai'; 3 | 4 | test('openai chat', async () => { 5 | const instance = new ChatGPT(); 6 | const data1 = await import('./fixtures/deps.json'); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/ai/tests/model/coze.ts: -------------------------------------------------------------------------------- 1 | // Langchain does not provide a nodejs version of the coze sdk. 2 | // Only python version: https://python.langchain.com/docs/integrations/chat/coze 3 | // So use coze sdk first. 4 | -------------------------------------------------------------------------------- /packages/ai/tests/socket.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from 'vitest'; 2 | import { createSocket, sendRequest } from '../src/server/socket'; 3 | import { SDK } from '@rsdoctor/types'; 4 | 5 | test('createSocket', async () => { 6 | const res = await sendRequest(SDK.ServerAPI.API.GetChunkGraph, {}); 7 | console.log(res); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/ai/tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "include": [".", "../vitest.setup.ts"], 4 | "exclude": ["fixtures/**/*"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/ai/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "Node16", 5 | "moduleResolution": "Node16", 6 | "strict": true, 7 | "esModuleInterop": true, 8 | "skipLibCheck": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "resolveJsonModule": true, 11 | "outDir": "./dist", 12 | "rootDir": "./src", 13 | "paths": { 14 | "@/*": ["./src/*"] 15 | } 16 | }, 17 | "include": ["src/**/*.ts"], 18 | "exclude": ["node_modules", "dist", "src/resources/**/*"] 19 | } 20 | -------------------------------------------------------------------------------- /packages/ai/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["ES2021"], 4 | "module": "ESNext", 5 | "noEmit": true, 6 | "strict": true, 7 | "skipLibCheck": true, 8 | "isolatedModules": true, 9 | "resolveJsonModule": true, 10 | "moduleResolution": "bundler", 11 | "useDefineForClassFields": true, 12 | "allowImportingTsExtensions": true, 13 | "paths": { 14 | "@/*": ["./src/*"] 15 | } 16 | }, 17 | "include": ["src"] 18 | } 19 | -------------------------------------------------------------------------------- /packages/ai/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path'; 2 | import { defineConfig } from 'vitest/config'; 3 | 4 | export default defineConfig({ 5 | // Configure Vitest (https://vitest.dev/config/) 6 | test: { 7 | testTimeout: 500000, 8 | setupFiles: ['dotenv/config'], 9 | alias: { 10 | '@': path.resolve(__dirname, 'src'), 11 | }, 12 | }, 13 | }); 14 | -------------------------------------------------------------------------------- /packages/cli/README.md: -------------------------------------------------------------------------------- 1 | # @rsdoctor/cli 2 | 3 | This is the CLI of Rsdoctor, you can use the capabilities of this package to open the analysis page without building. 4 | 5 | ```bash 6 | npx @rsdoctor/cli analyze --profile [.rsdoctor/manifest.json filepath] 7 | ``` 8 | 9 | ## Documentation 10 | 11 | https://rsdoctor.rs/ 12 | 13 | ## Contributing 14 | 15 | Please read the [Contributing Guide](https://github.com/web-infra-dev/rsdoctor/blob/main/CONTRIBUTING.md). 16 | 17 | ## License 18 | 19 | Rsdoctor is [MIT licensed](https://github.com/web-infra-dev/rsdoctor/blob/main/LICENSE). 20 | -------------------------------------------------------------------------------- /packages/cli/bin/rsdoctor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { execute } = require('../dist/index.js'); 4 | 5 | execute(); 6 | -------------------------------------------------------------------------------- /packages/cli/modern.config.ts: -------------------------------------------------------------------------------- 1 | import { baseBuildConfig } from '../../scripts/modern.base.config'; 2 | 3 | export default baseBuildConfig; 4 | -------------------------------------------------------------------------------- /packages/cli/src/commands/index.ts: -------------------------------------------------------------------------------- 1 | export * from './analyze'; 2 | export * from './bundle-diff'; 3 | -------------------------------------------------------------------------------- /packages/cli/src/constants.ts: -------------------------------------------------------------------------------- 1 | export enum Commands { 2 | Analyze = 'analyze', 3 | BundleDiff = 'bundle-diff', 4 | } 5 | 6 | export const pkg: { 7 | name: string; 8 | version: string; 9 | bin: Record; 10 | } = require('../package.json'); 11 | 12 | export const bin = Object.keys(pkg.bin)[0]; 13 | -------------------------------------------------------------------------------- /packages/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "outDir": "./dist", 6 | "baseUrl": "./", 7 | "paths": { 8 | "@/*": ["./src/*"] 9 | }, 10 | "rootDir": "src" 11 | }, 12 | "include": ["src"], 13 | "exclude": ["**/node_modules"], 14 | "references": [ 15 | { 16 | "path": "../types/tsconfig.json" 17 | }, 18 | { 19 | "path": "../utils/tsconfig.json" 20 | }, 21 | { 22 | "path": "../sdk/tsconfig.json" 23 | }, 24 | { 25 | "path": "../client/tsconfig.json" 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /packages/client/README.md: -------------------------------------------------------------------------------- 1 | # @rsdoctor/client 2 | 3 | This package is the Rsdoctor reporting platform. 4 | 5 | ## Documentation 6 | 7 | https://rsdoctor.rs/ 8 | 9 | ## Contributing 10 | 11 | Please read the [Contributing Guide](https://github.com/web-infra-dev/rsdoctor/blob/main/CONTRIBUTING.md). 12 | 13 | ## License 14 | 15 | Rsdoctor is [MIT licensed](https://github.com/web-infra-dev/rsdoctor/blob/main/LICENSE). 16 | -------------------------------------------------------------------------------- /packages/client/config/constants.ts: -------------------------------------------------------------------------------- 1 | import { Constants } from '@rsdoctor/types'; 2 | 3 | import path from 'path'; 4 | 5 | export const DistPath = path.resolve(__dirname, '../dist'); 6 | 7 | export const DistResourcePath = path.resolve(__dirname, '../dist/resource'); 8 | 9 | export const WebpackRsdoctorDirPath = path.resolve(__dirname, `../dist/${Constants.RsdoctorOutputFolder}`); 10 | 11 | export const WebpackStatsFilePath = path.resolve(__dirname, '../dist/stats.json'); 12 | 13 | export const PortForWeb = 8681; 14 | 15 | export const PortForCLI = 8123; 16 | 17 | export const ClientEntry = path.resolve(__dirname, '../src/index.tsx'); 18 | 19 | export const RsdoctorWebpackPluginMain = path.resolve(__dirname, '../../webpack-plugin/dist'); 20 | -------------------------------------------------------------------------------- /packages/client/src/common/styles/base.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:meta'; 2 | @import 'normalize.css'; 3 | @include meta.load-css('./theme.scss'); 4 | 5 | .body { 6 | font-size: 12px; 7 | } 8 | -------------------------------------------------------------------------------- /packages/client/src/common/styles/theme.scss: -------------------------------------------------------------------------------- 1 | // body { 2 | // background-color: rgb(247, 245, 245); 3 | // } 4 | -------------------------------------------------------------------------------- /packages/client/src/index.tsx: -------------------------------------------------------------------------------- 1 | import '@rsdoctor/components/i18n'; 2 | import App from './App'; 3 | import ReactDOM from 'react-dom/client'; 4 | import './common/styles/base.scss'; 5 | 6 | const rootElement = document.getElementById('root'); 7 | const root = ReactDOM.createRoot(rootElement!); 8 | 9 | root.render(); 10 | 11 | const link = document.createElement('link'); 12 | link.setAttribute('type', 'image/x-icon'); 13 | link.setAttribute('rel', 'icon'); 14 | link.setAttribute( 15 | 'href', 16 | 'https://assets.rspack.rs/rsdoctor/rsdoctor-logo-960x960.png', 17 | ); 18 | document.head.appendChild(link); 19 | -------------------------------------------------------------------------------- /packages/client/src/typings/assetsDefinition.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.png'; 2 | declare module '*.jpg'; 3 | declare module '*.svg'; 4 | declare module '*.jpeg'; 5 | declare module '*.gif'; 6 | declare module '*.webp'; 7 | declare module '*.ttf'; 8 | declare module '*.woff'; 9 | declare module '*.woff2'; 10 | declare module '*.scss'; 11 | declare module '*.less'; 12 | declare module '*.css'; 13 | declare module '*?__inline'; 14 | declare module '*?__inline=true'; 15 | declare module '*?__inline=false'; 16 | 17 | -------------------------------------------------------------------------------- /packages/client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "jsx": "react-jsx", 6 | "isolatedModules": true, 7 | "declaration": true, 8 | "declarationMap": false, 9 | "composite": true, 10 | "outDir": "dist" 11 | }, 12 | "include": ["src", "config"], 13 | "exclude": ["**/node_modules"], 14 | "references": [ 15 | { 16 | "path": "../types/tsconfig.json" 17 | }, 18 | { 19 | "path": "../components/tsconfig.json" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /packages/components/README.md: -------------------------------------------------------------------------------- 1 | # @rsdoctor/components 2 | 3 | This package is the Rsdoctor reporting platform’s components. 4 | 5 | ## Documentation 6 | 7 | https://rsdoctor.rs/ 8 | 9 | ## Contributing 10 | 11 | Please read the [Contributing Guide](https://github.com/web-infra-dev/rsdoctor/blob/main/CONTRIBUTING.md). 12 | 13 | ## License 14 | 15 | Rsdoctor is [MIT licensed](https://github.com/web-infra-dev/rsdoctor/blob/main/LICENSE). 16 | -------------------------------------------------------------------------------- /packages/components/modern.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, moduleTools } from '@modern-js/module-tools'; 2 | 3 | export default defineConfig({ 4 | plugins: [moduleTools()], 5 | buildConfig: { 6 | buildType: 'bundleless', 7 | format: 'esm', 8 | target: 'es2020', 9 | outDir: './dist', 10 | sourceMap: true, 11 | minify: false, 12 | asset: { 13 | svgr: { 14 | include: /\.svg$/, 15 | }, 16 | }, 17 | }, 18 | }); 19 | -------------------------------------------------------------------------------- /packages/components/src/common/imgs/rsdoctor-navbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/packages/components/src/common/imgs/rsdoctor-navbar.png -------------------------------------------------------------------------------- /packages/components/src/common/imgs/webpack.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/components/src/common/svg/file.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/components/src/common/svg/navbar/compile-analysis-active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/common/svg/navbar/compile-analysis-inactive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/common/svg/source-size.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/components/src/common/svg/total-size.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/components/src/components/Alert/ecma-version-check.module.scss: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | justify-content: space-between; 4 | align-items: center; 5 | padding: 10px 20px; 6 | 7 | .box { 8 | width: 290px; 9 | display: flex; 10 | } 11 | 12 | .title { 13 | font-size: 12px; 14 | font-weight: 400; 15 | line-height: 16px; 16 | margin-bottom: 5px; 17 | color: #00000073; 18 | } 19 | 20 | .content { 21 | font-size: 14px; 22 | font-weight: 400; 23 | line-height: 16px; 24 | margin-left: 5px; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/components/src/components/Alert/file-relation.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Alert } from 'antd'; 3 | import { FileRelationAlertProps } from './types'; 4 | 5 | export const FileRelationAlert: React.FC = ({ data }) => { 6 | const { description = '', level } = data; 7 | return ; 8 | }; 9 | -------------------------------------------------------------------------------- /packages/components/src/components/Alert/index.scss: -------------------------------------------------------------------------------- 1 | // can del 2 | .file-inline-decoration { 3 | cursor: pointer; 4 | text-decoration: underline; 5 | background: rgb(77, 112, 151); 6 | } 7 | 8 | .alert-space, 9 | .full-space { 10 | width: 100%; 11 | height: 100%; 12 | 13 | > *:last-child { 14 | flex-grow: 1; 15 | } 16 | } 17 | .full-space { 18 | flex-grow: 1; 19 | } 20 | 21 | .code-change-tag-list { 22 | margin-left: 10px; 23 | } 24 | 25 | .tabs-space { 26 | width: 100%; 27 | height: 100%; 28 | 29 | .ant-tabs-content, 30 | .ant-tabs-tabpane { 31 | width: 100%; 32 | height: 100%; 33 | } 34 | } 35 | 36 | .ant-alert-warning { 37 | border: none; 38 | } 39 | -------------------------------------------------------------------------------- /packages/components/src/components/Alert/package-relation.module.scss: -------------------------------------------------------------------------------- 1 | .dot { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | justify-content: center; 6 | } 7 | 8 | .filePath { 9 | display: flex; 10 | justify-content: space-between; 11 | align-items: center; 12 | border: 1px solid #eaedf1; 13 | padding: 5px 10px; 14 | border-radius: 10px; 15 | } 16 | 17 | .arrow { 18 | position: relative; 19 | top: 8px; 20 | left: 50%; 21 | transform: translateX(-50%) rotate(90deg); 22 | color: #2994ff; 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/src/components/Alerts/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './bundle'; 2 | export * from './compile'; 3 | export * from './overlay'; 4 | -------------------------------------------------------------------------------- /packages/components/src/components/Alerts/list.module.scss: -------------------------------------------------------------------------------- 1 | .description { 2 | font-size: 14px; 3 | font-weight: 400; 4 | line-height: 16px; 5 | } 6 | -------------------------------------------------------------------------------- /packages/components/src/components/Alerts/overlay.module.scss: -------------------------------------------------------------------------------- 1 | .container { 2 | position: relative; 3 | top: 4px; 4 | 5 | .badgeContainer { 6 | display: flex; 7 | justify-content: center; 8 | align-items: center; 9 | width: 32px; 10 | height: 32px; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/components/src/components/Card/size.module.scss: -------------------------------------------------------------------------------- 1 | .dataContainer { 2 | display: flex; 3 | flex-direction: column; 4 | 5 | .title { 6 | font-size: 12px; 7 | font-weight: 400; 8 | line-height: 20px; 9 | margin-bottom: 2px; 10 | color: #000000a6; 11 | } 12 | } 13 | 14 | .description { 15 | font-size: 18px; 16 | 17 | @media (max-width: 1500px) { 18 | font-size: 14px; 19 | } 20 | 21 | font-weight: 500; 22 | line-height: 28px; 23 | color: #000000d9; 24 | } 25 | 26 | .percentContainer { 27 | display: flex; 28 | flex-direction: column; 29 | font-size: 20px; 30 | 31 | .percentDescription { 32 | font-size: 12px; 33 | font-weight: 400; 34 | line-height: 20px; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/components/src/components/Charts/constants.ts: -------------------------------------------------------------------------------- 1 | export const PALETTE_COLORS = [ 2 | '#F2793D', 3 | '#F28B24', 4 | '#F2A200', 5 | '#F5CC00', 6 | '#F5E000', 7 | '#A3D900', 8 | '#66CC00', 9 | '#0AC419', 10 | '#0AC496', 11 | '#0AC7D1', 12 | '#00A8E0', 13 | '#1471F5', 14 | '#4060FF', 15 | '#7559FF', 16 | '#884DFF', 17 | '#A526FF', 18 | '#BA39E5', 19 | '#C700D9', 20 | '#D900B5', 21 | '#E50099', 22 | '#E52E6B', 23 | '#F24957', 24 | '#30B2F2', 25 | '#00BF70', 26 | '#5959FF', 27 | '#9F40FF', 28 | '#528BFF', 29 | ]; 30 | 31 | export enum ChartTypes { 32 | Bootstrap, 33 | Compile, 34 | Done, 35 | Minify, 36 | Loader, 37 | Normal, 38 | } 39 | -------------------------------------------------------------------------------- /packages/components/src/components/Configuration/builder.module.scss: -------------------------------------------------------------------------------- 1 | .title { 2 | font-size: 13px; 3 | font-weight: 400; 4 | line-height: 22px; 5 | text-align: right; 6 | } 7 | -------------------------------------------------------------------------------- /packages/components/src/components/Configuration/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './builder'; 2 | -------------------------------------------------------------------------------- /packages/components/src/components/Keyword/style.module.scss: -------------------------------------------------------------------------------- 1 | .text { 2 | font-size: 14px; 3 | font-weight: 400; 4 | color: rgba(0, 0, 0, 0.85); 5 | } 6 | -------------------------------------------------------------------------------- /packages/components/src/components/Layout/compile-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/components/Layout/constants.ts: -------------------------------------------------------------------------------- 1 | export const CompileName = 'Compile Analysis'; 2 | -------------------------------------------------------------------------------- /packages/components/src/components/Layout/header.scss: -------------------------------------------------------------------------------- 1 | .header-switch { 2 | .ant-switch-handle { 3 | top: 1px !important; 4 | } 5 | } 6 | 7 | .header-icon { 8 | user-select: none; 9 | 10 | &:hover { 11 | color: #1668dc; 12 | } 13 | &:active { 14 | color: #40a9ff; 15 | } 16 | } 17 | 18 | .rsdoctor-logo { 19 | cursor: pointer; 20 | height: 30px; 21 | 22 | &:active { 23 | opacity: 0.8; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/components/src/components/Manifest/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './data'; 2 | export * from './api'; 3 | -------------------------------------------------------------------------------- /packages/components/src/components/Opener/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './code'; 2 | export * from './vscode'; 3 | -------------------------------------------------------------------------------- /packages/components/src/components/Overall/card.module.scss: -------------------------------------------------------------------------------- 1 | .card { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /packages/components/src/components/Overall/compile.module.scss: -------------------------------------------------------------------------------- 1 | .progress { 2 | :global(.ant-progress-text) { 3 | opacity: 0.8; 4 | font-size: 13px; 5 | } 6 | } 7 | 8 | .title { 9 | font-size: 16px; 10 | font-weight: 500; 11 | line-height: 20px; 12 | } 13 | -------------------------------------------------------------------------------- /packages/components/src/components/Overall/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './bundle'; 2 | export * from './compile'; 3 | export * from './project'; 4 | -------------------------------------------------------------------------------- /packages/components/src/components/Overall/list.module.scss: -------------------------------------------------------------------------------- 1 | .projectOverall { 2 | :global(.ant-descriptions-item-label), 3 | :global(.ant-descriptions-item-content) { 4 | font-size: 13px; 5 | color: #000000a6; 6 | } 7 | 8 | :global(.ant-descriptions-item) { 9 | padding-bottom: 10px !important; 10 | } 11 | } 12 | 13 | .bundleOverall { 14 | :global(.ant-descriptions-item-label), 15 | :global(.ant-descriptions-item-content) { 16 | font-size: 13px; 17 | color: #000000a6; 18 | } 19 | 20 | :global(.ant-descriptions-item) { 21 | padding-bottom: 0px !important; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/components/src/components/Overall/overview.module.scss: -------------------------------------------------------------------------------- 1 | .container { 2 | width: 100%; 3 | display: flex; 4 | background: #f6f8fa; 5 | align-items: center; 6 | justify-content: space-between; 7 | border-radius: 8px; 8 | padding: 8px 20px 8px 20px; 9 | margin-right: 10px; 10 | white-space: nowrap; 11 | 12 | .content { 13 | flex: 1; 14 | 15 | .title { 16 | font-size: 12px; 17 | font-weight: 400; 18 | line-height: 20px; 19 | color: #000000a6; 20 | } 21 | 22 | .description { 23 | font-size: 24px; 24 | font-weight: 500; 25 | line-height: 32px; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/components/src/components/Overall/overview.tsx: -------------------------------------------------------------------------------- 1 | import styles from './overview.module.scss'; 2 | 3 | interface OverviewProps { 4 | title?: string | React.ReactNode; 5 | description?: string | React.ReactNode; 6 | icon?: React.ReactNode; 7 | style?: React.CSSProperties; 8 | } 9 | 10 | export const Overview = (props: OverviewProps) => { 11 | const { title, description, icon, style } = props; 12 | return ( 13 |
14 |
15 |
{title}
16 |
{description}
17 |
18 | {icon} 19 |
20 | ); 21 | }; 22 | 23 | export default Overview; 24 | -------------------------------------------------------------------------------- /packages/components/src/components/Overall/project.module.scss: -------------------------------------------------------------------------------- 1 | .overview { 2 | display: flex; 3 | margin-bottom: 19px; 4 | } 5 | 6 | .title { 7 | display: flex; 8 | justify-content: space-between; 9 | align-items: center; 10 | padding-bottom: 20px; 11 | 12 | .left { 13 | font-size: 16px; 14 | font-weight: 500; 15 | line-height: 24px; 16 | text-align: left; 17 | text-underline-position: from-font; 18 | text-decoration-skip-ink: none; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/components/src/components/Select/index.scss: -------------------------------------------------------------------------------- 1 | .loader-select { 2 | .ant-select-selector { 3 | width: 300px; 4 | } 5 | } 6 | 7 | .layer-select { 8 | .ant-select-selector { 9 | width: 150px; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/components/src/components/Status/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './failed'; 2 | -------------------------------------------------------------------------------- /packages/components/src/components/base/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 业务无关的基础组件 3 | */ 4 | 5 | export * from './CodeViewer'; 6 | export * from './DiffViewer'; 7 | -------------------------------------------------------------------------------- /packages/components/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Alerts'; 2 | export * from './Badge'; 3 | export * from './base'; 4 | export * from './Card'; 5 | export { TimelineCom } from './Charts/TimelineCharts'; 6 | export * from './Form/keyword'; 7 | export * from './Layout'; 8 | export * from './Manifest'; 9 | export * from './Overall'; 10 | export * from './TextDrawer'; 11 | -------------------------------------------------------------------------------- /packages/components/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components'; 2 | export * from './utils'; 3 | export * as Constants from './constants'; -------------------------------------------------------------------------------- /packages/components/src/modern-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /packages/components/src/pages/BundleSize/components/index.scss: -------------------------------------------------------------------------------- 1 | $prefixCls: 'bundle-size'; 2 | 3 | .monaco-hover .markdown-hover.hover-row hr { 4 | margin: 2px; 5 | background-color: gray; 6 | } 7 | 8 | .#{$prefixCls}-editor { 9 | margin-left: 40px; 10 | flex-grow: 1; 11 | height: 700px; 12 | 13 | .ant-card-body { 14 | width: auto; 15 | height: calc(100% - 48px); 16 | padding: 0; 17 | } 18 | } 19 | 20 | .#{$prefixCls}-module-bunton { 21 | margin-left: 4em; 22 | } 23 | 24 | .ant-tabs-nav { 25 | width: 100%; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /packages/components/src/pages/BundleSize/config.tsx: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | 3 | interface config { 4 | setModuleJumpList(ids: number[]): void; 5 | moduleJumpList: number[]; 6 | } 7 | 8 | export const ModuleGraphListContext = createContext({ 9 | setModuleJumpList(_ids: number[]): void {}, 10 | moduleJumpList: [] as number[], 11 | }); 12 | -------------------------------------------------------------------------------- /packages/components/src/pages/BundleSize/constants.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '@rsdoctor/types'; 2 | 3 | export const maxModuleSize = 5000; 4 | 5 | export const name = 'BundleSize'; 6 | 7 | export const route = Client.RsdoctorClientRoutes.BundleSize; 8 | 9 | export type GraphType = 'tile' | 'tree'; 10 | -------------------------------------------------------------------------------- /packages/components/src/pages/BundleSize/index.tsx: -------------------------------------------------------------------------------- 1 | import { Col, Row } from 'antd'; 2 | import React from 'react'; 3 | 4 | import { Size } from '../../constants'; 5 | import { WebpackModulesOverall } from './components'; 6 | 7 | export const Page: React.FC = () => { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | }; 16 | 17 | export * from './constants'; 18 | -------------------------------------------------------------------------------- /packages/components/src/pages/ModuleAnalyze/constants.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '@rsdoctor/types'; 2 | 3 | export const name = 'Module Analyze'; 4 | 5 | export const route = Client.RsdoctorClientRoutes.ModuleAnalyze; 6 | 7 | export enum DevtoolsRuleClientConstant { 8 | UrlQueryForModuleAnalyze = 'curModuleId', 9 | } 10 | 11 | export const clsNamePrefix = 'module-analyze'; 12 | -------------------------------------------------------------------------------- /packages/components/src/pages/ModuleAnalyze/index.scss: -------------------------------------------------------------------------------- 1 | $prefixCls: 'module-analyze'; 2 | 3 | .#{$prefixCls}-file-tree { 4 | width: '100%'; 5 | min-height: 50em; 6 | 7 | .#{$prefixCls}-empty { 8 | margin-top: 20%; 9 | } 10 | } 11 | 12 | .module-analyze-box { 13 | display: flex; 14 | flex-direction: column; 15 | } 16 | 17 | .file-tree-com-titles-box { 18 | line-height: 30px; 19 | } 20 | -------------------------------------------------------------------------------- /packages/components/src/pages/ModuleResolve/constants.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '@rsdoctor/types'; 2 | 3 | export const name = 'ModuleResolve'; 4 | 5 | export const route = Client.RsdoctorClientRoutes.ModuleResolve; 6 | -------------------------------------------------------------------------------- /packages/components/src/pages/ModuleResolve/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Card } from 'antd'; 3 | import { ResolverAnalysis } from '../../components/Resolver/analysis'; 4 | import { WebpackConfigurationViewer } from '../../components/Configuration'; 5 | 6 | export const Page: React.FC = () => { 7 | return ( 8 |
9 | } 12 | bodyStyle={{ paddingTop: 0 }} 13 | > 14 | 15 | 16 |
17 | ); 18 | }; 19 | 20 | export * from './constants'; 21 | -------------------------------------------------------------------------------- /packages/components/src/pages/Overall/constants.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '@rsdoctor/types'; 2 | 3 | export const name = 'Overall'; 4 | 5 | export const route = Client.RsdoctorClientRoutes.Overall; 6 | -------------------------------------------------------------------------------- /packages/components/src/pages/Overall/responsiveLayout.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from 'antd'; 2 | import React from 'react'; 3 | 4 | import style from './index.module.scss'; 5 | 6 | interface Props { 7 | children: React.ReactNode[]; 8 | } 9 | 10 | export const ResponsiveLayout = ({ children }: Props) => { 11 | return ( 12 | 13 | {children.map((e) => ( 14 |
{e}
15 | ))} 16 |
17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /packages/components/src/pages/Resources/BundleDiff/DiffContainer/constants.ts: -------------------------------------------------------------------------------- 1 | export enum UpdateType { 2 | New = 'New', 3 | Changed = 'Changed', 4 | Deleted = 'Deleted', 5 | NotChanged = 'Not Changed', 6 | } 7 | 8 | export enum SortType { 9 | Name = 'Sorted by Name', 10 | Size = 'Sorted by Size', 11 | Delta = 'Sorted by Delta', 12 | } 13 | -------------------------------------------------------------------------------- /packages/components/src/pages/Resources/BundleDiff/constants.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Client, Manifest } from '@rsdoctor/types'; 3 | 4 | export const name = 'Bundle Diff'; 5 | 6 | export const route = Client.RsdoctorClientRoutes.BundleDiff; 7 | 8 | export const BundleDiffContext = React.createContext({ 9 | manifests: [] as Manifest.RsdoctorManifest[], 10 | setManifests(_manifests: Manifest.RsdoctorManifest[]): void {}, 11 | loading: false, 12 | setLoading(_loading: boolean): void {}, 13 | async withLoading( 14 | _func: (...args: unknown[]) => Promise | unknown, 15 | ) {}, 16 | }); 17 | -------------------------------------------------------------------------------- /packages/components/src/pages/Resources/BundleDiff/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { DiffContainer } from './DiffContainer'; 3 | 4 | export * from './constants'; 5 | export * from './DiffContainer'; 6 | 7 | export const Page: React.FC = () => { 8 | return ; 9 | }; 10 | -------------------------------------------------------------------------------- /packages/components/src/pages/Resources/RuleIndex/constants.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '@rsdoctor/types'; 2 | 3 | export const name = 'Rule Index'; 4 | 5 | export const route = Client.RsdoctorClientRoutes.RuleIndex; 6 | -------------------------------------------------------------------------------- /packages/components/src/pages/TreeShaking/constants.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '@rsdoctor/types'; 2 | 3 | export const name = 'TreeShaking'; 4 | 5 | export const route = Client.RsdoctorClientRoutes.TreeShaking; 6 | -------------------------------------------------------------------------------- /packages/components/src/pages/TreeShaking/space.tsx: -------------------------------------------------------------------------------- 1 | import { Card, Empty } from 'antd'; 2 | 3 | export function Space() { 4 | return ( 5 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /packages/components/src/pages/TreeShaking/types.ts: -------------------------------------------------------------------------------- 1 | import { SDK } from '@rsdoctor/types'; 2 | 3 | export type TableKind = 'side-effect' | 'export'; 4 | export type SetEditorStatus = ( 5 | module: SDK.ModuleInstance, 6 | ranges: SDK.SourceRange[], 7 | line?: number, 8 | ) => void; 9 | -------------------------------------------------------------------------------- /packages/components/src/pages/WebpackLoaders/Analysis/constants.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '@rsdoctor/types'; 2 | 3 | export const name = 'Loaders Analysis'; 4 | 5 | export const route = Client.RsdoctorClientRoutes.WebpackLoaderAnalysis; 6 | -------------------------------------------------------------------------------- /packages/components/src/pages/WebpackLoaders/Overall/constants.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '@rsdoctor/types'; 2 | 3 | export const name = 'Loaders Timeline'; 4 | 5 | export const route = Client.RsdoctorClientRoutes.WebpackLoaderOverall; 6 | -------------------------------------------------------------------------------- /packages/components/src/pages/WebpackLoaders/constants.ts: -------------------------------------------------------------------------------- 1 | export const name = 'Loaders'; 2 | 3 | export const route = '/webpack/loaders'; 4 | -------------------------------------------------------------------------------- /packages/components/src/pages/WebpackPlugins/constants.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '@rsdoctor/types'; 2 | 3 | export const name = 'Plugins Analysis'; 4 | 5 | export const route = Client.RsdoctorClientRoutes.WebpackPlugins; 6 | -------------------------------------------------------------------------------- /packages/components/src/pages/WebpackPlugins/index.scss: -------------------------------------------------------------------------------- 1 | .plugin-select { 2 | .ant-select-selector { 3 | width: 300px; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/components/src/pages/index.ts: -------------------------------------------------------------------------------- 1 | export * as Overall from './Overall'; 2 | export * as BundleSize from './BundleSize'; 3 | export * as ModuleAnalyze from './ModuleAnalyze'; 4 | export * as LoaderTimeline from './WebpackLoaders/Overall'; 5 | export * as LoaderFiles from './WebpackLoaders/Analysis'; 6 | export * as PluginsAnalyze from './WebpackPlugins'; 7 | export * as ModuleResolve from './ModuleResolve'; 8 | export * as RuleIndex from './Resources/RuleIndex'; 9 | export * as TreeShaking from './TreeShaking'; 10 | export * as BundleDiff from './Resources/BundleDiff'; 11 | -------------------------------------------------------------------------------- /packages/components/src/typings/assetsDefinition.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.png'; 2 | declare module '*.jpg'; 3 | declare module '*.svg'; 4 | declare module '*.jpeg'; 5 | declare module '*.gif'; 6 | declare module '*.webp'; 7 | declare module '*.ttf'; 8 | declare module '*.woff'; 9 | declare module '*.woff2'; 10 | declare module '*.scss'; 11 | declare module '*.less'; 12 | declare module '*.css'; 13 | declare module '*?__inline'; 14 | declare module '*?__inline=true'; 15 | declare module '*?__inline=false'; 16 | -------------------------------------------------------------------------------- /packages/components/src/typings/index.d.ts: -------------------------------------------------------------------------------- 1 | interface Window { 2 | [key: string]: any; 3 | __RSDOCTOR__: any; 4 | } 5 | -------------------------------------------------------------------------------- /packages/components/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './data'; 2 | export * from './file'; 3 | export * from './hooks'; 4 | export * from './loader'; 5 | export * from './locale'; 6 | export * from './manifest'; 7 | export * from './request'; 8 | export * from './routes'; 9 | export * from './size'; 10 | export * from './socket'; 11 | export * from './storage'; 12 | export * from './string'; 13 | export * from './time'; 14 | export * from './url'; 15 | export * from './worker'; 16 | -------------------------------------------------------------------------------- /packages/components/src/utils/locale.ts: -------------------------------------------------------------------------------- 1 | import cn from 'antd/es/locale/zh_CN'; 2 | import en from 'antd/es/locale/en_GB'; 3 | import type { Locale } from 'antd/es/locale'; 4 | import { Language } from '../constants'; 5 | 6 | export function getLocale(locale: string): Locale { 7 | const res = locale === 'cn' || locale === 'zh-CN' ? cn : en; 8 | return res; 9 | } 10 | 11 | export function getLanguage(locale: string): Language { 12 | const res = locale === 'cn' || locale === 'zh' ? Language.Cn : Language.En; 13 | return res; 14 | } 15 | -------------------------------------------------------------------------------- /packages/components/src/utils/size.ts: -------------------------------------------------------------------------------- 1 | export function formatSize(bytes: number) { 2 | let res: string; 3 | 4 | if (bytes >= 1000000000) { 5 | res = `${(bytes / 1000000000).toFixed(2)} GB`; 6 | } else if (bytes >= 1000000) { 7 | res = `${(bytes / 1000000).toFixed(2)} MB`; 8 | } else if (bytes >= 1000) { 9 | res = `${(bytes / 1000).toFixed(2)} KB`; 10 | } else if (bytes > 1) { 11 | res = `${bytes} bytes`; 12 | } else if (bytes === 1) { 13 | res = `${bytes} byte`; 14 | } else { 15 | res = '0 bytes'; 16 | } 17 | return res; 18 | } 19 | 20 | export function formatPercent(percent: number) { 21 | return `${+percent.toFixed(2)}%`; 22 | } 23 | -------------------------------------------------------------------------------- /packages/components/src/utils/string.ts: -------------------------------------------------------------------------------- 1 | export function ensurePrefix(str: string, prefix: string): string { 2 | return str.slice(0, prefix.length) === prefix ? str : `${str}${prefix}`; 3 | } 4 | 5 | export function removePrefix(str: string, prefix: string): string { 6 | let res = str; 7 | 8 | while (res.slice(0, prefix.length) === prefix) { 9 | res = res.slice(prefix.length); 10 | } 11 | 12 | return res; 13 | } 14 | -------------------------------------------------------------------------------- /packages/components/src/utils/time.ts: -------------------------------------------------------------------------------- 1 | import { Time } from '@rsdoctor/utils/common'; 2 | 3 | const { toFixedDigits, getUnit, formatCosts } = Time; 4 | 5 | export { toFixedDigits as toFixed, getUnit, formatCosts }; 6 | -------------------------------------------------------------------------------- /packages/components/src/utils/worker/index.ts: -------------------------------------------------------------------------------- 1 | export * from './utils'; 2 | export * from './types'; 3 | export * from './master'; 4 | export * from './worker'; 5 | -------------------------------------------------------------------------------- /packages/components/src/utils/worker/master.ts: -------------------------------------------------------------------------------- 1 | import { CreateWorker } from './types'; 2 | import { ChildWorker } from './worker'; 3 | 4 | class Master { 5 | private _workerMap = new WeakMap(); 6 | 7 | public detectWorker(create: CreateWorker) { 8 | if (this._workerMap.has(create)) return this._workerMap.get(create)!; 9 | 10 | const worker = create(); 11 | const child = new ChildWorker(worker); 12 | this._workerMap.set(create, child); 13 | 14 | return child; 15 | } 16 | } 17 | 18 | export const master = new Master(); 19 | -------------------------------------------------------------------------------- /packages/components/src/utils/worker/types.ts: -------------------------------------------------------------------------------- 1 | export type CreateWorker = () => Worker; 2 | 3 | export type NativeWorkerMessage = MessageEvent>; 4 | 5 | export type WorkerMessage = { 6 | id: number | string; 7 | data: T; 8 | }; 9 | 10 | export type InternalWorkerEventCallback = (message: WorkerMessage) => unknown; 11 | 12 | export type UserWorkerEventCallback = (data: T) => unknown; 13 | 14 | export type UserWorkerEventHandler = (data: T) => R | Promise; 15 | -------------------------------------------------------------------------------- /packages/components/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "jsx": "react-jsx", 6 | "isolatedModules": true, 7 | "declaration": true, 8 | "declarationMap": false, 9 | "composite": true, 10 | "rootDir": "src", 11 | "outDir": "dist", 12 | "paths": { 13 | "src": ["./src"] 14 | } 15 | }, 16 | "include": ["src"], 17 | "exclude": ["**/node_modules"], 18 | "references": [ 19 | { 20 | "path": "../types/tsconfig.json" 21 | }, 22 | { 23 | "path": "../utils/tsconfig.json" 24 | }, 25 | { 26 | "path": "../graph/tsconfig.json" 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /packages/core/README.md: -------------------------------------------------------------------------------- 1 | # @rsdoctor/core 2 | 3 | This is the core package of Rsdoctor, providing core tools and analysis capabilities for Rsdoctor plugins. 4 | 5 | ## Documentation 6 | 7 | https://rsdoctor.rs/ 8 | 9 | ## Contributing 10 | 11 | Please read the [Contributing Guide](https://github.com/web-infra-dev/rsdoctor/blob/main/CONTRIBUTING.md). 12 | 13 | ## License 14 | 15 | Rsdoctor is [MIT licensed](https://github.com/web-infra-dev/rsdoctor/blob/main/LICENSE). 16 | -------------------------------------------------------------------------------- /packages/core/modern.config.ts: -------------------------------------------------------------------------------- 1 | import { baseBuildConfig } from '../../scripts/modern.base.config'; 2 | 3 | export default baseBuildConfig; 4 | -------------------------------------------------------------------------------- /packages/core/src/build-utils/build/chunks/assetsModules.ts: -------------------------------------------------------------------------------- 1 | import { 2 | getAssetsModulesData as transform, 3 | ParsedModuleSizeData, 4 | } from '@/build-utils/common/chunks'; 5 | import { parseBundle } from '../utils'; 6 | import { SDK } from '@rsdoctor/types'; 7 | 8 | export async function getAssetsModulesData( 9 | moduleGraph: SDK.ModuleGraphInstance, 10 | chunkGraph: SDK.ChunkGraphInstance, 11 | bundleDir: string, 12 | hasParseBundle = true, 13 | ): Promise { 14 | return transform( 15 | moduleGraph, 16 | chunkGraph, 17 | bundleDir, 18 | hasParseBundle ? { parseBundle } : {}, 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /packages/core/src/build-utils/build/chunks/chunkTransform.ts: -------------------------------------------------------------------------------- 1 | import { Plugin } from '@rsdoctor/types'; 2 | import { chunkTransform as transform } from '@/build-utils/common/chunks'; 3 | 4 | export function chunkTransform( 5 | assetMap: Map, 6 | bundleStats: Plugin.StatsCompilation, 7 | ) { 8 | return transform(assetMap, bundleStats); 9 | } 10 | -------------------------------------------------------------------------------- /packages/core/src/build-utils/build/chunks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './assetsModules'; 2 | export * from './chunkTransform'; 3 | export * from './generateTileGraph'; 4 | export * from './rspack/transform'; 5 | -------------------------------------------------------------------------------- /packages/core/src/build-utils/build/index.ts: -------------------------------------------------------------------------------- 1 | export * as Chunks from './chunks'; 2 | export * as Utils from './utils'; 3 | export * as Loader from './loader'; 4 | export * as Types from '../../types'; 5 | export * as ModuleGraph from './module-graph'; 6 | -------------------------------------------------------------------------------- /packages/core/src/build-utils/build/loader/index.ts: -------------------------------------------------------------------------------- 1 | export * from './probeLoaderPlugin'; 2 | -------------------------------------------------------------------------------- /packages/core/src/build-utils/build/module-graph/index.ts: -------------------------------------------------------------------------------- 1 | export * from './webpack/transform'; 2 | export * from './transform'; 3 | export * from './treeShaking'; 4 | export * from './rspack/transform'; 5 | -------------------------------------------------------------------------------- /packages/core/src/build-utils/build/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './loader'; 2 | export * from './plugin'; 3 | export * from './parseBundle'; 4 | export * from '../loader/probeLoader'; 5 | -------------------------------------------------------------------------------- /packages/core/src/build-utils/common/chunks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './assetsModules'; 2 | export * from './chunkTransform'; 3 | export * from './assetsContent'; 4 | -------------------------------------------------------------------------------- /packages/core/src/build-utils/common/index.ts: -------------------------------------------------------------------------------- 1 | export * as Chunks from './chunks'; 2 | export * as Types from '../../types'; 3 | export * as ModuleGraph from './module-graph'; 4 | export * as TransUtils from './trans-utils'; 5 | export * as Webpack from './webpack/compatible'; 6 | -------------------------------------------------------------------------------- /packages/core/src/build-utils/common/module-graph/index.ts: -------------------------------------------------------------------------------- 1 | export * from './transform'; 2 | export * from './compatible'; 3 | export * from './utils'; 4 | -------------------------------------------------------------------------------- /packages/core/src/build-utils/common/trans-utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './transStats'; 2 | -------------------------------------------------------------------------------- /packages/core/src/build-utils/common/trans-utils/transStats.ts: -------------------------------------------------------------------------------- 1 | import { Plugin, SDK } from '@rsdoctor/types'; 2 | import { Chunks, ModuleGraph } from '..'; 3 | 4 | export async function transStats(json: Plugin.StatsCompilation) { 5 | const chunkGraph: SDK.ChunkGraphInstance = Chunks.chunkTransform( 6 | new Map(), 7 | json, 8 | ); 9 | const moduleGraph = ModuleGraph.getModuleGraphByStats(json, '.', chunkGraph); 10 | const assetsModuleMap = 11 | (await Chunks.getAssetsModulesData( 12 | moduleGraph, 13 | chunkGraph, 14 | json.outputPath || '', 15 | {}, 16 | )) || {}; 17 | Chunks.transformAssetsModulesData(assetsModuleMap, moduleGraph); 18 | return { chunkGraph, moduleGraph }; 19 | } 20 | -------------------------------------------------------------------------------- /packages/core/src/build-utils/index.ts: -------------------------------------------------------------------------------- 1 | export * as Build from './build'; 2 | export * as Common from './common'; 3 | -------------------------------------------------------------------------------- /packages/core/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './build-utils'; 2 | export * as InnerPlugins from './inner-plugins'; 3 | export * from './types'; 4 | -------------------------------------------------------------------------------- /packages/core/src/inner-plugins/constants.ts: -------------------------------------------------------------------------------- 1 | import type { Tap } from 'tapable'; 2 | 3 | export const pluginTapName = 'RsdoctorWebpackPlugin'; 4 | 5 | export const pluginTapPostOptions: Tap = { 6 | name: pluginTapName, 7 | stage: 999, 8 | }; 9 | 10 | export const pluginTapPreOptions: Tap = { 11 | name: pluginTapName, 12 | stage: -999, 13 | }; 14 | 15 | export const internalPluginTapPreOptions = (namespace: string): Tap => ({ 16 | name: `${pluginTapName}:${namespace}`, 17 | stage: -998, 18 | }); 19 | 20 | export const internalPluginTapPostOptions = (namespace: string): Tap => ({ 21 | name: `${pluginTapName}:${namespace}`, 22 | stage: 1000, 23 | }); 24 | -------------------------------------------------------------------------------- /packages/core/src/inner-plugins/index.ts: -------------------------------------------------------------------------------- 1 | export * from './plugins'; 2 | export * from './utils'; 3 | -------------------------------------------------------------------------------- /packages/core/src/inner-plugins/plugins/index.ts: -------------------------------------------------------------------------------- 1 | export * from './loader'; 2 | export * from './plugins'; 3 | export * from './errors'; 4 | export * from './progress'; 5 | export * from './summary'; 6 | export * from './base'; 7 | export * from './bundle'; 8 | export * from './ensureModulesChunkGraph'; 9 | export * from './rules'; 10 | export * from './bundleTagPlugin'; 11 | -------------------------------------------------------------------------------- /packages/core/src/inner-plugins/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './loader'; 2 | export * from './plugin'; 3 | export * from './sdk'; 4 | export * from './config'; 5 | export * from './circleDetect'; -------------------------------------------------------------------------------- /packages/core/src/inner-plugins/utils/sdk.ts: -------------------------------------------------------------------------------- 1 | import { RsdoctorPrimarySDK, RsdoctorSDK } from '@rsdoctor/sdk'; 2 | 3 | let sdks: RsdoctorSDK[] = []; 4 | let sdk: RsdoctorSDK; 5 | 6 | export function setSDK(t: RsdoctorSDK) { 7 | sdks.push(t); 8 | sdk = t; 9 | } 10 | 11 | export function getSDK(builderName?: string) { 12 | if (sdk && sdk.name !== builderName) { 13 | sdk = builderName ? sdks.find((s) => s.name === builderName) || sdk : sdk; 14 | } 15 | if (sdk && builderName && 'parent' in sdk) { 16 | const _sdk = sdk as RsdoctorPrimarySDK; 17 | const slaveSDK = _sdk.parent.slaves.find( 18 | (_sdk: { name: string }) => _sdk.name === builderName, 19 | ); 20 | return slaveSDK || sdk; 21 | } 22 | return sdk; 23 | } 24 | -------------------------------------------------------------------------------- /packages/core/src/rules/index.ts: -------------------------------------------------------------------------------- 1 | export * from './linter'; 2 | export * from './rule'; 3 | 4 | export { rules } from './rules'; 5 | -------------------------------------------------------------------------------- /packages/core/src/rules/rules/cross-chunks-package/types.ts: -------------------------------------------------------------------------------- 1 | export interface Config { 2 | ignore: string[]; 3 | } 4 | -------------------------------------------------------------------------------- /packages/core/src/rules/rules/cross-chunks-package/utils.ts: -------------------------------------------------------------------------------- 1 | export function getErrorMsgForDupPckChunks( 2 | chunks: String[], 3 | pkgName: String, 4 | ): string { 5 | let message = `The same module of Package ${pkgName} was bundled into different chunks:\n`; 6 | 7 | for (const chunkName of chunks) { 8 | message += ` ${chunkName}\n`; 9 | } 10 | 11 | return message.slice(0, -1); 12 | } 13 | -------------------------------------------------------------------------------- /packages/core/src/rules/rules/default-import-check/types.ts: -------------------------------------------------------------------------------- 1 | export interface Config { 2 | /** Packages that need to be ignored */ 3 | ignore: string[]; 4 | } 5 | -------------------------------------------------------------------------------- /packages/core/src/rules/rules/ecma-version-check/types.ts: -------------------------------------------------------------------------------- 1 | import type { PluginCheckSyntaxOptions } from '@rsbuild/plugin-check-syntax'; 2 | 3 | export interface Config extends PluginCheckSyntaxOptions {} 4 | -------------------------------------------------------------------------------- /packages/core/src/rules/rules/ecma-version-check/utils.ts: -------------------------------------------------------------------------------- 1 | import type { ECMAVersion } from '@rsdoctor/utils/ruleUtils'; 2 | 3 | export function getVersionNumber(ECMAString: ECMAVersion) { 4 | const version = ECMAString.match(/\d/); 5 | 6 | return version?.length ? Number(version[0]) : undefined; 7 | } 8 | -------------------------------------------------------------------------------- /packages/core/src/rules/rules/index.ts: -------------------------------------------------------------------------------- 1 | import { rule as duplicatePackage } from './duplicate-package'; 2 | import { rule as defaultImportCheck } from './default-import-check'; 3 | import { rule as loaderPerformanceOptimization } from './loader-performance-optimization'; 4 | import { rule as ecmaVersionCheck } from './ecma-version-check'; 5 | import { rule as crossChunksPackage } from './cross-chunks-package'; 6 | 7 | export const rules = [ 8 | duplicatePackage, 9 | defaultImportCheck, 10 | loaderPerformanceOptimization, 11 | ecmaVersionCheck, 12 | crossChunksPackage, 13 | ]; 14 | -------------------------------------------------------------------------------- /packages/core/src/rules/rules/loader-performance-optimization/types.ts: -------------------------------------------------------------------------------- 1 | import type { SDK } from '@rsdoctor/types'; 2 | 3 | export interface Config { 4 | /** 5 | * loaders which should be ignore. 6 | */ 7 | ignore?: (string | RegExp)[]; 8 | /** 9 | * threshold which the loader total costs. 10 | * @unit millisecond 11 | * @default 5000 12 | */ 13 | threshold?: number; 14 | /** 15 | * the file extensions which will be match in rule check. 16 | * @default ["js", "css", "jpg", "jpeg", "png", "gif", "webp", "svg"] 17 | */ 18 | extensions?: (string | RegExp)[]; 19 | } 20 | 21 | export interface LoaderMapValue extends SDK.LoaderTransformData { 22 | __resource__: SDK.ResourceData; 23 | __costs__: number; 24 | } 25 | -------------------------------------------------------------------------------- /packages/core/src/rules/rules/loader-performance-optimization/utils.ts: -------------------------------------------------------------------------------- 1 | export function match(str: string, patterns: (string | RegExp)[]) { 2 | if (patterns.length === 0) return false; 3 | 4 | return patterns.some((p) => { 5 | if (typeof p === 'string') return str === p; 6 | if (p instanceof RegExp) return p.test(str); 7 | return false; 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /packages/core/src/rules/utils.ts: -------------------------------------------------------------------------------- 1 | import { Linter } from '@rsdoctor/types'; 2 | 3 | export function toSeverity( 4 | input: Linter.SeverityInput, 5 | defaultLevel: Linter.Severity, 6 | ): Linter.Severity { 7 | if (input === 'off') { 8 | return Linter.Severity.Ignore; 9 | } 10 | 11 | if (input === 'on') { 12 | return defaultLevel; 13 | } 14 | 15 | const key = `${input[0].toUpperCase()}${input.slice( 16 | 1, 17 | )}` as Linter.SeverityString; 18 | return Linter.Severity[key] as Linter.Severity; 19 | } 20 | 21 | export function noop() {} 22 | -------------------------------------------------------------------------------- /packages/core/src/types/chunks.ts: -------------------------------------------------------------------------------- 1 | import { Plugin, SDK } from '@rsdoctor/types'; 2 | 3 | export type AssetsModules = { 4 | label?: string; 5 | isAsset?: boolean; 6 | modules?: Plugin.StatsModule[]; 7 | }; 8 | 9 | export type ParseBundle = ( 10 | assetFile: string, 11 | modules: Pick[], 12 | ) => { 13 | modules?: Record; 14 | src?: string; 15 | runtimeSrc?: string; 16 | }; 17 | -------------------------------------------------------------------------------- /packages/core/src/types/declare.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'webpack-bundle-analyzer/lib/viewer' { 2 | export function generateReport(bundleStats: any, opts: any): Promise; 3 | } 4 | -------------------------------------------------------------------------------- /packages/core/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './chunks'; 2 | export * from './rules'; 3 | export * from './webpack'; 4 | export * from './loader'; 5 | export * from './plugin'; 6 | -------------------------------------------------------------------------------- /packages/core/src/types/loader.ts: -------------------------------------------------------------------------------- 1 | import { Loader } from '@rsdoctor/utils/common'; 2 | 3 | export interface ProxyLoaderInternalOptions { 4 | cwd: string; 5 | /** 6 | * the url host of http server(which used to collect data). 7 | */ 8 | host: string; 9 | /** 10 | * correct loader path. 11 | */ 12 | loader: string; 13 | /** include the loader option */ 14 | hasOptions: boolean; 15 | skipLoaders: string[]; 16 | } 17 | 18 | export interface ProxyLoaderOptions { 19 | [key: string]: any; 20 | [Loader.LoaderInternalPropertyName]: ProxyLoaderInternalOptions; 21 | } 22 | -------------------------------------------------------------------------------- /packages/core/src/types/rules.ts: -------------------------------------------------------------------------------- 1 | import { RuleSetRule } from 'webpack'; 2 | 3 | export interface Rule extends RuleSetRule { 4 | /** 5 | * https://webpack.js.org/configuration/module/#ruleloaders 6 | */ 7 | loaders: RuleSetRule['use']; 8 | } 9 | -------------------------------------------------------------------------------- /packages/core/tests/build/utils/bundles/validBundleWithArrowFunction.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([0],[(t,e,r)=>{ 2 | console.log('Hello world!'); 3 | }]); 4 | -------------------------------------------------------------------------------- /packages/core/tests/build/utils/bundles/validBundleWithArrowFunction.modules.json: -------------------------------------------------------------------------------- 1 | { 2 | "modules": { 3 | "0": { 4 | "size": 43, 5 | "sizeConvert": "43 B", 6 | "content": "(t,e,r)=>{\n console.log('Hello world!');\n}" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/core/tests/build/utils/bundles/validBundleWithEsNextFeatures.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([2],[function(t,e,r){ 2 | async function asyncFn() { 3 | return await Promise.resolve(1); 4 | } 5 | 6 | const arrowFn = arg => arg * 2; 7 | 8 | function* generatorFn() { 9 | yield 1; 10 | } 11 | 12 | class TestClass { 13 | static staticMethod() {} 14 | constructor() {} 15 | testMethod() {} 16 | } 17 | 18 | for (const i of [1, 2, 3]) { 19 | console.log(i); 20 | } 21 | 22 | let obj = { 23 | ['a' + 'b']: 1, 24 | func() {} 25 | }; 26 | 27 | const [var1, var2] = [1, 2]; 28 | }]); 29 | -------------------------------------------------------------------------------- /packages/core/tests/build/utils/bundles/validBundleWithEsNextFeatures.modules.json: -------------------------------------------------------------------------------- 1 | { 2 | "modules": { 3 | "0": { 4 | "content": "function(t,e,r){\n async function asyncFn() {\n return await Promise.resolve(1);\n }\n\n const arrowFn = arg => arg * 2;\n\n function* generatorFn() {\n yield 1;\n }\n\n class TestClass {\n static staticMethod() {}\n constructor() {}\n testMethod() {}\n }\n\n for (const i of [1, 2, 3]) {\n console.log(i);\n }\n\n let obj = {\n ['a' + 'b']: 1,\n func() {}\n };\n\n const [var1, var2] = [1, 2];\n}", 5 | "size": 406, 6 | "sizeConvert": "406 B" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/core/tests/build/utils/bundles/validCommonBundleWithModulesAsArray.modules.json: -------------------------------------------------------------------------------- 1 | { 2 | "modules": { 3 | "0": { 4 | "size": 95, 5 | "sizeConvert": "95 B", 6 | "content": "function(e,t,n){n(1),n(21),n(96),n(306),n(23),n(150),n(57),n(56),n(34),n(138),e.exports=n(348)}" 7 | }, 8 | "5": { 9 | "size": 15, 10 | "sizeConvert": "15 B", 11 | "content": "function(e,t){}" 12 | }, 13 | "33": { 14 | "size": 46, 15 | "sizeConvert": "46 B", 16 | "content": "function(e,t,n){\"use strict\";e.exports=n(680)}" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/core/tests/build/utils/loader/basic.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { extractLoaderName } from '@/build-utils/build/utils'; 3 | 4 | describe('test src/build/utils/loader.ts basic functions', () => { 5 | it('extractLoaderName()', () => { 6 | expect(extractLoaderName('cache-loader')).toEqual('cache-loader'); 7 | expect( 8 | extractLoaderName('/Users/node_modules/cache-loader/lib/index.js'), 9 | ).toEqual('cache-loader'); 10 | expect( 11 | extractLoaderName('/Users/node_modules/cache-loader/lib/loader.js'), 12 | ).toEqual('cache-loader/lib/loader'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/core/tests/common/utils.ts: -------------------------------------------------------------------------------- 1 | import { relative } from 'path'; 2 | import { SDK } from '@rsdoctor/types'; 3 | export function removeAbsModulePath( 4 | graph: SDK.ModuleGraphInstance, 5 | root: string, 6 | ) { 7 | for (const mod of graph.getModules()) { 8 | (mod as any).path = relative(root, mod.path); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/default-export/expression/index.js: -------------------------------------------------------------------------------- 1 | import utils from './utils'; 2 | 3 | console.log(utils); 4 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/default-export/expression/utils.js: -------------------------------------------------------------------------------- 1 | const a = 0; 2 | 3 | export const ab = 123; 4 | 5 | export default a + 1; 6 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/default-export/literal/index.js: -------------------------------------------------------------------------------- 1 | import utils from './utils'; 2 | 3 | console.log(utils); 4 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/default-export/literal/utils.js: -------------------------------------------------------------------------------- 1 | export default 'utils'; 2 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/default-export/variable/index.js: -------------------------------------------------------------------------------- 1 | import utils from './utils'; 2 | 3 | console.log(utils); 4 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/default-export/variable/utils.js: -------------------------------------------------------------------------------- 1 | const abc = 123; 2 | 3 | export const abcd = 1234; 4 | 5 | export default abc; 6 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/loaders/basic-loader-esm.js: -------------------------------------------------------------------------------- 1 | Object.defineProperty(exports, '__esModule', { value: true }); 2 | 3 | exports.default = loader; 4 | 5 | function loader(code) { 6 | return code; 7 | } 8 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/loaders/basic-loader.js: -------------------------------------------------------------------------------- 1 | module.exports = loader; 2 | 3 | function loader(code) { 4 | return code; 5 | } 6 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/loaders/pitch-loader-esm.js: -------------------------------------------------------------------------------- 1 | Object.defineProperty(exports, '__esModule', { value: true }); 2 | 3 | exports.default = loader; 4 | 5 | exports.default.pitch = pitch; 6 | 7 | function loader(code) { 8 | return code; 9 | } 10 | 11 | function pitch() { 12 | return 'pitch'; 13 | } 14 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/loaders/pitch-loader.js: -------------------------------------------------------------------------------- 1 | module.exports = loader; 2 | 3 | module.exports.pitch = pitch; 4 | 5 | function loader(code) { 6 | return code; 7 | } 8 | 9 | function pitch() { 10 | return 'pitch'; 11 | } 12 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/loaders/raw-loader-esm.js: -------------------------------------------------------------------------------- 1 | Object.defineProperty(exports, '__esModule', { value: true }); 2 | 3 | exports.default = loader; 4 | 5 | exports.default.raw = true; 6 | 7 | function loader(code) { 8 | return code; 9 | } 10 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/loaders/raw-loader.js: -------------------------------------------------------------------------------- 1 | module.exports = loader; 2 | 3 | module.exports.raw = true; 4 | 5 | function loader(code) { 6 | return code; 7 | } 8 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/normal-module-in-multi-concatenation/common.js: -------------------------------------------------------------------------------- 1 | export const key1 = 'key1'; 2 | export const key2 = 'key2'; 3 | export const key3 = 'key3'; 4 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/normal-module-in-multi-concatenation/entry1.js: -------------------------------------------------------------------------------- 1 | import { key1, key3 } from './common'; 2 | 3 | console.log(key1); 4 | console.log(key3); 5 | -------------------------------------------------------------------------------- /packages/core/tests/fixtures/normal-module-in-multi-concatenation/entry2.js: -------------------------------------------------------------------------------- 1 | import { key2, key3 } from './common'; 2 | 3 | console.log(key2); 4 | console.log(key3); 5 | -------------------------------------------------------------------------------- /packages/core/tests/plugins/__snapshots__/circle-check.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`test checkCirclePath function > makeRulesSerializable() 1`] = ` 4 | [ 5 | [ 6 | "foo", 7 | "a", 8 | ], 9 | [ 10 | "foo", 11 | "x", 12 | "foo", 13 | ], 14 | ] 15 | `; 16 | 17 | exports[`test checkCirclePath function > makeRulesSerializable() 2`] = ` 18 | { 19 | "a": { 20 | "b": "b", 21 | }, 22 | "foo": "[Circular]", 23 | } 24 | `; 25 | -------------------------------------------------------------------------------- /packages/core/tests/plugins/__snapshots__/config.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`test src/utils/config.ts > makeRulesSerializable() 1`] = ` 4 | "[ 5 | { 6 | \\"test\\": \\"/rule1/\\" 7 | }, 8 | { 9 | \\"test\\": \\"/rule2/\\", 10 | \\"oneOf\\": [ 11 | { 12 | \\"test\\": \\"/oneof1/\\" 13 | }, 14 | { 15 | \\"test\\": \\"aaa\\" 16 | } 17 | ], 18 | \\"exclude\\": { 19 | \\"and\\": [ 20 | \\"/exclude_and1/\\", 21 | \\"/exclude_and2/\\" 22 | ], 23 | \\"or\\": [ 24 | \\"/exclude_or/\\" 25 | ], 26 | \\"not\\": \\"/exclude_not/\\" 27 | } 28 | } 29 | ]" 30 | `; 31 | -------------------------------------------------------------------------------- /packages/core/tests/plugins/fixtures/a.js: -------------------------------------------------------------------------------- 1 | console.log('a'); 2 | -------------------------------------------------------------------------------- /packages/core/tests/plugins/fixtures/b.js: -------------------------------------------------------------------------------- 1 | const ll = 1; 2 | 3 | console.log('a'); 4 | 5 | function kk() { 6 | console.log('hhe: ', ll); 7 | return '111'; 8 | } 9 | 10 | kk(); 11 | -------------------------------------------------------------------------------- /packages/core/tests/plugins/fixtures/loaders/serialize-query-to-comment.js: -------------------------------------------------------------------------------- 1 | const { parseQuery } = require('loader-utils'); 2 | 3 | /** 4 | * @type {import("webpack").LoaderDefinitionFunction<{}, {}>} 5 | */ 6 | module.exports = function (input) { 7 | const res = [input, `// ${JSON.stringify(this.query)}`]; 8 | 9 | // Based on https://github.com/windicss/windicss-webpack-plugin/blob/main/src/loaders/windicss-template.ts#L42 10 | // test the loader query 11 | if (this.query !== '') { 12 | res.push(`// ${JSON.stringify(parseQuery(this.query))}`); 13 | } 14 | 15 | return res.join('\n'); 16 | }; 17 | -------------------------------------------------------------------------------- /packages/core/tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@/*": ["../src/*"], 7 | } 8 | }, 9 | "include": ["./**/*.ts"], 10 | "exclude": ["../**/node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "outDir": "./dist", 6 | "baseUrl": "./", 7 | "paths": { 8 | "@/*": ["./src/*"] 9 | }, 10 | "rootDir": "src" 11 | }, 12 | "include": ["src"], 13 | "exclude": ["**/node_modules"], 14 | "references": [ 15 | { 16 | "path": "../types/tsconfig.json" 17 | }, 18 | { 19 | "path": "../utils/tsconfig.json" 20 | }, 21 | { 22 | "path": "../graph/tsconfig.json" 23 | }, 24 | { 25 | "path": "../sdk/tsconfig.json" 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /packages/document/README.md: -------------------------------------------------------------------------------- 1 | # Rsdoctor website 2 | 3 | ## Writing style guide 4 | 5 | The same as Rspack: [Writing style guide](https://github.com/web-infra-dev/rspack/tree/main/website#writing-style-guide). 6 | -------------------------------------------------------------------------------- /packages/document/docs/en/_meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "text": "Guide", 4 | "link": "/guide/start/intro", 5 | "activeMatch": "/guide/" 6 | }, 7 | { 8 | "text": "Config", 9 | "link": "/config/options/options", 10 | "activeMatch": "/config/" 11 | }, 12 | { 13 | "text": "Blog", 14 | "link": "/blog/release/release-note-1_0", 15 | "activeMatch": "/blog/" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /packages/document/docs/en/blog/_meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "dir", 4 | "name": "release", 5 | "label": "Release Note" 6 | }, 7 | { 8 | "type": "dir", 9 | "name": "topic", 10 | "label": "Topic" 11 | } 12 | ] 13 | -------------------------------------------------------------------------------- /packages/document/docs/en/blog/release/_meta.json: -------------------------------------------------------------------------------- 1 | ["release-note-1_0", "release-note-0_4", "release-note-0_3", "release-note-0_1"] 2 | -------------------------------------------------------------------------------- /packages/document/docs/en/blog/topic/_meta.json: -------------------------------------------------------------------------------- 1 | ["loader-optimization", "duplicate-pkg-problem"] 2 | -------------------------------------------------------------------------------- /packages/document/docs/en/config/_meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "dir", 4 | "name": "options", 5 | "label": "Config Instruction" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /packages/document/docs/en/config/options/_meta.json: -------------------------------------------------------------------------------- 1 | ["options", "term"] 2 | -------------------------------------------------------------------------------- /packages/document/docs/en/config/options/term.mdx: -------------------------------------------------------------------------------- 1 | # Terminology 2 | 3 | ## Common terminology 4 | 5 | ### manifest.json 6 | 7 | When your project integrates with plugins provided by **Rsdoctor** (such as `@rsdoctor/webpack-plugin`, etc.), Rsdoctor will write **build-related data information** into a local JSON file: 8 | 9 | - The **filename is `manifest.json`** 10 | - The output path of this file is `output directory of the project/.rsdoctor/manifest.json` 11 | -------------------------------------------------------------------------------- /packages/document/docs/en/guide/_meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "dir", 4 | "name": "start", 5 | "label": "Getting Started" 6 | }, 7 | { 8 | "type": "dir", 9 | "name": "usage", 10 | "label": "Usage" 11 | }, 12 | { 13 | "type": "dir", 14 | "name": "rules", 15 | "label": "Scan Rules" 16 | }, 17 | { 18 | "type": "dir", 19 | "name": "more", 20 | "label": "More" 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /packages/document/docs/en/guide/more/_meta.json: -------------------------------------------------------------------------------- 1 | ["faq", "rules"] 2 | -------------------------------------------------------------------------------- /packages/document/docs/en/guide/more/rules.mdx: -------------------------------------------------------------------------------- 1 | # Rule index 2 | 3 | import RuleIndex from '@components/RuleIndex'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/document/docs/en/guide/rules/_meta.json: -------------------------------------------------------------------------------- 1 | ["rules", "rule-custom", "upload-data"] 2 | -------------------------------------------------------------------------------- /packages/document/docs/en/guide/start/_meta.json: -------------------------------------------------------------------------------- 1 | ["intro", "quick-start", "features", "cicd", "cli"] 2 | -------------------------------------------------------------------------------- /packages/document/docs/en/guide/usage/_meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | "project-overall", 3 | "bundle-overall", 4 | "compile-overall", 5 | "compile-alerts", 6 | "bundle-alerts", 7 | "loaders-timeline", 8 | "loaders-analysis", 9 | "plugins-analysis", 10 | "bundle-size", 11 | "module-analysis", 12 | "resolver", 13 | "rule-config", 14 | "bundle-diff" 15 | ] 16 | -------------------------------------------------------------------------------- /packages/document/docs/en/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | pageType: home 3 | titleSuffix: ' - Build Analyzer' 4 | --- 5 | -------------------------------------------------------------------------------- /packages/document/docs/en/shared/features-rspack.md: -------------------------------------------------------------------------------- 1 | ```ts 2 | interface RsdoctorRspackPluginFeatures { 3 | /** 4 | * turn off it if you need not to analyze the executions of webpack loaders. 5 | * @default true 6 | */ 7 | loader?: boolean; 8 | /** 9 | * turn off it if you need not to analyze the executions of webpack plugins. 10 | * @default true 11 | */ 12 | plugins?: boolean; 13 | /** 14 | * turn off it if you need not to analyze the output bundle. 15 | * @default true 16 | */ 17 | bundle?: boolean; 18 | /** 19 | * turn on it if you just use lite mode. This mode do not have source codes. 20 | * @default false 21 | * @deprecated 22 | */ 23 | lite?: boolean; 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /packages/document/docs/public/netlify.toml: -------------------------------------------------------------------------------- 1 | # Redirect rsdoctor.dev to rsdoctor.rs 2 | [[redirects]] 3 | from = "https://rsdoctor.dev/*" 4 | to = "https://rsdoctor.rs/:splat" 5 | status = 301 6 | force = true 7 | 8 | [[redirects]] 9 | from = "/*" 10 | to = "/404.html" 11 | status = 404 12 | -------------------------------------------------------------------------------- /packages/document/docs/zh/_meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "text": "指南", 4 | "link": "/guide/start/intro", 5 | "activeMatch": "/guide/" 6 | }, 7 | { 8 | "text": "配置", 9 | "link": "/config/options/options", 10 | "activeMatch": "/config/" 11 | }, 12 | { 13 | "text": "博客", 14 | "link": "/blog/release/release-note-1_0", 15 | "activeMatch": "/blog/" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /packages/document/docs/zh/blog/_meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "dir", 4 | "name": "release", 5 | "label": "Release 公告" 6 | }, 7 | { 8 | "type": "dir", 9 | "name": "topic", 10 | "label": "专题" 11 | } 12 | ] 13 | -------------------------------------------------------------------------------- /packages/document/docs/zh/blog/release/_meta.json: -------------------------------------------------------------------------------- 1 | ["release-note-1_0", "release-note-0_4", "release-note-0_3", "release-note-0_1"] 2 | -------------------------------------------------------------------------------- /packages/document/docs/zh/blog/topic/_meta.json: -------------------------------------------------------------------------------- 1 | ["loader-optimization", "duplicate-pkg-problem"] 2 | -------------------------------------------------------------------------------- /packages/document/docs/zh/config/_meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "dir", 4 | "name": "options", 5 | "label": "配置说明" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /packages/document/docs/zh/config/options/_meta.json: -------------------------------------------------------------------------------- 1 | ["options", "term"] 2 | -------------------------------------------------------------------------------- /packages/document/docs/zh/config/options/term.mdx: -------------------------------------------------------------------------------- 1 | # 术语 2 | 3 | ## 通用术语 4 | 5 | ### manifest.json 6 | 7 | 当你的项目集成 **Rsdoctor** 提供的插件(比如 `@rsdoctor/webpack-plugin` 等)之后,Rsdoctor 会将项目**构建相关的数据信息**写入到一个本地的 JSON 文件中: 8 | 9 | - 其**文件名为 `manifest.json`** 10 | - 该文件的输出**路径为 `项目产物目录/.rsdoctor/manifest.json`** 11 | -------------------------------------------------------------------------------- /packages/document/docs/zh/guide/_meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "dir", 4 | "name": "start", 5 | "label": "快速开始" 6 | }, 7 | { 8 | "type": "dir", 9 | "name": "usage", 10 | "label": "功能介绍" 11 | }, 12 | { 13 | "type": "dir", 14 | "name": "rules", 15 | "label": "扫描规则" 16 | }, 17 | { 18 | "type": "dir", 19 | "name": "more", 20 | "label": "更多" 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /packages/document/docs/zh/guide/more/_meta.json: -------------------------------------------------------------------------------- 1 | ["faq", "rules"] 2 | -------------------------------------------------------------------------------- /packages/document/docs/zh/guide/more/rules.mdx: -------------------------------------------------------------------------------- 1 | # Rule index 2 | 3 | import RuleIndex from '@components/RuleIndex'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/document/docs/zh/guide/rules/_meta.json: -------------------------------------------------------------------------------- 1 | ["rules", "rule-custom", "upload-data"] 2 | -------------------------------------------------------------------------------- /packages/document/docs/zh/guide/start/_meta.json: -------------------------------------------------------------------------------- 1 | ["intro", "quick-start", "features", "cicd", "cli"] 2 | -------------------------------------------------------------------------------- /packages/document/docs/zh/guide/start/quick-start.mdx: -------------------------------------------------------------------------------- 1 | # 快速开始 2 | 3 | 本文档将介绍如何接入 Rsdoctor 能力。 4 | 5 | ## 第一步:安装依赖 6 | 7 | import { PackageManagerTabs } from '@theme'; 8 | 9 | ### Rspack 项目 10 | 11 | 基于 Rspack 或 Rsbuild 的项目,安装以下依赖: 12 | 13 | 14 | 15 | ### Webpack 项目 16 | 17 | :::tip 18 | Rsdoctor 仅支持 webpack >= 5。 19 | ::: 20 | 21 | 基于 webpack 的项目,安装以下依赖: 22 | 23 | 24 | 25 | --- 26 | 27 | import QuickStartShared from './quick-start-shared.mdx'; 28 | 29 | 30 | -------------------------------------------------------------------------------- /packages/document/docs/zh/guide/usage/_meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | "project-overall", 3 | "bundle-overall", 4 | "compile-overall", 5 | "compile-alerts", 6 | "bundle-alerts", 7 | "loaders-timeline", 8 | "loaders-analysis", 9 | "plugins-analysis", 10 | "bundle-size", 11 | "module-analysis", 12 | "resolver", 13 | "rule-config", 14 | "bundle-diff" 15 | ] 16 | -------------------------------------------------------------------------------- /packages/document/docs/zh/guide/usage/bundle-alerts.mdx: -------------------------------------------------------------------------------- 1 | # 产物预警 2 | 3 | ## 功能介绍 4 | 5 | Overall 页面中的 `Alerts` 部分用于展示「构建规则」及「编译规则」结果,如下图。规则展示除了展示在页面中,还会展示在终端日志中。 6 | 7 | 8 | 9 | 可以查看下方的产物预警内置规则了解各个规则详情。 10 | 11 | ### 内置规则 12 | 13 | 1. [[E1001] Duplicate Packages](../../guide/rules/rules#e1001-duplicate-packages) 14 | 2. [[E1002] Cross Chunks Package](../../guide/rules/rules#e1002-cross-chunks-package) 15 | 3. [[E1004] ECMA Version Check](../../guide/rules/rules#e1004-ecma-version-check) 16 | 17 | 具体可以查看[内置规则](../../guide/rules/rules)。 18 | -------------------------------------------------------------------------------- /packages/document/docs/zh/guide/usage/compile-alerts.mdx: -------------------------------------------------------------------------------- 1 | # 编译预警 2 | 3 | 我们还集成了一些基于编译数据做检测的能力,如果本次编译结果中,存在命中了我们定义的[规则](../more/rules)的数据,则会在 **Rsdoctor** 主界面下方出现 `Compile Alerts` 模块,参考下图所示: 4 | 5 | 6 | 7 | 通过该模块可以比较直观的看到我们项目在编译方面的一些预警信息,有助于我们可以更进一步优化项目的编译性能。 8 | 9 | ## 规则 10 | 11 | 目前编译规则有: 12 | 13 | :::tip 14 | [规则列表](../more/rules) 15 | ::: 16 | 17 | - `E1003` Loader 性能检查。[[E1003] Loader Performance Optimization](/guide/rules/rules#e1003-loader-performance-optimization) 18 | - `E1005` 默认导入检查。[[E1005] Default Import Check](/guide/rules/rules#e1005-default-import-check) 19 | -------------------------------------------------------------------------------- /packages/document/docs/zh/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | pageType: home 3 | titleSuffix: ' - 构建分析工具' 4 | --- 5 | -------------------------------------------------------------------------------- /packages/document/docs/zh/shared/features-rspack.md: -------------------------------------------------------------------------------- 1 | ```ts 2 | interface RsdoctorRspackPluginFeatures { 3 | /** 4 | * turn off it if you need not to analyze the executions of webpack loaders. 5 | * @default true 6 | */ 7 | loader?: boolean; 8 | /** 9 | * turn off it if you need not to analyze the executions of webpack plugins. 10 | * @default true 11 | */ 12 | plugins?: boolean; 13 | /** 14 | * turn off it if you need not to analyze the output bundle. 15 | * @default true 16 | */ 17 | bundle?: boolean; 18 | /** 19 | * turn on it if you just use lite mode. This mode do not have source codes. 20 | * @default false 21 | * @deprecated 22 | */ 23 | lite?: boolean; 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /packages/document/docs/zh/shared/mode-intro.md: -------------------------------------------------------------------------------- 1 | - **normal 模式:** 在构建产物目录中生成一个 `.rsdoctor` 文件夹,其中包含各种数据文件,并在报告页面中展示代码。输出目录可以通过 [reportDir](/config/options/options#reportdir) 进行配置。 2 | 3 | - **brief 模式:** 在构建产物目录的 `.rsdoctor` 文件夹中生成一个 HTML 报告文件,所有构建分析数据会整合注入到这个 HTML 文件中,可以通过浏览器打开该 HTML 文件查看报告。brief 模式还有更多配置项,详细信息请参阅:[brief](/config/options/options#brief). 4 | 5 | - **lite 模式:** 基于普通模式,不展示源码和产物代码,仅显示打包后的代码信息。 6 | -------------------------------------------------------------------------------- /packages/document/theme/components/Copyright.module.scss: -------------------------------------------------------------------------------- 1 | @media (min-width: 640px) { 2 | .copyRight { 3 | padding: 2rem; 4 | } 5 | } 6 | 7 | .copyRight { 8 | bottom: 0; 9 | margin-top: 6rem; 10 | padding-top: 2rem; 11 | padding-bottom: 2rem; 12 | padding-left: 1.5rem; 13 | padding-right: 1.5rem; 14 | 15 | width: 100%; 16 | border-top: 1px solid var(--rp-c-divider-light); 17 | } 18 | 19 | .copyRightInner { 20 | margin: 0 auto; 21 | width: 100%; 22 | text-align: center; 23 | } 24 | 25 | .copyRightText { 26 | font-weight: 400; 27 | font-size: 0.875rem; 28 | color: var(--rp-c-text-2); 29 | } 30 | -------------------------------------------------------------------------------- /packages/document/theme/components/Copyright.tsx: -------------------------------------------------------------------------------- 1 | import styles from './Copyright.module.scss'; 2 | 3 | export const CopyRight = () => { 4 | return ( 5 |
6 |
7 |
8 |

9 | Rsdoctor is free and open source software released under the MIT 10 | license. 11 |

12 |

© 2024-present ByteDance Inc.

13 |
14 |
15 |
16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /packages/document/theme/components/Features.module.scss: -------------------------------------------------------------------------------- 1 | :global { 2 | .max-w-6xl.flex.m-auto { 3 | max-width: 1200px; 4 | } 5 | html.dark { 6 | --rp-home-feature-bg: linear-gradient( 7 | 135deg, 8 | rgba(255, 255, 255, 0), 9 | rgba(255, 255, 255, 0.03) 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/document/theme/components/Hero.module.scss: -------------------------------------------------------------------------------- 1 | :global { 2 | .rs-oval { 3 | width: 70% !important; 4 | height: 70% !important; 5 | top: calc(50% + 20px) !important; 6 | left: calc(50% + 5px) !important; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/document/theme/components/NextSteps.module.scss: -------------------------------------------------------------------------------- 1 | .next-steps { 2 | display: flex; 3 | flex-wrap: wrap; 4 | justify-content: space-between; 5 | margin-top: 3rem; 6 | } 7 | -------------------------------------------------------------------------------- /packages/document/theme/components/NextSteps.tsx: -------------------------------------------------------------------------------- 1 | import styles from './NextSteps.module.scss'; 2 | 3 | const NextSteps = (props: { children?: React.ReactNode }) => { 4 | return
{props.children}
; 5 | }; 6 | 7 | export default NextSteps; 8 | -------------------------------------------------------------------------------- /packages/document/theme/components/Step.tsx: -------------------------------------------------------------------------------- 1 | import { useUrl } from '../utils'; 2 | import styles from './Step.module.scss'; 3 | 4 | const Step = (props: { href: string; title: string; description: string }) => { 5 | return ( 6 | 7 |

{props.title}

8 |

{props.description}

9 |
10 | ); 11 | }; 12 | 13 | export default Step; 14 | -------------------------------------------------------------------------------- /packages/document/theme/components/ToolStack.tsx: -------------------------------------------------------------------------------- 1 | import { containerStyle } from '@rstack-dev/doc-ui/section-style'; 2 | import { ToolStack as BaseToolStack } from '@rstack-dev/doc-ui/tool-stack'; 3 | import { useLang } from 'rspress/runtime'; 4 | 5 | export function ToolStack() { 6 | const lang = useLang(); 7 | return ( 8 |
9 | 10 |
11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /packages/document/theme/components/utils.ts: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | import { useLang, usePageData, withBase } from 'rspress/runtime'; 3 | 4 | export function useI18nUrl() { 5 | const lang = useLang(); 6 | const { 7 | siteData: { lang: defaultLang }, 8 | } = usePageData(); 9 | return useCallback( 10 | (url: string) => withBase(lang === defaultLang ? url : `/${lang}${url}`), 11 | [lang, defaultLang], 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /packages/document/theme/global.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.module.scss' { 2 | const classes: { readonly [key: string]: string }; 3 | export default classes; 4 | } 5 | -------------------------------------------------------------------------------- /packages/document/theme/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --rp-c-brand: #ff5e00; 3 | --rp-c-brand-dark: #ff704d; 4 | --rp-c-brand-darker: #ff704d; 5 | --rp-c-brand-light: #ff7524; 6 | --rp-c-brand-lighter: #ff7524; 7 | --rp-c-link: var(--rp-c-brand); 8 | --rp-c-brand-tint: rgba(255, 94, 0, 0.07); 9 | } 10 | 11 | .dark { 12 | --rp-c-link: var(--rp-c-brand-light); 13 | } 14 | 15 | button:focus, 16 | button:focus-visible { 17 | outline: none; 18 | } 19 | 20 | [disabled] { 21 | cursor: not-allowed; 22 | } 23 | 24 | [role='tablist'] { 25 | max-width: 100vw; 26 | padding: 0 10px; 27 | } 28 | -------------------------------------------------------------------------------- /packages/document/theme/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import { BackgroundImage } from '@rstack-dev/doc-ui/background-image'; 2 | import { CopyRight } from '../components/Copyright'; 3 | import { Hero } from '../components/Hero'; 4 | import { Features } from '../components/Features'; 5 | import { ToolStack } from '../components/ToolStack'; 6 | 7 | export function HomeLayout() { 8 | return ( 9 |
10 | 11 | 12 | 13 | 14 | 15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /packages/document/theme/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.module.scss' { 2 | const classes: { [key: string]: string }; 3 | export default classes; 4 | } 5 | 6 | declare module '*.png' { 7 | const value: string; 8 | export default value; 9 | } 10 | -------------------------------------------------------------------------------- /packages/document/theme/utils.ts: -------------------------------------------------------------------------------- 1 | import { useLang, withBase, usePageData } from 'rspress/runtime'; 2 | 3 | export function useUrl(url: string) { 4 | const lang = useLang(); 5 | const { 6 | siteData: { lang: defaultLang }, 7 | } = usePageData(); 8 | return withBase(lang === defaultLang ? url : `/${lang}${url}`); 9 | } 10 | -------------------------------------------------------------------------------- /packages/document/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "jsx": "react-jsx", 6 | "isolatedModules": true, 7 | "declaration": true, 8 | "composite": true, 9 | "outDir": "dist", 10 | "paths": { 11 | "@zh/*": ["./docs/zh/*"], 12 | "@en/*": ["./docs/en/*"], 13 | "@components/*": ["./theme/components/*"], 14 | "i18n": ["./i18n.json"] 15 | } 16 | }, 17 | "mdx": { 18 | "checkMdx": true 19 | }, 20 | "include": ["src", "theme", "i18n.json"], 21 | "exclude": ["**/node_modules"], 22 | "references": [ 23 | { 24 | "path": "../types/tsconfig.json" 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /packages/graph/README.md: -------------------------------------------------------------------------------- 1 | # @rsdoctor/graph 2 | 3 | This package is the intermediate data layer of Rsdoctor. 4 | 5 | ## Documentation 6 | 7 | https://rsdoctor.rs/ 8 | 9 | ## Contributing 10 | 11 | Please read the [Contributing Guide](https://github.com/web-infra-dev/rsdoctor/blob/main/CONTRIBUTING.md). 12 | 13 | ## License 14 | 15 | Rsdoctor is [MIT licensed](https://github.com/web-infra-dev/rsdoctor/blob/main/LICENSE). 16 | -------------------------------------------------------------------------------- /packages/graph/modern.config.ts: -------------------------------------------------------------------------------- 1 | import { configWithEsm } from '../../scripts/modern.base.config'; 2 | 3 | export default configWithEsm; 4 | -------------------------------------------------------------------------------- /packages/graph/src/graph/chunk-graph/index.ts: -------------------------------------------------------------------------------- 1 | export * from './chunk'; 2 | export * from './graph'; 3 | export * from './asset'; 4 | export * from './entrypoint'; 5 | -------------------------------------------------------------------------------- /packages/graph/src/graph/index.ts: -------------------------------------------------------------------------------- 1 | export * from './chunk-graph'; 2 | export * from './module-graph'; 3 | export * from './package-graph'; 4 | -------------------------------------------------------------------------------- /packages/graph/src/graph/module-graph/index.ts: -------------------------------------------------------------------------------- 1 | export * from './dependency'; 2 | export * from './module'; 3 | export * from './graph'; 4 | export * from './statement'; 5 | export * from './tree-shaking'; 6 | export * from './types'; 7 | -------------------------------------------------------------------------------- /packages/graph/src/graph/module-graph/tree-shaking/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module'; 2 | export * from './export'; 3 | export * from './variable'; 4 | export * from './sideEffect'; 5 | export * from './types'; 6 | -------------------------------------------------------------------------------- /packages/graph/src/graph/module-graph/tree-shaking/types.ts: -------------------------------------------------------------------------------- 1 | import type { SDK } from '@rsdoctor/types'; 2 | 3 | export type ExportData = SDK.ExportData; 4 | export type ModuleGraphModuleData = SDK.ModuleGraphModuleData; 5 | export type SideEffectData = SDK.SideEffectData; 6 | export type VariableData = SDK.VariableData; 7 | -------------------------------------------------------------------------------- /packages/graph/src/graph/module-graph/types.ts: -------------------------------------------------------------------------------- 1 | import type { SDK } from '@rsdoctor/types'; 2 | 3 | export type ModuleBuildMeta = SDK.ModuleBuildMeta; 4 | export type ModuleSize = SDK.ModuleSize; 5 | export type ModuleSource = SDK.ModuleSource; 6 | export type DependencyBuildMeta = SDK.DependencyBuildMeta; 7 | export type SourcePosition = SDK.SourcePosition; 8 | export type SourceRange = SDK.SourceRange; 9 | export type StatementPosition = SDK.StatementPosition; 10 | export type ModuleData = SDK.ModuleData; 11 | export type DependencyData = SDK.DependencyData; 12 | export type StatementData = SDK.StatementData; 13 | export type ModuleGraphData = SDK.ModuleGraphData; 14 | -------------------------------------------------------------------------------- /packages/graph/src/graph/package-graph/index.ts: -------------------------------------------------------------------------------- 1 | export * from './dependency'; 2 | export * from './graph'; 3 | export * from './package'; 4 | export * from './types'; 5 | -------------------------------------------------------------------------------- /packages/graph/src/graph/package-graph/types.ts: -------------------------------------------------------------------------------- 1 | import type { SDK } from '@rsdoctor/types'; 2 | 3 | export type PackageData = SDK.PackageData; 4 | export type PackageJSONData = SDK.PackageJSONData; 5 | export type PackageBasicData = SDK.PackageBasicData; 6 | export type PackageDependencyData = SDK.PackageDependencyData; 7 | export type GetPackageFile = SDK.GetPackageFile; 8 | -------------------------------------------------------------------------------- /packages/graph/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './graph'; 2 | -------------------------------------------------------------------------------- /packages/graph/tests/__snapshots__/utils.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`readPackageJson util > readPackageJson util 1`] = ` 4 | { 5 | "name": "@lodash/es", 6 | "private": true, 7 | "root": "/packages/graph/tests/fixture", 8 | "type": "module", 9 | "version": "0.1.0", 10 | } 11 | `; 12 | -------------------------------------------------------------------------------- /packages/graph/tests/fixture/index/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web-infra-dev/rsdoctor/4b7a0d6a991fa2c1affa09428fb50e2a1f742c5d/packages/graph/tests/fixture/index/index.js -------------------------------------------------------------------------------- /packages/graph/tests/fixture/index/package.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /packages/graph/tests/fixture/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "@lodash/es", 4 | "version": "0.1.0", 5 | "type": "module" 6 | } 7 | -------------------------------------------------------------------------------- /packages/graph/tests/utils.ts: -------------------------------------------------------------------------------- 1 | import { beforeAll, afterAll, afterEach, beforeEach } from 'vitest'; 2 | import { File, Server } from '@rsdoctor/utils/build'; 3 | import { Common, SDK } from '@rsdoctor/types'; 4 | import { request } from 'http'; 5 | import { tmpdir } from 'os'; 6 | import path from 'path'; 7 | -------------------------------------------------------------------------------- /packages/graph/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "noUnusedLocals": false, 6 | "outDir": "./dist", 7 | "baseUrl": "./", 8 | "paths": { 9 | "@/*": ["./src/*"] 10 | }, 11 | "rootDir": "src" 12 | }, 13 | "include": ["src"], 14 | "exclude": ["**/node_modules"], 15 | "references": [ 16 | { 17 | "path": "../types/tsconfig.json" 18 | }, 19 | { 20 | "path": "../utils/tsconfig.json" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/rspack-plugin/README.md: -------------------------------------------------------------------------------- 1 | # @rsdoctor/rspack-plugin 2 | 3 | An Rspack plugin for integrating Rsdoctor. 4 | 5 | ## Documentation 6 | 7 | https://rsdoctor.rs/ 8 | 9 | ## Contributing 10 | 11 | Please read the [Contributing Guide](https://github.com/web-infra-dev/rsdoctor/blob/main/CONTRIBUTING.md). 12 | 13 | ## License 14 | 15 | Rsdoctor is [MIT licensed](https://github.com/web-infra-dev/rsdoctor/blob/main/LICENSE). 16 | -------------------------------------------------------------------------------- /packages/rspack-plugin/modern.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@modern-js/module-tools'; 2 | import { baseBuildConfig } from '../../scripts/modern.base.config'; 3 | import { merge } from 'lodash'; 4 | 5 | const modernConfig = defineConfig({ 6 | ...merge(baseBuildConfig, { 7 | buildConfig: { tsconfig: 'tsconfig.build.json' }, 8 | }), 9 | }); 10 | 11 | export default modernConfig; 12 | -------------------------------------------------------------------------------- /packages/rspack-plugin/src/constants.ts: -------------------------------------------------------------------------------- 1 | import type { Tap } from 'tapable'; 2 | 3 | export const pluginTapName = 'RsdoctorRspackPlugin'; 4 | 5 | export const pluginTapPostOptions: Tap = { 6 | name: pluginTapName, 7 | stage: 999, 8 | }; 9 | 10 | export const pluginTapPreOptions: Tap = { 11 | name: pluginTapName, 12 | stage: -999, 13 | }; 14 | 15 | export const internalPluginTapPreOptions = (namespace: string): Tap => ({ 16 | name: `${pluginTapName}:${namespace}`, 17 | stage: -998, 18 | }); 19 | 20 | export const internalPluginTapPostOptions = (namespace: string): Tap => ({ 21 | name: `${pluginTapName}:${namespace}`, 22 | stage: 1000, 23 | }); 24 | 25 | export const pkg = require('../package.json'); 26 | -------------------------------------------------------------------------------- /packages/rspack-plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './plugin'; 2 | export * from './multiple'; 3 | -------------------------------------------------------------------------------- /packages/rspack-plugin/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src"], 4 | "exclude": ["**/node_modules"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/rspack-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "outDir": "./dist", 6 | "rootDir": "src" 7 | }, 8 | "include": ["src"], 9 | "exclude": ["**/node_modules"], 10 | "references": [ 11 | { 12 | "path": "../core/tsconfig.json" 13 | }, 14 | { 15 | "path": "../graph/tsconfig.json" 16 | }, 17 | { 18 | "path": "../sdk/tsconfig.json" 19 | }, 20 | { 21 | "path": "../types/tsconfig.json" 22 | }, 23 | { 24 | "path": "../utils/tsconfig.json" 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /packages/sdk/README.md: -------------------------------------------------------------------------------- 1 | # @rsdoctor/sdk 2 | 3 | This package is the intermediate data layer of Rsdoctor. 4 | 5 | ## Documentation 6 | 7 | https://rsdoctor.rs/ 8 | 9 | ## Contributing 10 | 11 | Please read the [Contributing Guide](https://github.com/web-infra-dev/rsdoctor/blob/main/CONTRIBUTING.md). 12 | 13 | ## License 14 | 15 | Rsdoctor is [MIT licensed](https://github.com/web-infra-dev/rsdoctor/blob/main/LICENSE). 16 | -------------------------------------------------------------------------------- /packages/sdk/modern.config.ts: -------------------------------------------------------------------------------- 1 | import { configWithEsm } from '../../scripts/modern.base.config'; 2 | 3 | export default configWithEsm; 4 | -------------------------------------------------------------------------------- /packages/sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sdk'; 2 | -------------------------------------------------------------------------------- /packages/sdk/src/sdk/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sdk'; 2 | export * from './multiple'; 3 | -------------------------------------------------------------------------------- /packages/sdk/src/sdk/multiple/index.ts: -------------------------------------------------------------------------------- 1 | export * from './controller'; 2 | export * from './primary'; 3 | -------------------------------------------------------------------------------- /packages/sdk/src/sdk/multiple/server.ts: -------------------------------------------------------------------------------- 1 | import { Server } from '@rsdoctor/utils/build'; 2 | import { RsdoctorServer } from '../server'; 3 | import type { RsdoctorPrimarySDK } from './primary'; 4 | 5 | export class RsdoctorSlaveServer extends RsdoctorServer { 6 | protected sdk: RsdoctorPrimarySDK; 7 | 8 | constructor(sdk: RsdoctorPrimarySDK, port = Server.defaultPort) { 9 | super(sdk, port); 10 | this.sdk = sdk; 11 | } 12 | 13 | async openClientPage(...args: unknown[]) { 14 | if (this.sdk.isMaster) { 15 | return super.openClientPage(...(args as ['homepage'])); 16 | } 17 | 18 | return Promise.resolve(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/sdk/src/sdk/server/apis/fs.ts: -------------------------------------------------------------------------------- 1 | import { SDK } from '@rsdoctor/types'; 2 | 3 | import { BaseAPI } from './base'; 4 | import { Router } from '../router'; 5 | 6 | export class FileSystemAPI extends BaseAPI { 7 | @Router.post(SDK.ServerAPI.API.ApplyErrorFix) 8 | public async applyErrorFix(): Promise< 9 | SDK.ServerAPI.InferResponseType 10 | > { 11 | const { body } = this.ctx.req; 12 | const data = body as { id: number }; 13 | 14 | await this.ctx.sdk.applyErrorFix(data.id); 15 | 16 | return 'success'; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/sdk/src/sdk/server/apis/index.ts: -------------------------------------------------------------------------------- 1 | export * from './alerts'; 2 | export * from './data'; 3 | export * from './fs'; 4 | export * from './loader'; 5 | export * from './graph'; 6 | export * from './plugin'; 7 | export * from './project'; 8 | export * from './renderer'; 9 | export * from './resolver'; 10 | -------------------------------------------------------------------------------- /packages/sdk/src/sdk/server/fakeServer.ts: -------------------------------------------------------------------------------- 1 | import { SDK } from '@rsdoctor/types'; 2 | import { Server } from '@rsdoctor/utils/build'; 3 | import { RsdoctorServer } from '.'; 4 | 5 | export class RsdoctorFakeServer extends RsdoctorServer { 6 | constructor( 7 | protected sdk: SDK.RsdoctorBuilderSDKInstance, 8 | port = Server.defaultPort, 9 | ) { 10 | super(sdk, port); 11 | this.sdk = sdk; 12 | } 13 | 14 | async openClientPage() {} 15 | } 16 | -------------------------------------------------------------------------------- /packages/sdk/src/sdk/utils/constant.ts: -------------------------------------------------------------------------------- 1 | import dayjs from 'dayjs'; 2 | 3 | export const CLOUD_DIR = `rsdoctor/manifests/${dayjs().format( 4 | 'YYYYMMDD', 5 | )}`; 6 | -------------------------------------------------------------------------------- /packages/sdk/src/sdk/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './constant'; 2 | export * from './upload'; 3 | -------------------------------------------------------------------------------- /packages/sdk/src/sdk/utils/upload.ts: -------------------------------------------------------------------------------- 1 | import { DataWithUrl } from '../sdk/types'; 2 | 3 | export const transformDataUrls = ( 4 | d: DataWithUrl[], 5 | ): Record => { 6 | return d.reduce((t: { [key: string]: string[] | string }, item) => { 7 | t[item.name] = Array.isArray(item.files) 8 | ? item.files.map((e) => e.path).concat(t[item.name] || []) 9 | : item.files; 10 | return t; 11 | }, {}); 12 | }; 13 | -------------------------------------------------------------------------------- /packages/sdk/tests/server/apis/data.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect, vi } from 'vitest'; 2 | import { SDK } from '@rsdoctor/types'; 3 | import { setupSDK } from '../../utils'; 4 | 5 | vi.setConfig({ testTimeout: 50000 }); 6 | 7 | describe('test server/apis/data.ts', () => { 8 | const target = setupSDK(); 9 | 10 | it(`test api: ${SDK.ServerAPI.API.ReportLoader}`, async () => { 11 | const spy = vi 12 | .spyOn(target.sdk, 'reportLoader') 13 | .mockImplementation(() => {}); 14 | 15 | await target.post(SDK.ServerAPI.API.ReportLoader, { a: 1 } as any); 16 | 17 | expect(spy).toBeCalledTimes(1); 18 | expect(spy).toHaveBeenCalledWith({ a: 1 }); 19 | 20 | spy.mockRestore(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /packages/sdk/tests/server/apis/fs.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, vi, expect } from 'vitest'; 2 | import { SDK } from '@rsdoctor/types'; 3 | import { setupSDK } from '../../utils'; 4 | 5 | describe('test server/apis/fs.ts', () => { 6 | const target = setupSDK(); 7 | 8 | it(`test api: ${SDK.ServerAPI.API.ApplyErrorFix}`, async () => { 9 | const spy = vi 10 | .spyOn(target.sdk, 'applyErrorFix') 11 | .mockImplementation(async () => {}); 12 | 13 | await target.post(SDK.ServerAPI.API.ApplyErrorFix, { id: 111 } as any); 14 | 15 | expect(spy).toBeCalledTimes(1); 16 | expect(spy).toHaveBeenCalledWith(111); 17 | 18 | spy.mockRestore(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/sdk/tests/server/apis/index.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { SDK } from '@rsdoctor/types'; 3 | import { Router } from '../../../src/sdk/server/router'; 4 | 5 | // make sure the decorators work. 6 | import '../../../src/sdk/server/apis'; 7 | 8 | describe('ensure all of the apis implementation for server', () => { 9 | const apis = Object.values(SDK.ServerAPI.API); 10 | 11 | it(`ensure server`, async () => { 12 | const { get, post } = Router.routes; 13 | 14 | const list = [...get, ...post].map((e) => e[1].map((el) => el[1])).flat(); 15 | 16 | list.forEach((api) => { 17 | expect(apis).toContain(api); 18 | }); 19 | expect(list.length).toBeGreaterThan(30); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/sdk/tests/server/apis/renderer.test.ts: -------------------------------------------------------------------------------- 1 | import { File } from '@rsdoctor/utils/build'; 2 | import { describe, it, expect } from 'vitest'; 3 | import { SDK } from '@rsdoctor/types'; 4 | import { setupSDK } from '../../utils'; 5 | 6 | describe('test server/apis/data.ts', () => { 7 | const target = setupSDK(); 8 | 9 | it(`test api: ${SDK.ServerAPI.API.EntryHtml}`, async () => { 10 | const { text } = await target.get(SDK.ServerAPI.API.EntryHtml); 11 | expect(text).toBeDefined(); 12 | // const clientHtmlPath = require.resolve('@rsdoctor/client'); // TODO: add doctor client. 13 | // const clientHtml = await File.fse.readFile(clientHtmlPath, 'utf-8'); 14 | 15 | // expect(text).toEqual(clientHtml); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "outDir": "./dist", 6 | "baseUrl": "./", 7 | "paths": { 8 | "@/*": ["./src/*"] 9 | }, 10 | "rootDir": "src" 11 | }, 12 | "include": ["src"], 13 | "exclude": ["**/node_modules"], 14 | "references": [ 15 | { 16 | "path": "../types/tsconfig.json" 17 | }, 18 | { 19 | "path": "../utils/tsconfig.json" 20 | }, 21 | { 22 | "path": "../graph/tsconfig.json" 23 | }, 24 | { 25 | "path": "../client/tsconfig.json" 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /packages/types/README.md: -------------------------------------------------------------------------------- 1 | # @rsdoctor/types 2 | 3 | This package is the Rsdoctor's types package. 4 | 5 | ## Documentation 6 | 7 | https://rsdoctor.rs/ 8 | 9 | ## Contributing 10 | 11 | Please read the [Contributing Guide](https://github.com/web-infra-dev/rsdoctor/blob/main/CONTRIBUTING.md). 12 | 13 | ## License 14 | 15 | Rsdoctor is [MIT licensed](https://github.com/web-infra-dev/rsdoctor/blob/main/LICENSE). 16 | -------------------------------------------------------------------------------- /packages/types/src/babel.ts: -------------------------------------------------------------------------------- 1 | /** Babel Error */ 2 | export interface Error { 3 | code: string; 4 | reasonCode: string; 5 | message: string; 6 | name: string; 7 | stack: string; 8 | pos?: number; 9 | loc?: { 10 | line: number; 11 | column: number; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /packages/types/src/index.ts: -------------------------------------------------------------------------------- 1 | export * as Manifest from './manifest'; 2 | export * as Esbuild from './esbuild'; 3 | export * as Babel from './babel'; 4 | export * as Common from './common'; 5 | 6 | export * as Err from './error'; 7 | export * as Logger from './logger'; 8 | export * as SDK from './sdk'; 9 | export * as Modules from './modules'; 10 | export * as Linter from './linter'; 11 | 12 | export * as Rule from './rule'; 13 | export * as Thirdparty from './thirdparty'; 14 | 15 | export * as Client from './client'; 16 | export * as Constants from './constants'; 17 | 18 | export * as Plugin from './plugin'; 19 | -------------------------------------------------------------------------------- /packages/types/src/linter/index.ts: -------------------------------------------------------------------------------- 1 | export * from './diagnostic'; 2 | export * from './rule'; 3 | -------------------------------------------------------------------------------- /packages/types/src/logger.ts: -------------------------------------------------------------------------------- 1 | export enum LogLevel { 2 | Silent, 3 | Error, 4 | Warning, 5 | Info, 6 | Debug, 7 | Verbose, 8 | } 9 | 10 | export type LogLevelName = keyof typeof LogLevel; 11 | -------------------------------------------------------------------------------- /packages/types/src/modules.ts: -------------------------------------------------------------------------------- 1 | import { StatsModule } from './plugin/baseStats'; 2 | 3 | export type ChunkModuleMap = { 4 | isAsset: boolean; 5 | label: string; 6 | modules: StatsModule[]; 7 | }; 8 | 9 | export type Modules = Record; 10 | -------------------------------------------------------------------------------- /packages/types/src/plugin/index.ts: -------------------------------------------------------------------------------- 1 | export * from './baseCompiler'; 2 | export * from './baseStats'; 3 | export * from './plugin'; 4 | export * from './baseLoader'; 5 | export * from './rspack'; 6 | -------------------------------------------------------------------------------- /packages/types/src/rule/code/E1004.ts: -------------------------------------------------------------------------------- 1 | import { RuleMessage } from './type'; 2 | 3 | export const code = 'E1004'; 4 | 5 | export const message: RuleMessage = { 6 | code, 7 | title: 'ECMA Version Check', 8 | type: 'markdown', 9 | category: 'bundle', 10 | description: ` 11 | #### Description 12 | 13 | Detect if there is a newer version of ECMA syntax in the js bundle file 14 | `, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/types/src/rule/index.ts: -------------------------------------------------------------------------------- 1 | export * from './code'; 2 | export * from './data'; 3 | -------------------------------------------------------------------------------- /packages/types/src/sdk/config.ts: -------------------------------------------------------------------------------- 1 | import type { Configuration } from 'webpack'; 2 | import type { Configuration as RspackConfiguration } from '@rspack/core'; 3 | 4 | type RspackConfigurationWrapper = any extends RspackConfiguration 5 | ? never 6 | : RspackConfiguration; 7 | 8 | export interface WebpackConfigData { 9 | name: 'webpack' | 'rspack'; 10 | version: string | number; 11 | bin?: string; 12 | config: Configuration | RspackConfigurationWrapper; 13 | } 14 | 15 | export type ConfigData = WebpackConfigData[]; 16 | -------------------------------------------------------------------------------- /packages/types/src/sdk/envinfo.ts: -------------------------------------------------------------------------------- 1 | export interface EnvInfo { 2 | /** 3 | * @example "macOS 11.4" 4 | */ 5 | os: string; 6 | /** 7 | * @example "(12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz" 8 | */ 9 | cpu: string; 10 | /** 11 | * @example "1.07 GB / 32.00 GB" 12 | */ 13 | memory: string; 14 | nodeVersion: string; 15 | yarnVersion: string; 16 | npmVersion: string; 17 | pnpmVersion: string; 18 | 19 | [key: string]: string; 20 | } 21 | -------------------------------------------------------------------------------- /packages/types/src/sdk/hooks.ts: -------------------------------------------------------------------------------- 1 | import type { AsyncSeriesHook } from 'tapable'; 2 | import { RsdoctorManifestWithShardingFiles } from '../manifest'; 3 | 4 | /** 5 | * sdk hooks map 6 | */ 7 | export interface Hooks { 8 | afterSaveManifest: AsyncSeriesHook< 9 | [ 10 | { 11 | manifestWithShardingFiles: RsdoctorManifestWithShardingFiles; 12 | manifestDiskPath: string; 13 | manifestCloudPath?: string; 14 | }, 15 | ] 16 | >; 17 | } 18 | -------------------------------------------------------------------------------- /packages/types/src/sdk/index.ts: -------------------------------------------------------------------------------- 1 | export * from './loader'; 2 | export * from './resolver'; 3 | export * from './plugin'; 4 | export * from './module'; 5 | export * from './chunk'; 6 | export * from './result'; 7 | export * from './summary'; 8 | export * from './package'; 9 | export * from './context'; 10 | export * from './config'; 11 | export * from './server'; 12 | export * from './statement'; 13 | export * from './treeShaking'; 14 | export * from './envinfo'; 15 | export * from './instance'; 16 | export * from './hooks'; 17 | -------------------------------------------------------------------------------- /packages/types/src/sdk/plugin.ts: -------------------------------------------------------------------------------- 1 | import { DevToolErrorInstance } from '../error'; 2 | 3 | export interface PluginHookData { 4 | /** hook tap name */ 5 | tapName: string; 6 | /** hook call time-consuming */ 7 | costs: number; 8 | startAt: number; 9 | endAt: number; 10 | /** hook function type */ 11 | type: 'sync' | 'async' | 'promise'; 12 | 13 | /** hook function result */ 14 | result: any; 15 | 16 | /** hook function running error */ 17 | error: DevToolErrorInstance[]; 18 | } 19 | 20 | /** 21 | * Plugin data 22 | * - Key name Hook name 23 | * - Key value is the hook data array 24 | */ 25 | export type PluginData = Record; 26 | -------------------------------------------------------------------------------- /packages/types/src/sdk/process.ts: -------------------------------------------------------------------------------- 1 | export interface ProcessData { 2 | /** 3 | * process id 4 | */ 5 | pid: number; 6 | /** 7 | * parent process id 8 | */ 9 | ppid: number | null; 10 | } 11 | -------------------------------------------------------------------------------- /packages/types/src/sdk/server/apis/pagination.ts: -------------------------------------------------------------------------------- 1 | export interface PaginationRequest { 2 | page?: number; 3 | pageSize?: number; 4 | } 5 | 6 | export interface PaginationResponse extends Required { 7 | hasNextPage: boolean; 8 | } 9 | 10 | export interface EnhanceWithPaginationResponse { 11 | data: T; 12 | pagination: PaginationResponse; 13 | } 14 | -------------------------------------------------------------------------------- /packages/types/src/sdk/server/apis/plugin.ts: -------------------------------------------------------------------------------- 1 | import { API } from './index'; 2 | import { PluginHookData } from '../../plugin'; 3 | 4 | export interface PluginAPIResponse { 5 | [API.GetPluginSummary]: { 6 | hooks: string[]; 7 | tapNames: string[]; 8 | }; 9 | 10 | [API.GetPluginData]: { 11 | hook: string; 12 | tapName: string; 13 | data: Pick[]; 14 | }[]; 15 | } 16 | 17 | export interface PluginAPIRequestBody { 18 | [API.GetPluginData]: { 19 | hooks?: string[]; 20 | tapNames?: string[]; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /packages/types/src/sdk/server/apis/project.ts: -------------------------------------------------------------------------------- 1 | import { 2 | RsdoctorManifestClientRoutes, 3 | RsdoctorManifestData, 4 | } from '../../../manifest'; 5 | import { API, APIExtends } from './index'; 6 | 7 | export interface ProjectAPIResponse { 8 | [API.Env]: { 9 | ip: string; 10 | port: number; 11 | }; 12 | [API.GetProjectInfo]: Pick< 13 | RsdoctorManifestData, 14 | 'hash' | 'root' | 'pid' | 'summary' | 'configs' | 'envinfo' | 'errors' 15 | >; 16 | [API.GetClientRoutes]: RsdoctorManifestClientRoutes[]; 17 | [APIExtends.GetCompileProgress]: { 18 | percentage: number; 19 | message: string; 20 | }; 21 | } 22 | 23 | export interface ProjectAPIRequestBody {} 24 | -------------------------------------------------------------------------------- /packages/types/src/sdk/server/apis/resolver.ts: -------------------------------------------------------------------------------- 1 | import { API } from './index'; 2 | import { PathResolverData } from '../../resolver'; 3 | 4 | export interface ResolverAPIResponse { 5 | [API.GetResolverFileTree]: Array>; 6 | [API.GetResolverFileDetails]: { 7 | filepath: string; 8 | before: string; 9 | after: string; 10 | resolvers: (PathResolverData & { costs: number })[]; 11 | }; 12 | } 13 | 14 | export interface ResolverAPIRequestBody { 15 | [API.GetResolverFileDetails]: { filepath: string }; 16 | } 17 | -------------------------------------------------------------------------------- /packages/types/src/sdk/summary.ts: -------------------------------------------------------------------------------- 1 | interface SummaryCostsData { 2 | /** 3 | * such as 'bootstrap' / 'compile' / 'minify' or else. 4 | */ 5 | name: string; 6 | /** 7 | * the start timestamp of the data. 8 | */ 9 | startAt: number; 10 | costs: number; 11 | } 12 | 13 | export interface SummaryData { 14 | /** 15 | * costs of different data. 16 | */ 17 | costs: SummaryCostsData[]; 18 | } 19 | -------------------------------------------------------------------------------- /packages/types/src/thirdparty.ts: -------------------------------------------------------------------------------- 1 | import type connect from 'connect'; 2 | 3 | export type { connect }; 4 | -------------------------------------------------------------------------------- /packages/types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "compilerOptions": { 4 | "module": "Node16", 5 | "moduleResolution": "Node16", 6 | "outDir": "./dist", 7 | "baseUrl": "./", 8 | "rootDir": "src", 9 | "paths": { 10 | "@/*": ["./src/*"] 11 | } 12 | }, 13 | "include": ["src"], 14 | "exclude": ["**/node_modules"] 15 | } 16 | -------------------------------------------------------------------------------- /packages/utils/README.md: -------------------------------------------------------------------------------- 1 | # @rsdoctor/utils 2 | 3 | This package is the Rsdoctor's tools package. 4 | 5 | ## Documentation 6 | 7 | https://rsdoctor.rs/ 8 | 9 | ## Contributing 10 | 11 | Please read the [Contributing Guide](https://github.com/web-infra-dev/rsdoctor/blob/main/CONTRIBUTING.md). 12 | 13 | ## License 14 | 15 | Rsdoctor is [MIT licensed](https://github.com/web-infra-dev/rsdoctor/blob/main/LICENSE). 16 | -------------------------------------------------------------------------------- /packages/utils/modern.config.ts: -------------------------------------------------------------------------------- 1 | import { configWithEsm } from '../../scripts/modern.base.config'; 2 | 3 | export default configWithEsm; 4 | -------------------------------------------------------------------------------- /packages/utils/src/build/file/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sharding'; 2 | 3 | export * as fse from 'fs-extra'; 4 | export * as cache from './cache'; 5 | -------------------------------------------------------------------------------- /packages/utils/src/build/index.ts: -------------------------------------------------------------------------------- 1 | export * as File from './file'; 2 | export * as Json from './json'; 3 | export * as Server from './server'; 4 | export * as EnvInfo from './envinfo'; 5 | export * as Process from './process'; 6 | -------------------------------------------------------------------------------- /packages/utils/src/common/crypto.ts: -------------------------------------------------------------------------------- 1 | const sep = '!'; 2 | 3 | export function encode(str: string) { 4 | let res = `${str.charCodeAt(0)}`; 5 | 6 | for (let i = 1; i < str.length; i++) { 7 | res += `${sep}${str.charCodeAt(i)}`; 8 | } 9 | 10 | return res; 11 | } 12 | 13 | export function decode(str: string) { 14 | let res = ''; 15 | let tmp = ''; 16 | 17 | for (let i = 0; i < str.length; i++) { 18 | if (str[i] === sep) { 19 | res += String.fromCharCode(+tmp); 20 | tmp = ''; 21 | } else { 22 | // 'number' 23 | tmp += str[i]; 24 | } 25 | } 26 | 27 | // end of str 28 | if (tmp) { 29 | res += String.fromCharCode(+tmp); 30 | } 31 | 32 | return res; 33 | } 34 | -------------------------------------------------------------------------------- /packages/utils/src/common/graph/entrypoints.ts: -------------------------------------------------------------------------------- 1 | import { SDK } from '@rsdoctor/types'; 2 | 3 | export function getEntryPoints( 4 | entrypoints: SDK.EntryPointData[], 5 | ): SDK.ServerAPI.InferResponseType { 6 | return entrypoints; 7 | } 8 | -------------------------------------------------------------------------------- /packages/utils/src/common/graph/index.ts: -------------------------------------------------------------------------------- 1 | export * from './assets'; 2 | export * from './chunk'; 3 | export * from './modules'; 4 | export * from './dependency'; 5 | export * from './entrypoints'; 6 | -------------------------------------------------------------------------------- /packages/utils/src/common/index.ts: -------------------------------------------------------------------------------- 1 | export * as Summary from './summary'; 2 | export * as Crypto from './crypto'; 3 | export * as Manifest from './manifest'; 4 | export * as Loader from './loader'; 5 | export * as Time from './time'; 6 | export * as Algorithm from './algorithm'; 7 | export * as Resolver from './resolver'; 8 | export * as Graph from './graph'; 9 | export * as Bundle from './bundle'; 10 | export * as Url from './url'; 11 | export * as Plugin from './plugin'; 12 | export * as Data from './data'; 13 | export * as Alerts from './alerts'; 14 | export * as Rspack from './rspack'; 15 | export * as Package from './package'; 16 | export * as Lodash from './lodash'; 17 | export * as GlobalConfig from './global-config'; 18 | -------------------------------------------------------------------------------- /packages/utils/src/common/rspack.ts: -------------------------------------------------------------------------------- 1 | export const RspackLoaderInternalPropertyName = '__l__'; 2 | 3 | export enum RspackSummaryCostsDataName { 4 | Bootstrap = 'bootstrap->rspack:beforeCompile', 5 | Compile = 'rspack:beforeCompile->afterCompile', 6 | Done = 'rspack:afterCompile->done', 7 | Minify = 'rspack:minify(rspack:optimizeChunkAssets)', 8 | } 9 | -------------------------------------------------------------------------------- /packages/utils/src/common/summary.ts: -------------------------------------------------------------------------------- 1 | export enum SummaryCostsDataName { 2 | Bootstrap = 'bootstrap->beforeCompile', 3 | Compile = 'beforeCompile->afterCompile', 4 | Done = 'afterCompile->done', 5 | Minify = 'minify(processAssets)', 6 | } 7 | -------------------------------------------------------------------------------- /packages/utils/src/common/url.ts: -------------------------------------------------------------------------------- 1 | import { isAbsolute } from 'path'; 2 | 3 | export function isUrl(uri: string) { 4 | return /^https?:\/\//.test(uri); 5 | } 6 | 7 | export function isFilePath(uri: string) { 8 | return isAbsolute(uri); 9 | } 10 | 11 | export function isRemoteUrl(uri: unknown) { 12 | if (typeof uri === 'string') { 13 | if (isUrl(uri) || isFilePath(uri)) { 14 | return true; 15 | } 16 | } 17 | 18 | return false; 19 | } 20 | -------------------------------------------------------------------------------- /packages/utils/src/error/index.ts: -------------------------------------------------------------------------------- 1 | export * from './error'; 2 | 3 | export { printErrors } from './utils'; 4 | -------------------------------------------------------------------------------- /packages/utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export * as RuleUtils from './rule-utils'; 2 | export * as Logger from './logger'; 3 | -------------------------------------------------------------------------------- /packages/utils/src/rule-utils/document/index.ts: -------------------------------------------------------------------------------- 1 | export * from './document'; 2 | export * from './types'; 3 | export * from './server'; 4 | -------------------------------------------------------------------------------- /packages/utils/src/rule-utils/document/server.ts: -------------------------------------------------------------------------------- 1 | import { Document } from './document'; 2 | 3 | const store = new Map(); 4 | 5 | /** Create Document */ 6 | export function getDocument(content: string) { 7 | if (store.has(content)) { 8 | return store.get(content)!; 9 | } 10 | 11 | const doc = new Document(content); 12 | store.set(content, doc); 13 | return doc; 14 | } 15 | 16 | export function clearDocument() { 17 | store.clear(); 18 | } 19 | -------------------------------------------------------------------------------- /packages/utils/src/rule-utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './document'; 2 | export * from './parser'; 3 | -------------------------------------------------------------------------------- /packages/utils/src/rule-utils/parser/index.ts: -------------------------------------------------------------------------------- 1 | export * from './asserts'; 2 | export * from './parser'; 3 | export * from './utils'; 4 | export * from './types'; 5 | -------------------------------------------------------------------------------- /packages/utils/src/typings/index.d.ts: -------------------------------------------------------------------------------- 1 | interface Window { 2 | [key: string]: any; 3 | __RSDOCTOR__: any; 4 | } 5 | -------------------------------------------------------------------------------- /packages/utils/tests/__snapshots__/crypto.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`test src/crypto.ts > encode & decode > encode() 1`] = ` 4 | ""00123sdfdkfkskfk" -> "48!48!49!50!51!115!100!102!100!107!102!107!115!107!102!107" 5 | "~!|.[]{}&……%()()\`·sdkf121" -> "126!33!65372!46!91!93!123!125!38!8230!8230!37!65288!65289!40!41!96!183!115!100!107!102!49!50!49" 6 | "~sd~d8哈哈哈😊" -> "126!115!100!65374!100!56!21704!21704!21704!55357!56842" 7 | "🔚🔜🌹👌" -> "55357!56602!55357!56604!55356!57145!55357!56396"" 8 | `; 9 | -------------------------------------------------------------------------------- /packages/utils/tests/build/time.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect, vi } from 'vitest'; 2 | import { hrtime } from 'process'; 3 | import { Time } from '../../src/common'; 4 | 5 | vi.setConfig({ testTimeout: 100000 }); 6 | 7 | describe('test src/build/time.ts', () => { 8 | it('getCurrentTimestamp', async () => { 9 | const start = Date.now(); 10 | const startH = hrtime(); 11 | const delay = 500; 12 | 13 | const value = await new Promise((r) => { 14 | setTimeout(() => { 15 | r(Time.getCurrentTimestamp(start, startH)); 16 | }, delay); 17 | }); 18 | 19 | expect(value).toBeGreaterThanOrEqual(start + delay); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/utils/tests/server.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { Server } from '../src/build'; 3 | import { getPortSync } from '../src/build/server'; 4 | 5 | describe('test src/server.ts', () => { 6 | it('getPort()', async () => { 7 | expect(await Server.getPort(6273)).toEqual(6273); 8 | 9 | const { close } = await Server.createServer(8292); 10 | expect(await Server.getPort(8292)).not.toEqual(8292); 11 | await close(); 12 | }); 13 | 14 | it('getPortSync()', async () => { 15 | expect(getPortSync(3543)).toEqual(3543); 16 | 17 | const { close } = await Server.createServer(8262); 18 | expect(getPortSync(8262)).not.toEqual(8262); 19 | await close(); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "baseUrl": ".", 6 | "rootDir": "src" 7 | }, 8 | "include": ["src"], 9 | "exclude": ["**/node_modules"], 10 | "references": [ 11 | { 12 | "path": "../types/tsconfig.json" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/webpack-plugin/README.md: -------------------------------------------------------------------------------- 1 | # @rsdoctor/webpack-plugin 2 | 3 | A webpack plugin for integrating Rsdoctor. 4 | 5 | ## Documentation 6 | 7 | https://rsdoctor.rs/ 8 | 9 | ## Contributing 10 | 11 | Please read the [Contributing Guide](https://github.com/web-infra-dev/rsdoctor/blob/main/CONTRIBUTING.md). 12 | 13 | ## License 14 | 15 | Rsdoctor is [MIT licensed](https://github.com/web-infra-dev/rsdoctor/blob/main/LICENSE). 16 | -------------------------------------------------------------------------------- /packages/webpack-plugin/modern.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@modern-js/module-tools'; 2 | import { baseBuildConfig } from '../../scripts/modern.base.config'; 3 | import { merge } from 'lodash'; 4 | 5 | const modernConfig = defineConfig({ 6 | ...merge(baseBuildConfig, { 7 | buildConfig: { tsconfig: 'tsconfig.build.json' }, 8 | }), 9 | }); 10 | 11 | export default modernConfig; 12 | -------------------------------------------------------------------------------- /packages/webpack-plugin/src/constants.ts: -------------------------------------------------------------------------------- 1 | import type { Tap } from 'tapable'; 2 | 3 | export const pluginTapName = 'RsdoctorWebpackPlugin'; 4 | 5 | export const pluginTapPostOptions: Tap = { 6 | name: pluginTapName, 7 | stage: 999, 8 | }; 9 | 10 | export const pluginTapPreOptions: Tap = { 11 | name: pluginTapName, 12 | stage: -999, 13 | }; 14 | 15 | export const internalPluginTapPreOptions = (namespace: string): Tap => ({ 16 | name: `${pluginTapName}:${namespace}`, 17 | stage: -998, 18 | }); 19 | 20 | export const internalPluginTapPostOptions = (namespace: string): Tap => ({ 21 | name: `${pluginTapName}:${namespace}`, 22 | stage: 1000, 23 | }); 24 | -------------------------------------------------------------------------------- /packages/webpack-plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './plugin'; 2 | export * from './multiple'; 3 | 4 | export { defineRule, LinterType } from '@rsdoctor/core/rules'; 5 | -------------------------------------------------------------------------------- /packages/webpack-plugin/tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@/*": ["../src/*"] 7 | } 8 | }, 9 | "include": ["./**/*.ts"], 10 | "exclude": ["../**/node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/webpack-plugin/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src"], 4 | "exclude": ["**/node_modules"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/webpack-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "outDir": "./dist", 6 | "rootDir": "src" 7 | }, 8 | "include": ["src"], 9 | "exclude": ["**/node_modules"], 10 | "references": [ 11 | { 12 | "path": "../core/tsconfig.json" 13 | }, 14 | { 15 | "path": "../graph/tsconfig.json" 16 | }, 17 | { 18 | "path": "../sdk/tsconfig.json" 19 | }, 20 | { 21 | "path": "../types/tsconfig.json" 22 | }, 23 | { 24 | "path": "../utils/tsconfig.json" 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'e2e/**' 3 | - 'scripts/**' 4 | - 'packages/**' 5 | - 'examples/**' 6 | -------------------------------------------------------------------------------- /scripts/requireShims.js: -------------------------------------------------------------------------------- 1 | // If you declare a variable named 'require', esbuild will change it to 'require2' 2 | // Otherwise you use banner to add this code, import.meta.url will be replaced with source file's value by bundle-require 3 | // So we can only add it to global scope, and not pure 4 | import { createRequire } from 'module'; 5 | 6 | global.require = createRequire(import.meta.url); 7 | -------------------------------------------------------------------------------- /scripts/test-helper/modern.config.ts: -------------------------------------------------------------------------------- 1 | import baseConfig from '../../scripts/modern.base.config'; 2 | 3 | export default baseConfig; 4 | -------------------------------------------------------------------------------- /scripts/test-helper/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@rsdoctor/tsconfig/base", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "baseUrl": "./" 6 | }, 7 | "include": ["src"] 8 | } 9 | -------------------------------------------------------------------------------- /scripts/tsconfig/base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2019", 4 | "lib": ["DOM", "ESNext"], 5 | "allowJs": true, 6 | "module": "ES2020", 7 | "strict": true, 8 | "isolatedModules": true, 9 | "declarationMap": true, 10 | "declaration": true, 11 | "esModuleInterop": true, 12 | "skipLibCheck": true, 13 | "noUnusedLocals": true, 14 | "noUnusedParameters": true, 15 | "jsx": "preserve", 16 | "resolveJsonModule": true, 17 | "moduleResolution": "Bundler", 18 | "composite": true 19 | }, 20 | "$schema": "https://json.schemastore.org/tsconfig", 21 | "display": "Base" 22 | } 23 | -------------------------------------------------------------------------------- /scripts/tsconfig/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rsdoctor/tsconfig", 3 | "private": true 4 | } 5 | -------------------------------------------------------------------------------- /scripts/vitest.setup.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import { expect } from 'vitest'; 3 | import { createSnapshotSerializer } from '@scripts/test-helper'; 4 | 5 | expect.addSnapshotSerializer( 6 | createSnapshotSerializer({ 7 | workspace: path.join(__dirname, '..'), 8 | }), 9 | ); 10 | --------------------------------------------------------------------------------