@rsdoctor/client 0.0.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@rsdoctor/client",
3
+ "version": "0.0.2-beta.0",
4
+ "main": "dist/index.html",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/web-infra-dev/rsdoctor",
8
+ "directory": "packages/client"
9
+ },
10
+ "lint-staged": {
11
+ "*.{js,jsx,ts,tsx,mjs,cjs}": [
12
+ "node --max_old_space_size=8192 ./node_modules/eslint/bin/eslint.js --fix --color --cache --quiet"
13
+ ]
14
+ },
15
+ "eslintIgnore": [
16
+ "node_modules/",
17
+ "dist/"
18
+ ],
19
+ "devDependencies": {
20
+ "@rsbuild/core": "0.1.9",
21
+ "@rsbuild/plugin-react": "0.1.9",
22
+ "@rsbuild/plugin-node-polyfill": "0.1.9",
23
+ "@rsbuild/plugin-type-check": "0.1.9",
24
+ "@types/node": "^16",
25
+ "@types/react": "^18",
26
+ "@types/react-dom": "^18",
27
+ "@types/serve-static": "1.15.0",
28
+ "@types/webpack": "5.28.0",
29
+ "antd": "5.8.3",
30
+ "normalize.css": "8.0.1",
31
+ "react": "^18",
32
+ "react-dom": "18.2.0",
33
+ "react-error-boundary": "^4.0.11",
34
+ "react-router-dom": "6.4.3",
35
+ "serve-static": "1.15.0",
36
+ "typescript": "^5.2.2",
37
+ "@rsdoctor/components": "0.0.2-beta.0",
38
+ "@rsdoctor/types": "0.0.2-beta.0"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public",
42
+ "registry": "https://registry.npmjs.org/"
43
+ },
44
+ "scripts": {
45
+ "dev": "rsbuild dev",
46
+ "start": "rsbuild dev",
47
+ "build": "rsbuild build",
48
+ "build:analysis": "ENABLE_DEVTOOLS_PLUGIN=true DEVTOOLS_DEV=true rsbuild build",
49
+ "preview": "rsbuild preview"
50
+ }
51
+ }
@@ -0,0 +1,163 @@
1
+ import type { Compiler } from 'webpack';
2
+ import { defineConfig } from '@rsbuild/core';
3
+ import { pluginReact } from '@rsbuild/plugin-react';
4
+ import { pluginTypeCheck } from '@rsbuild/plugin-type-check';
5
+ import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill';
6
+ import serve from 'serve-static';
7
+ import path from 'path';
8
+ import fs from 'fs';
9
+ import {
10
+ ClientEntry,
11
+ DistPath,
12
+ PortForCLI,
13
+ PortForWeb,
14
+ WebpackDoctorDirPath,
15
+ WebpackStatsFilePath,
16
+ } from './config/constants';
17
+
18
+ const {
19
+ ENABLE_DEVTOOLS_PLUGIN,
20
+ OFFICAL_PREVIEW_PUBLIC_PATH,
21
+ OFFICAL_DEMO_MANIFEST_PATH,
22
+ ENABLE_CLIENT_SERVER,
23
+ } = process.env;
24
+
25
+ export default defineConfig((env) => {
26
+ const IS_PRODUCTION = env.env === 'production';
27
+
28
+ return {
29
+ plugins: [
30
+ pluginReact(),
31
+ pluginNodePolyfill(),
32
+ pluginTypeCheck({ enable: IS_PRODUCTION }),
33
+ ],
34
+
35
+ source: {
36
+ entry: {
37
+ index: ClientEntry,
38
+ },
39
+ define: {
40
+ 'process.env.NODE_DEBUG': JSON.stringify(false),
41
+ 'process.env.NODE_ENV': JSON.stringify(env.env),
42
+ 'process.env.OFFICAL_DEMO_MANIFEST_PATH': JSON.stringify(
43
+ OFFICAL_DEMO_MANIFEST_PATH,
44
+ ),
45
+ 'process.env.LOCAL_CLI_PORT': JSON.stringify(PortForCLI),
46
+ },
47
+ },
48
+
49
+ output: {
50
+ distPath: {
51
+ root: path.basename(DistPath),
52
+ js: 'resource/js',
53
+ css: 'resource/css',
54
+ svg: 'resource/svg',
55
+ font: 'resource/font',
56
+ image: 'resource/image',
57
+ media: 'resource/media',
58
+ },
59
+ assetPrefix: IS_PRODUCTION
60
+ ? OFFICAL_PREVIEW_PUBLIC_PATH?.replace(/\/resource$/, '') || '/'
61
+ : '/',
62
+ cleanDistPath: IS_PRODUCTION,
63
+ disableTsChecker: !IS_PRODUCTION,
64
+ disableSourceMap: true,
65
+ disableMinimize: !IS_PRODUCTION,
66
+ },
67
+
68
+ performance: {
69
+ chunkSplit: {
70
+ strategy: 'custom',
71
+ splitChunks: {
72
+ cacheGroups: {
73
+ monaco: {
74
+ test: /node_modules\/monaco-editor\/*/,
75
+ name: 'monaco',
76
+ chunks: 'all',
77
+ maxSize: 1000000,
78
+ minSize: 500000,
79
+ },
80
+ },
81
+ },
82
+ },
83
+ },
84
+
85
+ tools: {
86
+ bundlerChain: (chainConfig) => {
87
+ if (ENABLE_DEVTOOLS_PLUGIN) {
88
+ const { RsdoctorRspackPlugin } =
89
+ require('../rspack-plugin/dist') as typeof import('../rspack-plugin/dist');
90
+
91
+ class StatsWriter {
92
+ apply(compiler: Compiler) {
93
+ compiler.hooks.done.tapPromise(
94
+ { name: 'webpack-stats-json-writer', stage: 99999 },
95
+ async (stats) => {
96
+ const json = stats.toJson({
97
+ all: false,
98
+ assets: true,
99
+ chunks: true,
100
+ modules: true,
101
+ builtAt: true,
102
+ hash: true,
103
+ ids: true,
104
+ version: true,
105
+ entrypoints: true,
106
+ });
107
+ await fs.promises.writeFile(
108
+ WebpackStatsFilePath,
109
+ JSON.stringify(json, null, 2),
110
+ 'utf-8',
111
+ );
112
+ },
113
+ );
114
+ }
115
+ }
116
+
117
+ chainConfig.plugin('stats-writer').use(StatsWriter);
118
+ chainConfig.plugin('rsdoctor').use(RsdoctorRspackPlugin, [
119
+ {
120
+ disableClientServer: !ENABLE_CLIENT_SERVER,
121
+ features: {
122
+ loader: true,
123
+ plugins: true,
124
+ resolver: true,
125
+ bundle: true,
126
+ treeShaking: true,
127
+ },
128
+ },
129
+ ]);
130
+ }
131
+ },
132
+
133
+ devServer: {
134
+ historyApiFallback: true,
135
+ setupMiddlewares: [
136
+ (middlewares) => {
137
+ if (fs.existsSync(WebpackDoctorDirPath)) {
138
+ const fn = serve(WebpackDoctorDirPath, {
139
+ index: false,
140
+ setHeaders(res) {
141
+ res.setHeader('Content-Type', 'text/plain; charset=utf-8');
142
+ },
143
+ });
144
+ middlewares.push(fn);
145
+ }
146
+ },
147
+ ],
148
+ },
149
+ },
150
+
151
+ html: {
152
+ title: 'Rsdoctor',
153
+ },
154
+
155
+ server: {
156
+ port: PortForWeb,
157
+ },
158
+
159
+ dev: {
160
+ startUrl: ENABLE_CLIENT_SERVER ? undefined : true,
161
+ },
162
+ };
163
+ });
package/src/App.tsx ADDED
@@ -0,0 +1,147 @@
1
+ import { Constants } from '@rsdoctor/components';
2
+ import { Config, ConfigContext, defaultConfig } from '@rsdoctor/components/config';
3
+ import { Layout } from '@rsdoctor/components/elements';
4
+ import { getDemoUrl, getLocale, setThemeToStorage, setViewModeToStorage, useDetectIfCloudIdeEnv } from '@rsdoctor/components/utils';
5
+ import type { Manifest } from '@rsdoctor/types';
6
+ import { Alert, Button, ConfigProvider, Divider, Result, Space, Typography, theme as te } from 'antd';
7
+ import React, { useState } from 'react';
8
+ import { ErrorBoundary } from 'react-error-boundary';
9
+ import { HashRouter as BrowserRouter } from 'react-router-dom';
10
+ import Router from './router';
11
+ // import UploaderComponent from './pages/Resources/Uploader'; TODO: uploader components
12
+
13
+ const { PageState, Theme } = Constants;
14
+
15
+ const App: React.FC = (): React.ReactElement => {
16
+ const ifCloudIdeEnv = useDetectIfCloudIdeEnv();
17
+
18
+ const [state, setState] = useState<Constants.PageState>(PageState.Success);
19
+ const [viewMode, setViewMode] = useState<Config['viewMode']>({ ...defaultConfig.viewMode });
20
+ const [manifest, setManifest] = useState<Manifest.DoctorManifest>();
21
+ const [theme, setTheme] = useState(defaultConfig.theme);
22
+
23
+ if (state === Constants.PageState.Fail) {
24
+ const demoUrl = getDemoUrl();
25
+ return (
26
+ <Space direction="vertical" style={{ padding: 14 }}>
27
+ <Typography.Text strong style={{ fontSize: 16 }}>
28
+ load json file of Rsdoctor failed.
29
+ </Typography.Text>
30
+ <Typography.Text>
31
+ try to use <Typography.Text keyboard>command + r</Typography.Text> to refresh page.
32
+ </Typography.Text>
33
+ {process.env.NODE_ENV === 'development' ? (
34
+ <Typography.Text>
35
+ in development, you need to run <Typography.Text keyboard>emo run build:analysis</Typography.Text> to make
36
+ sure the mock data has been generated.
37
+ </Typography.Text>
38
+ ) : null}
39
+ <Divider />
40
+ <Space direction="vertical" style={{ width: '100%' }}>
41
+ <Typography.Text style={{ fontSize: 16 }}>
42
+ you can
43
+ <Typography.Text strong style={{ fontSize: 'inherit' }}>
44
+ {' '}
45
+ upload a file{' '}
46
+ </Typography.Text>
47
+ in the area below to analyze your project.
48
+ </Typography.Text>
49
+ {/* <UploaderComponent /> */}
50
+ </Space>
51
+ <Divider />
52
+ {demoUrl ? (
53
+ <Typography.Text style={{ fontSize: 16 }}>
54
+ or you can open the{' '}
55
+ <Typography.Text strong style={{ fontSize: 'inherit' }}>
56
+ <a href={demoUrl} target="_blank" rel="noreferrer">
57
+ demo
58
+ </a>
59
+ </Typography.Text>{' '}
60
+ to get started with the Rsdoctor.
61
+ </Typography.Text>
62
+ ) : null}
63
+ </Space>
64
+ );
65
+ }
66
+
67
+ return (
68
+ <BrowserRouter>
69
+ <ConfigContext.Provider
70
+ value={{
71
+ ...defaultConfig,
72
+ theme,
73
+ setTheme: (v) => {
74
+ setTheme(v);
75
+ setThemeToStorage(v);
76
+ },
77
+ pageState: state,
78
+ json: manifest!,
79
+ viewMode,
80
+ setManifest,
81
+ setPageState: setState,
82
+ setViewMode(m, saveStorage = true) {
83
+ const res = { ...viewMode, ...m };
84
+ setViewMode(res);
85
+ saveStorage && setViewModeToStorage(res);
86
+ },
87
+ }}
88
+ >
89
+ <ConfigContext.Consumer>
90
+ {(v) => {
91
+ return (
92
+ <ConfigProvider
93
+ locale={getLocale(v.locale)}
94
+ theme={{
95
+ algorithm: theme === Theme.Dark ? te.darkAlgorithm : te.defaultAlgorithm,
96
+ }}
97
+ >
98
+ <Layout>
99
+ <>
100
+ {ifCloudIdeEnv && (
101
+ <Alert
102
+ message="Warning"
103
+ description={
104
+ <a
105
+ href={window.location.href.replace(/https/, 'http')}
106
+ >{`Please jump to:${window.location.href.replace(/https/, 'http')}`}</a>
107
+ }
108
+ type="warning"
109
+ showIcon
110
+ closable
111
+ />
112
+ )}
113
+ <ErrorBoundary
114
+ FallbackComponent={({ error, resetErrorBoundary }) => (
115
+ <Result
116
+ status="error"
117
+ title="Sorry, something went wrong."
118
+ extra={
119
+ <Button type="primary" onClick={resetErrorBoundary} loading={state === PageState.Pending}>
120
+ Reload
121
+ </Button>
122
+ }
123
+ >
124
+ <Typography.Paragraph>
125
+ <Typography.Title level={3}>Error Stack</Typography.Title>
126
+ <pre>{error.stack || error.message}</pre>
127
+ </Typography.Paragraph>
128
+ </Result>
129
+ )}
130
+ onReset={() => {
131
+ window.location.reload();
132
+ }}
133
+ >
134
+ <Router />
135
+ </ErrorBoundary>
136
+ </>
137
+ </Layout>
138
+ </ConfigProvider>
139
+ );
140
+ }}
141
+ </ConfigContext.Consumer>
142
+ </ConfigContext.Provider>
143
+ </BrowserRouter>
144
+ );
145
+ };
146
+
147
+ export default App;
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 24L43 24" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M28 4H20C18.8954 4 18 4.89543 18 6V14C18 15.1046 18.8954 16 20 16H28C29.1046 16 30 15.1046 30 14V6C30 4.89543 29.1046 4 28 4Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M16 32H8C6.89543 32 6 32.8954 6 34V42C6 43.1046 6.89543 44 8 44H16C17.1046 44 18 43.1046 18 42V34C18 32.8954 17.1046 32 16 32Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M40 32H32C30.8954 32 30 32.8954 30 34V42C30 43.1046 30.8954 44 32 44H40C41.1046 44 42 43.1046 42 42V34C42 32.8954 41.1046 32 40 32Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M24 24V16" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M36 32V24" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 32V24" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>
@@ -0,0 +1,21 @@
1
+ <svg width="106.000000" height="113.000000" viewBox="0 0 106 113" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
2
+ <rect id="画板 934" width="106.000000" height="113.000000" fill="#FFFFFF" fill-opacity="0.035"/>
3
+ <g clip-path="url(#clip111_45)">
4
+ <rect id="矩形 2176" x="22.500000" y="10.500000" rx="3.000000" width="6.000000" height="11.000000" fill="#0F0D0D"/>
5
+ <rect id="矩形 2176" x="22.500000" y="10.500000" rx="3.000000" width="6.000000" height="11.000000" fill="#736C6C"/>
6
+ <rect id="矩形 2176" x="22.500000" y="10.500000" rx="3.000000" width="6.000000" height="11.000000" stroke="#000000" stroke-linejoin="bevel"/>
7
+ <rect id="矩形 2176" x="49.500000" y="10.500000" rx="3.000000" width="6.000000" height="11.000000" fill="#0F0D0D"/>
8
+ <rect id="矩形 2176" x="49.500000" y="10.500000" rx="3.000000" width="6.000000" height="11.000000" fill="#736C6C"/>
9
+ <rect id="矩形 2176" x="49.500000" y="10.500000" rx="3.000000" width="6.000000" height="11.000000" stroke="#000000" stroke-linejoin="bevel"/>
10
+ <path id="矢量 943" d="M24.0938 15.8218C24.0938 15.8218 14 11.3477 14 23.2773C14 35.207 26.1123 70 26.1123 70L41 70" stroke="#000000" stroke-width="5.000000"/>
11
+ <path id="矢量 943" d="M53.9062 15.8218C53.9062 15.8218 64 11.3477 64 23.2773C64 35.207 51.8877 70 51.8877 70L37 70" stroke="#000000" stroke-width="5.000000"/>
12
+ <path id="矢量 945" d="M40 83.0723C40 94.0781 48.9219 103 59.9277 103L70 103C81.0459 103 90 94.0459 90 83L90 48" stroke="#000000" stroke-width="5.000000"/>
13
+ <ellipse id="椭圆 54" cx="90.000000" cy="41.500000" rx="11.000000" ry="8.500000" fill="#5092FF"/>
14
+ <path id="矢量 946" d="M27 72C31.9609 80.7266 34.5361 81.2817 39.4443 80.9219C44.7744 81.2124 47.4326 79.7798 51 72" stroke="#000000" stroke-width="5.000000"/>
15
+ </g>
16
+ <defs>
17
+ <clipPath id="clip111_45">
18
+ <rect id="画板 934" width="106.000000" height="113.000000" fill="white"/>
19
+ </clipPath>
20
+ </defs>
21
+ </svg>
@@ -0,0 +1 @@
1
+ <svg viewBox="0 0 1200 1200" xmlns="http://www.w3.org/2000/svg"><path d="m600 0 530.3 300v600l-530.3 300-530.3-300v-600z" fill="#fff"/><path d="m1035.6 879.3-418.1 236.5v-184.2l260.5-143.3zm28.6-25.9v-494.6l-153 88.3v317.9zm-901.5 25.9 418.1 236.5v-184.2l-260.5-143.3zm-28.6-25.9v-494.6l153 88.3v317.9zm17.9-526.6 428.8-242.6v178.1l-274.7 151.1-2.1 1.2zm894.3 0-428.8-242.6v178.1l274.7 151.1 2.1 1.2z" fill="#8ed6fb"/><path d="m580.8 889.7-257-141.3v-280l257 148.4zm36.7 0 257-141.3v-280l-257 148.4zm-276.3-453.7 258-141.9 258 141.9-258 149z" fill="#1c78c0"/></svg>
@@ -0,0 +1,6 @@
1
+ @import "normalize.css";
2
+ @import "./theme.scss";
3
+
4
+ .body {
5
+ font-size: 12px;
6
+ }
@@ -0,0 +1,3 @@
1
+ // body {
2
+ // background-color: rgb(247, 245, 245);
3
+ // }
package/src/index.tsx ADDED
@@ -0,0 +1,16 @@
1
+ import '@rsdoctor/components/i18n';
2
+ import App from './App';
3
+ import ReactDOM from 'react-dom/client';
4
+ import './common/styles/base.scss';
5
+ import icon from './common/imgs/icon.svg';
6
+
7
+ const rootElement = document.getElementById('root');
8
+ const root = ReactDOM.createRoot(rootElement!);
9
+
10
+ root.render(<App />);
11
+
12
+ const link = document.createElement('link');
13
+ link.setAttribute('type', 'image/x-icon');
14
+ link.setAttribute('rel', 'icon');
15
+ link.setAttribute('href', icon);
16
+ document.head.appendChild(link);
package/src/main.tsx ADDED
@@ -0,0 +1,147 @@
1
+ import { Constants } from '@rsdoctor/components';
2
+ import { Config, ConfigContext, defaultConfig } from '@rsdoctor/components/config';
3
+ import { Layout } from '@rsdoctor/components/elements';
4
+ import { getDemoUrl, getLocale, setThemeToStorage, setViewModeToStorage, useDetectIfCloudIdeEnv } from '@rsdoctor/components/utils';
5
+ import type { Manifest } from '@rsdoctor/types';
6
+ import { Alert, Button, ConfigProvider, Divider, Result, Space, Typography, theme as te } from 'antd';
7
+ import React, { useState } from 'react';
8
+ import { ErrorBoundary } from 'react-error-boundary';
9
+ import { HashRouter as BrowserRouter } from 'react-router-dom';
10
+ import Router from './router';
11
+ // import UploaderComponent from './pages/Resources/Uploader'; TODO: uploader components
12
+
13
+ const { PageState, Theme } = Constants;
14
+
15
+ const Index: React.FC = (): React.ReactElement => {
16
+ const ifCloudIdeEnv = useDetectIfCloudIdeEnv();
17
+
18
+ const [state, setState] = useState<Constants.PageState>(PageState.Success);
19
+ const [viewMode, setViewMode] = useState<Config['viewMode']>({ ...defaultConfig.viewMode });
20
+ const [manifest, setManifest] = useState<Manifest.DoctorManifest>();
21
+ const [theme, setTheme] = useState(defaultConfig.theme);
22
+
23
+ if (state === Constants.PageState.Fail) {
24
+ const demoUrl = getDemoUrl();
25
+ return (
26
+ <Space direction="vertical" style={{ padding: 14 }}>
27
+ <Typography.Text strong style={{ fontSize: 16 }}>
28
+ load json file of Rsdoctor failed.
29
+ </Typography.Text>
30
+ <Typography.Text>
31
+ try to use <Typography.Text keyboard>command + r</Typography.Text> to refresh page.
32
+ </Typography.Text>
33
+ {process.env.NODE_ENV === 'development' ? (
34
+ <Typography.Text>
35
+ in development, you need to run <Typography.Text keyboard>emo run build:analysis</Typography.Text> to make
36
+ sure the mock data has been generated.
37
+ </Typography.Text>
38
+ ) : null}
39
+ <Divider />
40
+ <Space direction="vertical" style={{ width: '100%' }}>
41
+ <Typography.Text style={{ fontSize: 16 }}>
42
+ you can
43
+ <Typography.Text strong style={{ fontSize: 'inherit' }}>
44
+ {' '}
45
+ upload a file{' '}
46
+ </Typography.Text>
47
+ in the area below to analyze your project.
48
+ </Typography.Text>
49
+ {/* <UploaderComponent /> */}
50
+ </Space>
51
+ <Divider />
52
+ {demoUrl ? (
53
+ <Typography.Text style={{ fontSize: 16 }}>
54
+ or you can open the{' '}
55
+ <Typography.Text strong style={{ fontSize: 'inherit' }}>
56
+ <a href={demoUrl} target="_blank" rel="noreferrer">
57
+ demo
58
+ </a>
59
+ </Typography.Text>{' '}
60
+ to get started with the Rsdoctor.
61
+ </Typography.Text>
62
+ ) : null}
63
+ </Space>
64
+ );
65
+ }
66
+
67
+ return (
68
+ <BrowserRouter>
69
+ <ConfigContext.Provider
70
+ value={{
71
+ ...defaultConfig,
72
+ theme,
73
+ setTheme: (v) => {
74
+ setTheme(v);
75
+ setThemeToStorage(v);
76
+ },
77
+ pageState: state,
78
+ json: manifest!,
79
+ viewMode,
80
+ setManifest,
81
+ setPageState: setState,
82
+ setViewMode(m, saveStorage = true) {
83
+ const res = { ...viewMode, ...m };
84
+ setViewMode(res);
85
+ saveStorage && setViewModeToStorage(res);
86
+ },
87
+ }}
88
+ >
89
+ <ConfigContext.Consumer>
90
+ {(v) => {
91
+ return (
92
+ <ConfigProvider
93
+ locale={getLocale(v.locale)}
94
+ theme={{
95
+ algorithm: theme === Theme.Dark ? te.darkAlgorithm : te.defaultAlgorithm,
96
+ }}
97
+ >
98
+ <Layout>
99
+ <>
100
+ {ifCloudIdeEnv && (
101
+ <Alert
102
+ message="Warning"
103
+ description={
104
+ <a
105
+ href={window.location.href.replace(/https/, 'http')}
106
+ >{`Please jump to:${window.location.href.replace(/https/, 'http')}`}</a>
107
+ }
108
+ type="warning"
109
+ showIcon
110
+ closable
111
+ />
112
+ )}
113
+ <ErrorBoundary
114
+ FallbackComponent={({ error, resetErrorBoundary }) => (
115
+ <Result
116
+ status="error"
117
+ title="Sorry, something went wrong."
118
+ extra={
119
+ <Button type="primary" onClick={resetErrorBoundary} loading={state === PageState.Pending}>
120
+ Reload
121
+ </Button>
122
+ }
123
+ >
124
+ <Typography.Paragraph>
125
+ <Typography.Title level={3}>Error Stack</Typography.Title>
126
+ <pre>{error.stack || error.message}</pre>
127
+ </Typography.Paragraph>
128
+ </Result>
129
+ )}
130
+ onReset={() => {
131
+ window.location.reload();
132
+ }}
133
+ >
134
+ <Router />
135
+ </ErrorBoundary>
136
+ </>
137
+ </Layout>
138
+ </ConfigProvider>
139
+ );
140
+ }}
141
+ </ConfigContext.Consumer>
142
+ </ConfigContext.Provider>
143
+ </BrowserRouter>
144
+ );
145
+ };
146
+
147
+ export default Index;
package/src/router.tsx ADDED
@@ -0,0 +1,43 @@
1
+ import React from 'react';
2
+ import { Route, Routes } from 'react-router-dom';
3
+ import { Overall, BundleSize, LoaderFiles, PluginsAnalyze, ModuleResolve, LoaderTimeline } from '@rsdoctor/components/pages';
4
+
5
+
6
+ export default function Router(): React.ReactElement {
7
+ const routes = [
8
+ {
9
+ path: BundleSize.route,
10
+ element: <BundleSize.Page />,
11
+ },
12
+ {
13
+ path: LoaderFiles.route,
14
+ element: <LoaderFiles.Page />,
15
+ },
16
+ {
17
+ path: LoaderFiles.route,
18
+ element: <LoaderFiles.Page />,
19
+ },
20
+ {
21
+ path: PluginsAnalyze.route,
22
+ element: <PluginsAnalyze.Page />,
23
+ },
24
+ {
25
+ path: ModuleResolve.route,
26
+ element: <ModuleResolve.Page />,
27
+ },
28
+ {
29
+ path: LoaderTimeline.route,
30
+ element: <LoaderTimeline.Page />,
31
+ },
32
+ ].filter((e) => Boolean(e)) as { path: string; element: JSX.Element }[];
33
+
34
+ return (
35
+ <Routes>
36
+ <Route path="/" element={<Overall.Page />} />
37
+ <Route path={Overall.route} element={<Overall.Page />} />
38
+ {routes.map((e) => (
39
+ <Route key={e.path} path={e.path} element={e.element} />
40
+ ))}
41
+ </Routes>
42
+ );
43
+ }
@@ -0,0 +1,16 @@
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
+
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
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
+ },
11
+ "include": ["src", "config"],
12
+ "exclude": ["**/node_modules"]
13
+ }