@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.
@@ -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 = createApp({
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
- yield app.init();
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();
@@ -0,0 +1,2 @@
1
+ export declare const clientEntryTrace: import("@shuvi/service/lib/trace").Span;
2
+ export declare const clientRenderTrace: import("@shuvi/service/lib/trace").Span;
@@ -0,0 +1,4 @@
1
+ import { trace } from '@shuvi/service/lib/trace';
2
+ import { CLIENT_ENTRY, CLIENT_RENDER } from '@shuvi/shared/constants/trace';
3
+ export const clientEntryTrace = trace(CLIENT_ENTRY.name);
4
+ export const clientRenderTrace = trace(CLIENT_RENDER.name);
@@ -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
- doRender({
67
- root,
68
- appContainer,
69
- shouldHydrate
70
- }, () => {
71
- this._isInitialRender = false;
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,4 @@
1
+ declare const _default: {
2
+ core: import("@shuvi/hook").IPluginInstance<import("@shuvi/service/lib/core/plugin").PluginHooks, import("@shuvi/service").IPluginContext>;
3
+ };
4
+ export default _default;
@@ -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 (0, renderToHTML_1.renderToHTML)({
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 = application.createApp({
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 app.init();
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
@@ -1,3 +1,4 @@
1
1
  export declare const resolveDep: (module: string) => string;
2
2
  export declare const resolveLib: (module: string) => string;
3
3
  export declare const resolvePkgFile: (...paths: string[]) => string;
4
+ export declare const resolveLocal: (m: string, sub?: string) => string;
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,4 @@
1
+ declare const _default: {
2
+ core: import("@shuvi/hook").IPluginInstance<import("@shuvi/service/lib/core/plugin").PluginHooks, import("@shuvi/service").IPluginContext>;
3
+ };
4
+ export default _default;
@@ -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
+ };
@@ -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.28",
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.28",
76
- "@shuvi/hook": "1.0.28",
77
- "@shuvi/platform-shared": "1.0.28",
78
- "@shuvi/router": "1.0.28",
79
- "@shuvi/router-react": "1.0.28",
80
- "@shuvi/runtime": "1.0.28",
81
- "@shuvi/shared": "1.0.28",
82
- "@shuvi/toolpack": "1.0.28",
83
- "@shuvi/utils": "1.0.28",
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.28"
101
+ "@shuvi/service": "1.0.30"
102
102
  },
103
103
  "devDependencies": {
104
104
  "@shuvi/service": "workspace:*",