@shuvi/platform-web 1.0.28 → 1.0.30
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/esm/shared/appTypes.d.ts +2 -0
- package/esm/shared/renderTypes.d.ts +2 -0
- package/esm/shuvi-app/app/client.js +13 -0
- package/esm/shuvi-app/app/server.js +13 -1
- package/esm/shuvi-app/dev/hotDevClient.js +5 -1
- package/esm/shuvi-app/entry/client/app.js +11 -3
- package/esm/shuvi-app/entry/client/setup-env.js +7 -0
- package/esm/shuvi-app/entry/client/trace.d.ts +2 -0
- package/esm/shuvi-app/entry/client/trace.js +4 -0
- package/esm/shuvi-app/react/AppContainer.jsx +39 -0
- package/esm/shuvi-app/react/view/ReactView.client.jsx +12 -6
- package/esm/shuvi-app/react/view/ReactView.server.jsx +7 -1
- package/lib/node/external-internal-libs.d.ts +4 -0
- package/lib/node/external-internal-libs.js +23 -0
- package/lib/node/features/html-render/lib/getPageMiddleware.js +24 -2
- package/lib/node/features/html-render/lib/renderToHTML.js +11 -4
- package/lib/node/features/html-render/lib/renderer/ssr.js +3 -1
- package/lib/node/index.js +7 -0
- package/lib/node/paths.d.ts +1 -0
- package/lib/node/paths.js +6 -1
- package/lib/node/targets/react/bundler/index.js +9 -12
- package/lib/node/trace.d.ts +4 -0
- package/lib/node/trace.js +28 -0
- package/lib/shared/appTypes.d.ts +2 -0
- package/lib/shared/renderTypes.d.ts +2 -0
- package/package.json +11 -11
package/esm/shared/appTypes.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { IPageRouteRecord, IAppData, IAppState, Application as _Application } from '@shuvi/platform-shared/shared';
|
|
2
2
|
import { ApplicationImpl as _ApplicationImpl } from '@shuvi/platform-shared/shuvi-app/application';
|
|
3
3
|
import type { ShuviRequest } from '@shuvi/service';
|
|
4
|
+
import { Span } from '@shuvi/service/lib/trace';
|
|
4
5
|
export interface AppConfig {
|
|
5
6
|
ssr: boolean;
|
|
6
7
|
}
|
|
@@ -10,6 +11,7 @@ export interface CreateAppServer {
|
|
|
10
11
|
(options: {
|
|
11
12
|
req: ShuviRequest;
|
|
12
13
|
ssr: boolean;
|
|
14
|
+
serverCreateAppTrace: Span;
|
|
13
15
|
}): InternalApplication;
|
|
14
16
|
}
|
|
15
17
|
export interface CreateAppClient {
|
|
@@ -2,6 +2,7 @@ import type { ShuviRequest } from '@shuvi/service';
|
|
|
2
2
|
import { Response, IAppData } from '@shuvi/platform-shared/shared';
|
|
3
3
|
import { IManifest } from '../shared';
|
|
4
4
|
import { Application } from './appTypes';
|
|
5
|
+
import { Span } from '@shuvi/service/lib/trace';
|
|
5
6
|
export declare type IRenderViewOptions = {
|
|
6
7
|
app: Application;
|
|
7
8
|
};
|
|
@@ -38,6 +39,7 @@ export interface IClientRendererOptions<ExtraAppData = {}> extends IRenderOption
|
|
|
38
39
|
export interface IServerRendererOptions extends IRenderOptions {
|
|
39
40
|
req: ShuviRequest;
|
|
40
41
|
manifest: IManifest;
|
|
42
|
+
serverRequestTrace: Span;
|
|
41
43
|
}
|
|
42
44
|
export interface IViewClient<ExtraAppData = {}> extends IView<IClientRendererOptions<ExtraAppData>> {
|
|
43
45
|
}
|
|
@@ -13,8 +13,11 @@ import application from '@shuvi/platform-shared/shuvi-app/application';
|
|
|
13
13
|
import { createRouter, createBrowserHistory, createHashHistory } from '@shuvi/router';
|
|
14
14
|
import { historyMode } from '@shuvi/app/files/routerConfig';
|
|
15
15
|
import { SHUVI_ERROR } from '@shuvi/shared/constants';
|
|
16
|
+
import { CLIENT_RENDER } from '@shuvi/shared/constants/trace';
|
|
16
17
|
import isThirdSite from '../helper/isThirdSite';
|
|
18
|
+
import { clientRenderTrace } from '../entry/client/trace';
|
|
17
19
|
let app;
|
|
20
|
+
const { SHUVI_CLIENT_RUN_LOADERS } = CLIENT_RENDER.events;
|
|
18
21
|
export const createApp = ({ routes, appData, appComponent }) => {
|
|
19
22
|
// app is a singleton in client side
|
|
20
23
|
if (app) {
|
|
@@ -57,6 +60,7 @@ export const createApp = ({ routes, appData, appComponent }) => {
|
|
|
57
60
|
next();
|
|
58
61
|
return;
|
|
59
62
|
}
|
|
63
|
+
const runLoadersTrace = clientRenderTrace.traceChild(SHUVI_CLIENT_RUN_LOADERS.name);
|
|
60
64
|
const pageLoaders = yield app.getLoaders();
|
|
61
65
|
const matches = getRouteMatchesWithInvalidLoader(to, from, pageLoaders);
|
|
62
66
|
try {
|
|
@@ -97,8 +101,11 @@ export const createApp = ({ routes, appData, appComponent }) => {
|
|
|
97
101
|
});
|
|
98
102
|
});
|
|
99
103
|
app.setLoadersData(loaderDatas);
|
|
104
|
+
runLoadersTrace.setAttribute(SHUVI_CLIENT_RUN_LOADERS.attrs.error.name, false);
|
|
105
|
+
runLoadersTrace.stop();
|
|
100
106
|
}
|
|
101
107
|
catch (error) {
|
|
108
|
+
runLoadersTrace.setAttribute(SHUVI_CLIENT_RUN_LOADERS.attrs.error.name, true);
|
|
102
109
|
if (isRedirect(error)) {
|
|
103
110
|
const location = error.headers.get('Location');
|
|
104
111
|
if (isThirdSite(location)) {
|
|
@@ -110,6 +117,8 @@ export const createApp = ({ routes, appData, appComponent }) => {
|
|
|
110
117
|
replace: true
|
|
111
118
|
});
|
|
112
119
|
}
|
|
120
|
+
runLoadersTrace.setAttribute(SHUVI_CLIENT_RUN_LOADERS.attrs.errorType.name, 'redirect');
|
|
121
|
+
runLoadersTrace.stop();
|
|
113
122
|
return;
|
|
114
123
|
}
|
|
115
124
|
if (isResponse(error) && error.status >= 400 && error.status < 600) {
|
|
@@ -118,6 +127,8 @@ export const createApp = ({ routes, appData, appComponent }) => {
|
|
|
118
127
|
message: error.data
|
|
119
128
|
});
|
|
120
129
|
next();
|
|
130
|
+
runLoadersTrace.setAttribute(SHUVI_CLIENT_RUN_LOADERS.attrs.errorType.name, 'userError');
|
|
131
|
+
runLoadersTrace.stop();
|
|
121
132
|
return;
|
|
122
133
|
}
|
|
123
134
|
// If loader throws a error, we need to rethrow it
|
|
@@ -129,6 +140,8 @@ export const createApp = ({ routes, appData, appComponent }) => {
|
|
|
129
140
|
next(() => {
|
|
130
141
|
throw error;
|
|
131
142
|
});
|
|
143
|
+
runLoadersTrace.setAttribute(SHUVI_CLIENT_RUN_LOADERS.attrs.errorType.name, 'unexpectedError');
|
|
144
|
+
runLoadersTrace.stop();
|
|
132
145
|
return;
|
|
133
146
|
}
|
|
134
147
|
next(() => {
|
|
@@ -12,10 +12,12 @@ import { getRoutes, app as AppComponent } from '@shuvi/app/core/platform';
|
|
|
12
12
|
import { runLoaders, getRouteMatchesWithInvalidLoader, isResponse, isRedirect } from '@shuvi/platform-shared/shared';
|
|
13
13
|
import application from '@shuvi/platform-shared/shuvi-app/application';
|
|
14
14
|
import { createRouter, createMemoryHistory, pathToString } from '@shuvi/router';
|
|
15
|
+
import { SERVER_CREATE_APP } from '@shuvi/shared/constants/trace';
|
|
15
16
|
import logger from '@shuvi/utils/logger';
|
|
16
17
|
import { serializeServerError } from '../helper/serializeServerError';
|
|
18
|
+
const { SHUVI_SERVER_RUN_LOADERS } = SERVER_CREATE_APP.events;
|
|
17
19
|
export const createApp = options => {
|
|
18
|
-
const { req, ssr } = options;
|
|
20
|
+
const { req, ssr, serverCreateAppTrace } = options;
|
|
19
21
|
const history = createMemoryHistory({
|
|
20
22
|
initialEntries: [(req && req.url) || '/'],
|
|
21
23
|
initialIndex: 0
|
|
@@ -27,6 +29,7 @@ export const createApp = options => {
|
|
|
27
29
|
let app;
|
|
28
30
|
if (ssr) {
|
|
29
31
|
router.beforeResolve((to, from, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
32
|
+
const runLoadersTrace = serverCreateAppTrace.traceChild(SHUVI_SERVER_RUN_LOADERS.name);
|
|
30
33
|
const pageLoaders = yield app.getLoaders();
|
|
31
34
|
const matches = getRouteMatchesWithInvalidLoader(to, from, pageLoaders);
|
|
32
35
|
try {
|
|
@@ -38,8 +41,11 @@ export const createApp = options => {
|
|
|
38
41
|
getAppContext: () => app.context
|
|
39
42
|
});
|
|
40
43
|
app.setLoadersData(loaderResult);
|
|
44
|
+
runLoadersTrace.setAttribute(SHUVI_SERVER_RUN_LOADERS.attrs.error.name, false);
|
|
45
|
+
runLoadersTrace.stop();
|
|
41
46
|
}
|
|
42
47
|
catch (error) {
|
|
48
|
+
runLoadersTrace.setAttribute(SHUVI_SERVER_RUN_LOADERS.attrs.error.name, true);
|
|
43
49
|
if (isRedirect(error)) {
|
|
44
50
|
const location = error.headers.get('Location');
|
|
45
51
|
const status = error.status;
|
|
@@ -52,6 +58,8 @@ export const createApp = options => {
|
|
|
52
58
|
status
|
|
53
59
|
}
|
|
54
60
|
});
|
|
61
|
+
runLoadersTrace.setAttribute(SHUVI_SERVER_RUN_LOADERS.attrs.errorType.name, 'redirect');
|
|
62
|
+
runLoadersTrace.stop();
|
|
55
63
|
return;
|
|
56
64
|
}
|
|
57
65
|
if (isResponse(error) && error.status >= 400 && error.status < 600) {
|
|
@@ -60,6 +68,8 @@ export const createApp = options => {
|
|
|
60
68
|
message: error.data
|
|
61
69
|
});
|
|
62
70
|
next();
|
|
71
|
+
runLoadersTrace.setAttribute(SHUVI_SERVER_RUN_LOADERS.attrs.errorType.name, 'userError');
|
|
72
|
+
runLoadersTrace.stop();
|
|
63
73
|
return;
|
|
64
74
|
}
|
|
65
75
|
if (process.env.NODE_ENV === 'development') {
|
|
@@ -67,6 +77,8 @@ export const createApp = options => {
|
|
|
67
77
|
}
|
|
68
78
|
app.setError(serializeServerError(error));
|
|
69
79
|
next();
|
|
80
|
+
runLoadersTrace.setAttribute(SHUVI_SERVER_RUN_LOADERS.attrs.errorType.name, 'unexpectedError');
|
|
81
|
+
runLoadersTrace.stop();
|
|
70
82
|
return;
|
|
71
83
|
}
|
|
72
84
|
next();
|
|
@@ -280,7 +280,6 @@ function tryApplyUpdates(onHotUpdateSuccess) {
|
|
|
280
280
|
return;
|
|
281
281
|
}
|
|
282
282
|
function handleApplyUpdates(err, updatedModules) {
|
|
283
|
-
const hasUpdates = Boolean(updatedModules === null || updatedModules === void 0 ? void 0 : updatedModules.length);
|
|
284
283
|
if (hadRuntimeError) {
|
|
285
284
|
hadRuntimeError = false;
|
|
286
285
|
window.location.reload();
|
|
@@ -289,6 +288,11 @@ function tryApplyUpdates(onHotUpdateSuccess) {
|
|
|
289
288
|
if (err) {
|
|
290
289
|
hadRuntimeError = true;
|
|
291
290
|
}
|
|
291
|
+
const hasUpdates = Boolean(updatedModules === null || updatedModules === void 0 ? void 0 : updatedModules.length);
|
|
292
|
+
if (!hasUpdates) {
|
|
293
|
+
window.location.reload();
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
292
296
|
if (typeof onHotUpdateSuccess === 'function') {
|
|
293
297
|
// Maybe we want to do something.
|
|
294
298
|
onHotUpdateSuccess(hasUpdates);
|
|
@@ -13,13 +13,17 @@ import { CLIENT_CONTAINER_ID } from '@shuvi/shared/constants';
|
|
|
13
13
|
import { view, getRoutes, app as PlatformAppComponent } from '@shuvi/app/core/platform';
|
|
14
14
|
import routes from '@shuvi/app/files/routes';
|
|
15
15
|
import { getAppData } from '@shuvi/platform-shared/shared/helper/getAppData';
|
|
16
|
+
import { CLIENT_ENTRY } from '@shuvi/shared/constants/trace';
|
|
16
17
|
import { createApp } from '../../app/client';
|
|
18
|
+
import { clientEntryTrace } from './trace';
|
|
17
19
|
const appData = getAppData();
|
|
18
|
-
const app =
|
|
20
|
+
const app = clientEntryTrace
|
|
21
|
+
.traceChild(CLIENT_ENTRY.events.SHUVI_CLIENT_CREATE_APP.name)
|
|
22
|
+
.traceFn(() => createApp({
|
|
19
23
|
appComponent: PlatformAppComponent,
|
|
20
24
|
routes,
|
|
21
25
|
appData
|
|
22
|
-
});
|
|
26
|
+
}));
|
|
23
27
|
const render = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
28
|
const appContainer = document.getElementById(CLIENT_CONTAINER_ID);
|
|
25
29
|
yield view.renderApp({
|
|
@@ -29,8 +33,12 @@ const render = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
29
33
|
});
|
|
30
34
|
});
|
|
31
35
|
const run = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
32
|
-
|
|
36
|
+
const runAppTrace = clientEntryTrace.traceChild(CLIENT_ENTRY.events.SHUVI_CLIENT_RUN_APP.name);
|
|
37
|
+
yield clientEntryTrace
|
|
38
|
+
.traceChild(CLIENT_ENTRY.events.SHUVI_CLIENT_APP_INIT.name)
|
|
39
|
+
.traceAsyncFn(() => app.init());
|
|
33
40
|
yield render();
|
|
41
|
+
runAppTrace.stop();
|
|
34
42
|
});
|
|
35
43
|
export { run, app };
|
|
36
44
|
if (module.hot) {
|
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
import setRuntimeConfig from '@shuvi/app/core/setRuntimeConfig';
|
|
6
6
|
import runtimeConfig from '@shuvi/app/core/runtimeConfig';
|
|
7
7
|
import { getAppData } from '@shuvi/platform-shared/shared';
|
|
8
|
+
import { CLIENT_ENTRY } from '@shuvi/shared/constants/trace';
|
|
9
|
+
import { clientEntryTrace } from './trace';
|
|
10
|
+
clientEntryTrace
|
|
11
|
+
.traceChild(CLIENT_ENTRY.events.SHUVI_CLIENT_ENTRY_START.name)
|
|
12
|
+
.stop();
|
|
13
|
+
const setupEnvTrace = clientEntryTrace.traceChild(CLIENT_ENTRY.events.SHUVI_CLIENT_SETUP_ENV.name);
|
|
8
14
|
// === set runtime config ===
|
|
9
15
|
const appData = getAppData();
|
|
10
16
|
// build-time config for none-ssr
|
|
@@ -15,3 +21,4 @@ if (runtimeConfig) {
|
|
|
15
21
|
if (appData.runtimeConfig) {
|
|
16
22
|
setRuntimeConfig(appData.runtimeConfig);
|
|
17
23
|
}
|
|
24
|
+
setupEnvTrace.stop();
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { useCurrentRoute, useRouter } from '@shuvi/router-react';
|
|
2
3
|
import { errorModel, errorModelName } from '@shuvi/platform-shared/shared';
|
|
3
4
|
import { AppProvider } from './ApplicationContext';
|
|
4
5
|
import ErrorPage from './ErrorPage';
|
|
5
6
|
import { ErrorBoundary } from './ErrorBoundary';
|
|
6
7
|
import { Provider, useSharedModel } from './store';
|
|
8
|
+
import { clientRenderTrace } from '../entry/client/trace';
|
|
9
|
+
import { CLIENT_RENDER } from '@shuvi/shared/constants/trace';
|
|
10
|
+
const { SHUVI_NAVIGATION_TRIGGERED, SHUVI_NAVIGATION_DONE, SHUVI_PAGE_READY } = CLIENT_RENDER.events;
|
|
7
11
|
function ErrorGuard({ children = null }) {
|
|
8
12
|
const errorState = useSharedModel(errorModelName, errorModel);
|
|
9
13
|
const { error, hasError } = errorState;
|
|
@@ -12,7 +16,42 @@ function ErrorGuard({ children = null }) {
|
|
|
12
16
|
}
|
|
13
17
|
return <>{children}</>;
|
|
14
18
|
}
|
|
19
|
+
const uuid = () => {
|
|
20
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
21
|
+
var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
|
|
22
|
+
return v.toString(16);
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
function useTrace() {
|
|
26
|
+
const router = useRouter();
|
|
27
|
+
const route = useCurrentRoute();
|
|
28
|
+
let navigationTrace = React.useRef();
|
|
29
|
+
React.useEffect(() => {
|
|
30
|
+
clientRenderTrace.traceChild(SHUVI_PAGE_READY.name).stop();
|
|
31
|
+
router.beforeEach((to, from, next) => {
|
|
32
|
+
const fromPath = `${from.pathname}${from.search}`;
|
|
33
|
+
const toPath = `${to.pathname}${to.search}`;
|
|
34
|
+
const navigationId = uuid();
|
|
35
|
+
const traceAttrs = {
|
|
36
|
+
[SHUVI_NAVIGATION_DONE.attrs.from.name]: fromPath,
|
|
37
|
+
[SHUVI_NAVIGATION_DONE.attrs.to.name]: toPath,
|
|
38
|
+
[SHUVI_NAVIGATION_DONE.attrs.navigationId.name]: navigationId
|
|
39
|
+
};
|
|
40
|
+
clientRenderTrace
|
|
41
|
+
.traceChild(SHUVI_NAVIGATION_TRIGGERED.name, traceAttrs)
|
|
42
|
+
.stop();
|
|
43
|
+
navigationTrace.current = clientRenderTrace.traceChild(SHUVI_NAVIGATION_DONE.name);
|
|
44
|
+
navigationTrace.current.setAttributes(traceAttrs);
|
|
45
|
+
next();
|
|
46
|
+
});
|
|
47
|
+
}, []);
|
|
48
|
+
React.useEffect(() => {
|
|
49
|
+
var _a;
|
|
50
|
+
(_a = navigationTrace.current) === null || _a === void 0 ? void 0 : _a.stop();
|
|
51
|
+
}, [route]);
|
|
52
|
+
}
|
|
15
53
|
export default function AppContainer({ app, children }) {
|
|
54
|
+
useTrace();
|
|
16
55
|
return (<AppProvider app={app}>
|
|
17
56
|
<ErrorBoundary>
|
|
18
57
|
<Provider store={app.store}>
|
|
@@ -9,11 +9,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import * as React from 'react';
|
|
11
11
|
import { SHUVI_ERROR } from '@shuvi/shared/constants';
|
|
12
|
+
import { CLIENT_ENTRY } from '@shuvi/shared/constants/trace';
|
|
12
13
|
import { Router } from '@shuvi/router-react';
|
|
13
14
|
import AppContainer from '../AppContainer';
|
|
14
15
|
import { HeadManager, HeadManagerContext } from '../head';
|
|
15
16
|
import Loadable from '../loadable';
|
|
16
17
|
import { doRender } from './render';
|
|
18
|
+
import { clientEntryTrace } from '../../entry/client/trace';
|
|
17
19
|
const headManager = new HeadManager();
|
|
18
20
|
export class ReactClientView {
|
|
19
21
|
constructor() {
|
|
@@ -63,12 +65,16 @@ export class ReactClientView {
|
|
|
63
65
|
</HeadManagerContext.Provider>
|
|
64
66
|
</AppContainer>
|
|
65
67
|
</Router>);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
clientEntryTrace
|
|
69
|
+
.traceChild(CLIENT_ENTRY.events.SHUVI_CLIENT_DO_RENDER.name)
|
|
70
|
+
.traceFn(() => {
|
|
71
|
+
doRender({
|
|
72
|
+
root,
|
|
73
|
+
appContainer,
|
|
74
|
+
shouldHydrate
|
|
75
|
+
}, () => {
|
|
76
|
+
this._isInitialRender = false;
|
|
77
|
+
});
|
|
72
78
|
});
|
|
73
79
|
});
|
|
74
80
|
}
|
|
@@ -11,6 +11,7 @@ import * as React from 'react';
|
|
|
11
11
|
import { renderToString } from 'react-dom/server';
|
|
12
12
|
import { redirect } from '@shuvi/platform-shared/shared';
|
|
13
13
|
import { SHUVI_ERROR } from '@shuvi/shared/constants';
|
|
14
|
+
import { SERVER_REQUEST } from '@shuvi/shared/constants/trace';
|
|
14
15
|
import { Router } from '@shuvi/router-react';
|
|
15
16
|
import logger from '@shuvi/utils/logger';
|
|
16
17
|
import Loadable, { LoadableContext } from '../loadable';
|
|
@@ -18,9 +19,10 @@ import AppContainer from '../AppContainer';
|
|
|
18
19
|
import { Head } from '../head';
|
|
19
20
|
import { serializeServerError } from '../../helper/serializeServerError';
|
|
20
21
|
import isThirdSite from '../../helper/isThirdSite';
|
|
22
|
+
const { SHUVI_SERVER_RENDER_TO_STRING } = SERVER_REQUEST.events;
|
|
21
23
|
export class ReactServerView {
|
|
22
24
|
constructor() {
|
|
23
|
-
this.renderApp = ({ req, app, manifest }) => __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
this.renderApp = ({ req, app, manifest, serverRequestTrace }) => __awaiter(this, void 0, void 0, function* () {
|
|
24
26
|
yield Loadable.preloadAll();
|
|
25
27
|
const { router, appComponent: AppComponent, setError: setAppError } = app;
|
|
26
28
|
yield router.ready;
|
|
@@ -52,10 +54,13 @@ export class ReactServerView {
|
|
|
52
54
|
</LoadableContext.Provider>
|
|
53
55
|
</AppContainer>
|
|
54
56
|
</Router>);
|
|
57
|
+
const renderToStringTrace = serverRequestTrace.traceChild(SHUVI_SERVER_RENDER_TO_STRING.name);
|
|
55
58
|
try {
|
|
56
59
|
htmlContent = renderToString(RootApp);
|
|
60
|
+
renderToStringTrace.setAttribute(SHUVI_SERVER_RENDER_TO_STRING.attrs.error.name, false);
|
|
57
61
|
}
|
|
58
62
|
catch (error) {
|
|
63
|
+
renderToStringTrace.setAttribute(SHUVI_SERVER_RENDER_TO_STRING.attrs.error.name, true);
|
|
59
64
|
if (process.env.NODE_ENV === 'development') {
|
|
60
65
|
logger.error(error.stack);
|
|
61
66
|
}
|
|
@@ -64,6 +69,7 @@ export class ReactServerView {
|
|
|
64
69
|
}
|
|
65
70
|
finally {
|
|
66
71
|
head = Head.rewind() || [];
|
|
72
|
+
renderToStringTrace.stop();
|
|
67
73
|
}
|
|
68
74
|
const { loadble } = manifest;
|
|
69
75
|
const dynamicImportIdSet = new Set();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const service_1 = require("@shuvi/service");
|
|
4
|
+
const shared_1 = require("../shared");
|
|
5
|
+
const paths_1 = require("./paths");
|
|
6
|
+
const configWebpack = (config, { name, helpers }) => {
|
|
7
|
+
if (name === shared_1.BUNDLER_TARGET_SERVER) {
|
|
8
|
+
helpers.addExternals(config, ({ request }, next) => {
|
|
9
|
+
if (/@shuvi[/\\](hook$|router$|utils)/.test(request)) {
|
|
10
|
+
return next(null, (0, paths_1.resolveDep)(request));
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
return next(null, 'next');
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return config;
|
|
18
|
+
};
|
|
19
|
+
exports.default = {
|
|
20
|
+
core: (0, service_1.createPlugin)({
|
|
21
|
+
configWebpack
|
|
22
|
+
})
|
|
23
|
+
};
|
|
@@ -12,19 +12,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.getPageMiddleware = void 0;
|
|
13
13
|
const utils_1 = require("@shuvi/service/lib/server/utils");
|
|
14
14
|
const shared_1 = require("@shuvi/platform-shared/shared");
|
|
15
|
+
const trace_1 = require("@shuvi/shared/constants/trace");
|
|
15
16
|
const renderToHTML_1 = require("./renderToHTML");
|
|
17
|
+
const { SHUVI_SERVER_SEND_HTML_ORIGINAL, SHUVI_SERVER_SEND_HTML_HOOK, SHUVI_SERVER_RENDER_TO_HTML, SHUVI_SERVER_RUN_PAGE_MIDDLEWARE } = trace_1.SERVER_REQUEST.events;
|
|
16
18
|
function createPageHandler(serverPluginContext) {
|
|
19
|
+
const { traces: { serverRequestTrace } } = serverPluginContext;
|
|
17
20
|
const wrappedSendHtml = (html, { req, res }) => __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
const sendHtmlOriginalTrace = serverRequestTrace.traceChild(SHUVI_SERVER_SEND_HTML_ORIGINAL.name);
|
|
18
22
|
(0, utils_1.sendHTML)(req, res, html);
|
|
23
|
+
sendHtmlOriginalTrace.stop();
|
|
19
24
|
});
|
|
20
25
|
let sendHtml;
|
|
21
26
|
let pendingSendHtml;
|
|
22
27
|
return function (req, res) {
|
|
23
28
|
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
-
const result = yield
|
|
29
|
+
const result = yield serverRequestTrace
|
|
30
|
+
.traceChild(SHUVI_SERVER_RENDER_TO_HTML.name)
|
|
31
|
+
.traceAsyncFn(() => (0, renderToHTML_1.renderToHTML)({
|
|
25
32
|
req: req,
|
|
26
33
|
serverPluginContext
|
|
27
|
-
});
|
|
34
|
+
}));
|
|
28
35
|
if ((0, shared_1.isRedirect)(result)) {
|
|
29
36
|
const redirectResp = result;
|
|
30
37
|
res.writeHead(redirectResp.status, {
|
|
@@ -42,7 +49,10 @@ function createPageHandler(serverPluginContext) {
|
|
|
42
49
|
}
|
|
43
50
|
sendHtml = yield pendingSendHtml;
|
|
44
51
|
}
|
|
52
|
+
const { traces: { serverRequestTrace } } = serverPluginContext;
|
|
53
|
+
const sendHtmlHookTrace = serverRequestTrace.traceChild(SHUVI_SERVER_SEND_HTML_HOOK.name);
|
|
45
54
|
yield sendHtml(textResp.data, { req, res });
|
|
55
|
+
sendHtmlHookTrace.stop();
|
|
46
56
|
}
|
|
47
57
|
else {
|
|
48
58
|
// shuold never reach here
|
|
@@ -58,6 +68,8 @@ function getPageMiddleware(api) {
|
|
|
58
68
|
let pendingPageHandler;
|
|
59
69
|
return function (req, res, next) {
|
|
60
70
|
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
const { traces: { serverRequestTrace } } = api;
|
|
72
|
+
const runPageMiddlewareTrace = serverRequestTrace.traceChild(SHUVI_SERVER_RUN_PAGE_MIDDLEWARE.name);
|
|
61
73
|
if (!pageHandler) {
|
|
62
74
|
if (!pendingPageHandler) {
|
|
63
75
|
pendingPageHandler =
|
|
@@ -67,8 +79,18 @@ function getPageMiddleware(api) {
|
|
|
67
79
|
}
|
|
68
80
|
try {
|
|
69
81
|
yield pageHandler(req, res);
|
|
82
|
+
runPageMiddlewareTrace.setAttributes({
|
|
83
|
+
[SHUVI_SERVER_RUN_PAGE_MIDDLEWARE.attrs.error.name]: false,
|
|
84
|
+
[SHUVI_SERVER_RUN_PAGE_MIDDLEWARE.attrs.statusCode.name]: res.statusCode
|
|
85
|
+
});
|
|
86
|
+
runPageMiddlewareTrace.stop();
|
|
70
87
|
}
|
|
71
88
|
catch (error) {
|
|
89
|
+
runPageMiddlewareTrace.setAttributes({
|
|
90
|
+
[SHUVI_SERVER_RUN_PAGE_MIDDLEWARE.attrs.error.name]: true,
|
|
91
|
+
[SHUVI_SERVER_RUN_PAGE_MIDDLEWARE.attrs.statusCode.name]: res.statusCode
|
|
92
|
+
});
|
|
93
|
+
runPageMiddlewareTrace.stop();
|
|
72
94
|
next(error);
|
|
73
95
|
}
|
|
74
96
|
});
|
|
@@ -14,18 +14,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.renderToHTML = void 0;
|
|
16
16
|
const resources_1 = __importDefault(require("@shuvi/service/lib/resources"));
|
|
17
|
+
const trace_1 = require("@shuvi/shared/constants/trace");
|
|
17
18
|
const renderer_1 = require("./renderer");
|
|
18
19
|
function renderToHTML({ req, serverPluginContext }) {
|
|
19
20
|
return __awaiter(this, void 0, void 0, function* () {
|
|
20
21
|
let result;
|
|
21
22
|
const renderer = new renderer_1.Renderer({ serverPluginContext });
|
|
23
|
+
const { traces: { serverCreateAppTrace } } = serverPluginContext;
|
|
22
24
|
const { application } = resources_1.default.server;
|
|
23
|
-
const app =
|
|
25
|
+
const app = serverCreateAppTrace
|
|
26
|
+
.traceChild(trace_1.SERVER_CREATE_APP.events.SHUVI_SERVER_CREATE_APP.name)
|
|
27
|
+
.traceFn(() => application.createApp({
|
|
24
28
|
req,
|
|
25
|
-
ssr: serverPluginContext.config.ssr
|
|
26
|
-
|
|
29
|
+
ssr: serverPluginContext.config.ssr,
|
|
30
|
+
serverCreateAppTrace
|
|
31
|
+
}));
|
|
27
32
|
try {
|
|
28
|
-
yield
|
|
33
|
+
yield serverCreateAppTrace
|
|
34
|
+
.traceChild(trace_1.SERVER_CREATE_APP.events.SHUVI_SERVER_APP_INIT.name)
|
|
35
|
+
.traceAsyncFn(() => app.init());
|
|
29
36
|
result = yield renderer.renderView({
|
|
30
37
|
req,
|
|
31
38
|
app: app.getPublicAPI(),
|
|
@@ -22,6 +22,7 @@ class SsrRenderer extends base_1.BaseRenderer {
|
|
|
22
22
|
return __awaiter(this, void 0, void 0, function* () {
|
|
23
23
|
const { store, router, context } = app;
|
|
24
24
|
const serverPluginContext = this._serverPluginContext;
|
|
25
|
+
const { traces: { serverRequestTrace } } = serverPluginContext;
|
|
25
26
|
const { view } = resources_1.default.server;
|
|
26
27
|
if (!router) {
|
|
27
28
|
throw new Error('router is null');
|
|
@@ -29,7 +30,8 @@ class SsrRenderer extends base_1.BaseRenderer {
|
|
|
29
30
|
const result = yield view.renderApp({
|
|
30
31
|
app,
|
|
31
32
|
req,
|
|
32
|
-
manifest: resources_1.default.clientManifest
|
|
33
|
+
manifest: resources_1.default.clientManifest,
|
|
34
|
+
serverRequestTrace
|
|
33
35
|
});
|
|
34
36
|
if ((0, shared_1.isResponse)(result)) {
|
|
35
37
|
return result;
|
package/lib/node/index.js
CHANGED
|
@@ -22,8 +22,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
22
22
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
23
23
|
});
|
|
24
24
|
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
25
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
29
|
const node_1 = require("@shuvi/platform-shared/node");
|
|
30
|
+
const trace_1 = __importDefault(require("./trace"));
|
|
31
|
+
const external_internal_libs_1 = __importDefault(require("./external-internal-libs"));
|
|
27
32
|
const features_1 = require("./features");
|
|
28
33
|
const paths_1 = require("./paths");
|
|
29
34
|
__exportStar(require("../shared"), exports);
|
|
@@ -38,6 +43,8 @@ const platform = ({ framework = 'react' } = {}) => (platformContext) => __awaite
|
|
|
38
43
|
(0, paths_1.resolvePkgFile)('shuvi-image.d.ts')
|
|
39
44
|
],
|
|
40
45
|
plugins: [
|
|
46
|
+
external_internal_libs_1.default,
|
|
47
|
+
trace_1.default,
|
|
41
48
|
...node_1.SharedPlugins,
|
|
42
49
|
...(0, features_1.getPlugins)(platformContext),
|
|
43
50
|
...platformFrameworkContent.plugins
|
package/lib/node/paths.d.ts
CHANGED
package/lib/node/paths.js
CHANGED
|
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.resolvePkgFile = exports.resolveLib = exports.resolveDep = void 0;
|
|
26
|
+
exports.resolveLocal = exports.resolvePkgFile = exports.resolveLib = exports.resolveDep = void 0;
|
|
27
27
|
const path = __importStar(require("path"));
|
|
28
28
|
const PACKAGE_DIR = path.resolve(__dirname, '..', '..');
|
|
29
29
|
const resolveDep = (module) => require.resolve(module);
|
|
@@ -32,3 +32,8 @@ const resolveLib = (module) => path.dirname((0, exports.resolveDep)(path.join(mo
|
|
|
32
32
|
exports.resolveLib = resolveLib;
|
|
33
33
|
const resolvePkgFile = (...paths) => path.join(PACKAGE_DIR, ...paths);
|
|
34
34
|
exports.resolvePkgFile = resolvePkgFile;
|
|
35
|
+
const resolveLocal = (m, sub) => {
|
|
36
|
+
const pck = (0, exports.resolveLib)(m);
|
|
37
|
+
return sub ? `${pck}/${sub}` : pck;
|
|
38
|
+
};
|
|
39
|
+
exports.resolveLocal = resolveLocal;
|
|
@@ -29,13 +29,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
29
29
|
const path = __importStar(require("path"));
|
|
30
30
|
const service_1 = require("@shuvi/service");
|
|
31
31
|
const ReactRefreshWebpackPlugin_1 = __importDefault(require("@next/react-refresh-utils/ReactRefreshWebpackPlugin"));
|
|
32
|
+
const paths_1 = require("../../../paths");
|
|
32
33
|
const shared_1 = require("../../../../shared");
|
|
33
34
|
const isDefined = (value) => Boolean(value);
|
|
34
35
|
const configWebpack = (config, { name, webpack }, context) => {
|
|
35
|
-
const resolveLocal = (m, sub) => {
|
|
36
|
-
const pck = path.dirname(require.resolve(`${m}/package.json`));
|
|
37
|
-
return sub ? `${pck}/${sub}` : pck;
|
|
38
|
-
};
|
|
39
36
|
const resolveUser = (m, sub) => {
|
|
40
37
|
const { rootDir } = context.paths;
|
|
41
38
|
let userPkg = {
|
|
@@ -69,32 +66,32 @@ const configWebpack = (config, { name, webpack }, context) => {
|
|
|
69
66
|
}
|
|
70
67
|
catch (_a) { }
|
|
71
68
|
if (!version) {
|
|
72
|
-
version = require(resolveLocal('react-dom')).version;
|
|
69
|
+
version = require((0, paths_1.resolveLocal)('react-dom')).version;
|
|
73
70
|
}
|
|
74
71
|
const majorVersion = parseInt(version.split('.')[0] || '', 10);
|
|
75
72
|
return majorVersion >= 18;
|
|
76
73
|
};
|
|
77
|
-
config.resolve.alias.set('@shuvi/service', resolveLocal('@shuvi/service'));
|
|
78
|
-
config.resolve.alias.set('@shuvi/router$', resolveLocal('@shuvi/router'));
|
|
79
|
-
config.resolve.alias.set('@shuvi/router-react$', resolveLocal('@shuvi/router-react'));
|
|
74
|
+
config.resolve.alias.set('@shuvi/service', (0, paths_1.resolveLocal)('@shuvi/service'));
|
|
75
|
+
config.resolve.alias.set('@shuvi/router$', (0, paths_1.resolveLocal)('@shuvi/router'));
|
|
76
|
+
config.resolve.alias.set('@shuvi/router-react$', (0, paths_1.resolveLocal)('@shuvi/router-react'));
|
|
80
77
|
config.resolve.alias.set('react$',
|
|
81
78
|
// @ts-ignore
|
|
82
|
-
[resolveUser('react'), resolveLocal('react')].filter(isDefined));
|
|
79
|
+
[resolveUser('react'), (0, paths_1.resolveLocal)('react')].filter(isDefined));
|
|
83
80
|
config.resolve.alias.set('react/jsx-runtime$',
|
|
84
81
|
// @ts-ignore
|
|
85
82
|
[
|
|
86
83
|
resolveUser('react', 'jsx-runtime'),
|
|
87
|
-
resolveLocal('react', 'jsx-runtime')
|
|
84
|
+
(0, paths_1.resolveLocal)('react', 'jsx-runtime')
|
|
88
85
|
].filter(isDefined));
|
|
89
86
|
config.resolve.alias.set('react/jsx-dev-runtime$',
|
|
90
87
|
// @ts-ignore
|
|
91
88
|
[
|
|
92
89
|
resolveUser('react', 'jsx-dev-runtime'),
|
|
93
|
-
resolveLocal('react', 'jsx-dev-runtime')
|
|
90
|
+
(0, paths_1.resolveLocal)('react', 'jsx-dev-runtime')
|
|
94
91
|
].filter(isDefined));
|
|
95
92
|
config.resolve.alias.set('react-dom$',
|
|
96
93
|
// @ts-ignore
|
|
97
|
-
[resolveUser('react-dom'), resolveLocal('react-dom')].filter(isDefined));
|
|
94
|
+
[resolveUser('react-dom'), (0, paths_1.resolveLocal)('react-dom')].filter(isDefined));
|
|
98
95
|
if (name === shared_1.BUNDLER_TARGET_CLIENT) {
|
|
99
96
|
config.plugin('version-env-plugin').use(webpack.DefinePlugin, [
|
|
100
97
|
{
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const service_1 = require("@shuvi/service");
|
|
4
|
+
const shared_1 = require("../shared");
|
|
5
|
+
const paths_1 = require("./paths");
|
|
6
|
+
const configWebpack = (config, { name, helpers }) => {
|
|
7
|
+
if (name === shared_1.BUNDLER_TARGET_SERVER) {
|
|
8
|
+
const tracePath = (0, paths_1.resolveLocal)('@shuvi/service', 'lib/trace');
|
|
9
|
+
helpers.addExternals(config, ({ request }, next) => {
|
|
10
|
+
switch (request) {
|
|
11
|
+
// trace is a singleton, so we don't want to bundle it
|
|
12
|
+
case '@shuvi/service/lib/trace': {
|
|
13
|
+
next(null, `commonjs ${tracePath}`);
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
default: {
|
|
17
|
+
next(null, 'next');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return config;
|
|
23
|
+
};
|
|
24
|
+
exports.default = {
|
|
25
|
+
core: (0, service_1.createPlugin)({
|
|
26
|
+
configWebpack
|
|
27
|
+
})
|
|
28
|
+
};
|
package/lib/shared/appTypes.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { IPageRouteRecord, IAppData, IAppState, Application as _Application } from '@shuvi/platform-shared/shared';
|
|
2
2
|
import { ApplicationImpl as _ApplicationImpl } from '@shuvi/platform-shared/shuvi-app/application';
|
|
3
3
|
import type { ShuviRequest } from '@shuvi/service';
|
|
4
|
+
import { Span } from '@shuvi/service/lib/trace';
|
|
4
5
|
export interface AppConfig {
|
|
5
6
|
ssr: boolean;
|
|
6
7
|
}
|
|
@@ -10,6 +11,7 @@ export interface CreateAppServer {
|
|
|
10
11
|
(options: {
|
|
11
12
|
req: ShuviRequest;
|
|
12
13
|
ssr: boolean;
|
|
14
|
+
serverCreateAppTrace: Span;
|
|
13
15
|
}): InternalApplication;
|
|
14
16
|
}
|
|
15
17
|
export interface CreateAppClient {
|
|
@@ -2,6 +2,7 @@ import type { ShuviRequest } from '@shuvi/service';
|
|
|
2
2
|
import { Response, IAppData } from '@shuvi/platform-shared/shared';
|
|
3
3
|
import { IManifest } from '../shared';
|
|
4
4
|
import { Application } from './appTypes';
|
|
5
|
+
import { Span } from '@shuvi/service/lib/trace';
|
|
5
6
|
export declare type IRenderViewOptions = {
|
|
6
7
|
app: Application;
|
|
7
8
|
};
|
|
@@ -38,6 +39,7 @@ export interface IClientRendererOptions<ExtraAppData = {}> extends IRenderOption
|
|
|
38
39
|
export interface IServerRendererOptions extends IRenderOptions {
|
|
39
40
|
req: ShuviRequest;
|
|
40
41
|
manifest: IManifest;
|
|
42
|
+
serverRequestTrace: Span;
|
|
41
43
|
}
|
|
42
44
|
export interface IViewClient<ExtraAppData = {}> extends IView<IClientRendererOptions<ExtraAppData>> {
|
|
43
45
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shuvi/platform-web",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/shuvijs/shuvi.git",
|
|
@@ -72,15 +72,15 @@
|
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
74
|
"@next/react-refresh-utils": "12.1.6",
|
|
75
|
-
"@shuvi/error-overlay": "1.0.
|
|
76
|
-
"@shuvi/hook": "1.0.
|
|
77
|
-
"@shuvi/platform-shared": "1.0.
|
|
78
|
-
"@shuvi/router": "1.0.
|
|
79
|
-
"@shuvi/router-react": "1.0.
|
|
80
|
-
"@shuvi/runtime": "1.0.
|
|
81
|
-
"@shuvi/shared": "1.0.
|
|
82
|
-
"@shuvi/toolpack": "1.0.
|
|
83
|
-
"@shuvi/utils": "1.0.
|
|
75
|
+
"@shuvi/error-overlay": "1.0.30",
|
|
76
|
+
"@shuvi/hook": "1.0.30",
|
|
77
|
+
"@shuvi/platform-shared": "1.0.30",
|
|
78
|
+
"@shuvi/router": "1.0.30",
|
|
79
|
+
"@shuvi/router-react": "1.0.30",
|
|
80
|
+
"@shuvi/runtime": "1.0.30",
|
|
81
|
+
"@shuvi/shared": "1.0.30",
|
|
82
|
+
"@shuvi/toolpack": "1.0.30",
|
|
83
|
+
"@shuvi/utils": "1.0.30",
|
|
84
84
|
"content-type": "1.0.4",
|
|
85
85
|
"core-js": "3.6.5",
|
|
86
86
|
"doura": "0.0.11",
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"whatwg-fetch": "3.0.0"
|
|
99
99
|
},
|
|
100
100
|
"peerDependencies": {
|
|
101
|
-
"@shuvi/service": "1.0.
|
|
101
|
+
"@shuvi/service": "1.0.30"
|
|
102
102
|
},
|
|
103
103
|
"devDependencies": {
|
|
104
104
|
"@shuvi/service": "workspace:*",
|