@shuvi/platform-web 1.0.39 → 1.0.42
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/shuvi-app/app/client.js +8 -13
- package/esm/shuvi-app/app/server.js +2 -0
- package/esm/shuvi-app/react/AppContainer.jsx +4 -40
- package/esm/shuvi-app/react/Trace.d.ts +3 -0
- package/esm/shuvi-app/react/Trace.jsx +43 -0
- package/lib/node/features/filesystem-routes/api/middleware.js +3 -1
- package/lib/node/features/filesystem-routes/middleware/middleware.js +14 -3
- package/lib/node/features/html-render/lib/getPageMiddleware.js +2 -1
- package/package.json +11 -11
|
@@ -43,16 +43,14 @@ export const createApp = ({ routes, appData, appComponent }) => {
|
|
|
43
43
|
});
|
|
44
44
|
const loadersData = app.getLoadersData();
|
|
45
45
|
const hasHydrateData = Object.keys(loadersData).length > 0;
|
|
46
|
-
let shouldHydrate = ssr
|
|
47
|
-
let hasServerError = !!app.error;
|
|
46
|
+
let shouldHydrate = !!ssr;
|
|
48
47
|
router.beforeResolve((to, from, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
48
|
+
// when hydrating, we will never run loaders, but just use the data from server
|
|
49
49
|
if (shouldHydrate) {
|
|
50
50
|
shouldHydrate = false;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (hasServerError) {
|
|
55
|
-
hasServerError = false;
|
|
51
|
+
if (hasHydrateData) {
|
|
52
|
+
app.setLoadersData(loadersData);
|
|
53
|
+
}
|
|
56
54
|
return next();
|
|
57
55
|
}
|
|
58
56
|
if (!to.matches.length) {
|
|
@@ -113,10 +111,7 @@ export const createApp = ({ routes, appData, appComponent }) => {
|
|
|
113
111
|
window.location.replace(location);
|
|
114
112
|
}
|
|
115
113
|
else {
|
|
116
|
-
next(
|
|
117
|
-
path: location,
|
|
118
|
-
replace: true
|
|
119
|
-
});
|
|
114
|
+
next(location);
|
|
120
115
|
}
|
|
121
116
|
runLoadersTrace.setAttribute(SHUVI_CLIENT_RUN_LOADERS.attrs.errorType.name, 'redirect');
|
|
122
117
|
runLoadersTrace.stop();
|
|
@@ -132,6 +127,8 @@ export const createApp = ({ routes, appData, appComponent }) => {
|
|
|
132
127
|
runLoadersTrace.stop();
|
|
133
128
|
return;
|
|
134
129
|
}
|
|
130
|
+
runLoadersTrace.setAttribute(SHUVI_CLIENT_RUN_LOADERS.attrs.errorType.name, 'unexpectedError');
|
|
131
|
+
runLoadersTrace.stop();
|
|
135
132
|
// If loader throws a error, we need to rethrow it
|
|
136
133
|
app.setError({
|
|
137
134
|
message: SHUVI_ERROR.CLIENT_ERROR.message,
|
|
@@ -141,8 +138,6 @@ export const createApp = ({ routes, appData, appComponent }) => {
|
|
|
141
138
|
next(() => {
|
|
142
139
|
throw error;
|
|
143
140
|
});
|
|
144
|
-
runLoadersTrace.setAttribute(SHUVI_CLIENT_RUN_LOADERS.attrs.errorType.name, 'unexpectedError');
|
|
145
|
-
runLoadersTrace.stop();
|
|
146
141
|
return;
|
|
147
142
|
}
|
|
148
143
|
next(() => {
|
|
@@ -51,6 +51,8 @@ export const createApp = options => {
|
|
|
51
51
|
if (isRedirect(error)) {
|
|
52
52
|
const location = error.headers.get('Location');
|
|
53
53
|
const status = error.status;
|
|
54
|
+
// server side redirect is different from regular route redirect because it has the extra data - statusCode
|
|
55
|
+
// So it won't change route target, but just store the redirect location in state
|
|
54
56
|
next({
|
|
55
57
|
path: pathToString(to),
|
|
56
58
|
replace: true,
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useCurrentRoute, useRouter } from '@shuvi/router-react';
|
|
3
2
|
import { errorModel, errorModelName } from '@shuvi/platform-shared/shared';
|
|
4
3
|
import { AppProvider } from './ApplicationContext';
|
|
5
4
|
import ErrorPage from './ErrorPage';
|
|
6
5
|
import { ErrorBoundary } from './ErrorBoundary';
|
|
7
6
|
import { Provider, useSharedModel } from './store';
|
|
8
|
-
import {
|
|
9
|
-
import { CLIENT_RENDER } from '@shuvi/shared/constants/trace';
|
|
10
|
-
const { SHUVI_NAVIGATION_TRIGGERED, SHUVI_NAVIGATION_DONE, SHUVI_PAGE_READY } = CLIENT_RENDER.events;
|
|
7
|
+
import { Trace } from './Trace';
|
|
11
8
|
function ErrorGuard({ children = null }) {
|
|
12
9
|
const errorState = useSharedModel(errorModelName, errorModel);
|
|
13
10
|
const { error, hasError } = errorState;
|
|
@@ -16,46 +13,13 @@ function ErrorGuard({ children = null }) {
|
|
|
16
13
|
}
|
|
17
14
|
return <>{children}</>;
|
|
18
15
|
}
|
|
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
|
-
}
|
|
53
16
|
export default function AppContainer({ app, children }) {
|
|
54
|
-
useTrace();
|
|
55
17
|
return (<AppProvider app={app}>
|
|
56
18
|
<ErrorBoundary>
|
|
57
19
|
<Provider store={app.store}>
|
|
58
|
-
<ErrorGuard>
|
|
20
|
+
<ErrorGuard>
|
|
21
|
+
<Trace>{children}</Trace>
|
|
22
|
+
</ErrorGuard>
|
|
59
23
|
</Provider>
|
|
60
24
|
</ErrorBoundary>
|
|
61
25
|
</AppProvider>);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useCurrentRoute, useRouter } from '@shuvi/router-react';
|
|
3
|
+
import { clientRenderTrace } from '../entry/client/trace';
|
|
4
|
+
import { CLIENT_RENDER } from '@shuvi/shared/constants/trace';
|
|
5
|
+
const { SHUVI_NAVIGATION_TRIGGERED, SHUVI_NAVIGATION_DONE, SHUVI_PAGE_READY } = CLIENT_RENDER.events;
|
|
6
|
+
const uuid = () => {
|
|
7
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
8
|
+
var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
|
|
9
|
+
return v.toString(16);
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
export function useTrace() {
|
|
13
|
+
const router = useRouter();
|
|
14
|
+
const route = useCurrentRoute();
|
|
15
|
+
let navigationTrace = React.useRef();
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
clientRenderTrace.traceChild(SHUVI_PAGE_READY.name).stop();
|
|
18
|
+
router.beforeEach((to, from, next) => {
|
|
19
|
+
const fromPath = `${from.pathname}${from.search}`;
|
|
20
|
+
const toPath = `${to.pathname}${to.search}`;
|
|
21
|
+
const navigationId = uuid();
|
|
22
|
+
const traceAttrs = {
|
|
23
|
+
[SHUVI_NAVIGATION_DONE.attrs.from.name]: fromPath,
|
|
24
|
+
[SHUVI_NAVIGATION_DONE.attrs.to.name]: toPath,
|
|
25
|
+
[SHUVI_NAVIGATION_DONE.attrs.navigationId.name]: navigationId
|
|
26
|
+
};
|
|
27
|
+
clientRenderTrace
|
|
28
|
+
.traceChild(SHUVI_NAVIGATION_TRIGGERED.name, traceAttrs)
|
|
29
|
+
.stop();
|
|
30
|
+
navigationTrace.current = clientRenderTrace.traceChild(SHUVI_NAVIGATION_DONE.name);
|
|
31
|
+
navigationTrace.current.setAttributes(traceAttrs);
|
|
32
|
+
next();
|
|
33
|
+
});
|
|
34
|
+
}, []);
|
|
35
|
+
React.useEffect(() => {
|
|
36
|
+
var _a;
|
|
37
|
+
(_a = navigationTrace.current) === null || _a === void 0 ? void 0 : _a.stop();
|
|
38
|
+
}, [route]);
|
|
39
|
+
}
|
|
40
|
+
export function Trace({ children = null }) {
|
|
41
|
+
useTrace();
|
|
42
|
+
return <>{children}</>;
|
|
43
|
+
}
|
|
@@ -43,9 +43,11 @@ function middleware(_ctx) {
|
|
|
43
43
|
catch (error) {
|
|
44
44
|
runApiMiddlewareTrace.setAttributes({
|
|
45
45
|
[SHUVI_SERVER_RUN_API_MIDDLEWARE.attrs.error.name]: true,
|
|
46
|
-
[SHUVI_SERVER_RUN_API_MIDDLEWARE.attrs.statusCode.name]:
|
|
46
|
+
[SHUVI_SERVER_RUN_API_MIDDLEWARE.attrs.statusCode.name]: 500
|
|
47
47
|
});
|
|
48
|
+
runApiMiddlewareTrace.stop();
|
|
48
49
|
next(error);
|
|
50
|
+
return;
|
|
49
51
|
}
|
|
50
52
|
runApiMiddlewareTrace.setAttributes({
|
|
51
53
|
[SHUVI_SERVER_RUN_API_MIDDLEWARE.attrs.error.name]: false,
|
|
@@ -15,8 +15,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.middleware = void 0;
|
|
16
16
|
const router_1 = require("@shuvi/router");
|
|
17
17
|
const resources_1 = __importDefault(require("@shuvi/service/lib/resources"));
|
|
18
|
-
const trace_1 = require("@shuvi/
|
|
19
|
-
const
|
|
18
|
+
const trace_1 = require("@shuvi/service/lib/trace");
|
|
19
|
+
const trace_2 = require("@shuvi/shared/constants/trace");
|
|
20
|
+
const { SHUVI_SERVER_RUN_MIDDLEWARE_ROUTES } = trace_2.SERVER_REQUEST.events;
|
|
20
21
|
function middleware(_api) {
|
|
21
22
|
return function (req, res, next) {
|
|
22
23
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -64,7 +65,17 @@ function middleware(_api) {
|
|
|
64
65
|
return next(err);
|
|
65
66
|
}
|
|
66
67
|
});
|
|
67
|
-
|
|
68
|
+
yield runMiddleware(middlewares[i]);
|
|
69
|
+
// if a middleware directly ends the response, the middlewareRoutesTrace will be recorded here
|
|
70
|
+
if (middlewareRoutesTrace.status === trace_1.SpanStatus.Started) {
|
|
71
|
+
middlewareRoutesTrace.setAttributes({
|
|
72
|
+
[SHUVI_SERVER_RUN_MIDDLEWARE_ROUTES.attrs.error.name]: false,
|
|
73
|
+
[SHUVI_SERVER_RUN_MIDDLEWARE_ROUTES.attrs.statusCode.name]: res.statusCode,
|
|
74
|
+
[SHUVI_SERVER_RUN_MIDDLEWARE_ROUTES.attrs.headersSent.name]: res.headersSent
|
|
75
|
+
});
|
|
76
|
+
middlewareRoutesTrace.stop();
|
|
77
|
+
}
|
|
78
|
+
return;
|
|
68
79
|
}
|
|
69
80
|
catch (err) {
|
|
70
81
|
/** Catch error from the whole function */
|
|
@@ -57,7 +57,7 @@ function createPageHandler(serverPluginContext) {
|
|
|
57
57
|
sendHtmlHookTrace.stop();
|
|
58
58
|
}
|
|
59
59
|
else {
|
|
60
|
-
//
|
|
60
|
+
// should never reach here
|
|
61
61
|
throw new Error('Unexpected reponse type from renderToHTML');
|
|
62
62
|
}
|
|
63
63
|
});
|
|
@@ -90,6 +90,7 @@ function getPageMiddleware(api) {
|
|
|
90
90
|
runPageMiddlewareTrace.stop();
|
|
91
91
|
}
|
|
92
92
|
catch (error) {
|
|
93
|
+
// should never reach here except for server bundle broken
|
|
93
94
|
runPageMiddlewareTrace.setAttributes({
|
|
94
95
|
[SHUVI_SERVER_RUN_PAGE_MIDDLEWARE.attrs.error.name]: true,
|
|
95
96
|
[SHUVI_SERVER_RUN_PAGE_MIDDLEWARE.attrs.statusCode.name]: res.statusCode
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shuvi/platform-web",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.42",
|
|
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.42",
|
|
76
|
+
"@shuvi/hook": "1.0.42",
|
|
77
|
+
"@shuvi/platform-shared": "1.0.42",
|
|
78
|
+
"@shuvi/router": "1.0.42",
|
|
79
|
+
"@shuvi/router-react": "1.0.42",
|
|
80
|
+
"@shuvi/runtime": "1.0.42",
|
|
81
|
+
"@shuvi/shared": "1.0.42",
|
|
82
|
+
"@shuvi/toolpack": "1.0.42",
|
|
83
|
+
"@shuvi/utils": "1.0.42",
|
|
84
84
|
"content-type": "1.0.4",
|
|
85
85
|
"core-js": "3.6.5",
|
|
86
86
|
"doura": "0.0.13",
|
|
@@ -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.42"
|
|
102
102
|
},
|
|
103
103
|
"devDependencies": {
|
|
104
104
|
"@shuvi/service": "workspace:*",
|