@shuvi/platform-web 1.0.0-rc.2 → 1.0.0-rc.20

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.
Files changed (152) hide show
  1. package/esm/shared/appTypes.d.ts +12 -6
  2. package/esm/shared/configTypes.d.ts +1 -3
  3. package/esm/shared/constants.d.ts +8 -0
  4. package/esm/shared/constants.js +8 -0
  5. package/esm/shared/htmlRenderer.d.ts +33 -0
  6. package/esm/shared/{serverTypes.js → htmlRenderer.js} +0 -0
  7. package/esm/shared/index.d.ts +2 -1
  8. package/esm/shared/index.js +2 -1
  9. package/esm/shared/renderTypes.d.ts +8 -7
  10. package/esm/shared/routeTypes.d.ts +4 -9
  11. package/esm/shuvi-app/app/client.d.ts +2 -1
  12. package/esm/shuvi-app/app/client.js +13 -17
  13. package/esm/shuvi-app/app/server.js +13 -9
  14. package/esm/shuvi-app/dev/eventsource.d.ts +1 -0
  15. package/esm/shuvi-app/dev/eventsource.js +60 -0
  16. package/esm/shuvi-app/dev/hotDevClient.d.ts +32 -0
  17. package/esm/shuvi-app/dev/hotDevClient.js +327 -0
  18. package/esm/shuvi-app/dev/index.d.ts +3 -0
  19. package/esm/shuvi-app/dev/index.js +27 -0
  20. package/esm/shuvi-app/dev/websocket.d.ts +16 -0
  21. package/esm/shuvi-app/dev/websocket.js +61 -0
  22. package/esm/shuvi-app/entry/client/app.d.ts +2 -1
  23. package/esm/shuvi-app/entry/client/app.js +13 -6
  24. package/esm/shuvi-app/entry/client/index.js +1 -1
  25. package/esm/shuvi-app/entry/client/run.dev.js +15 -16
  26. package/esm/shuvi-app/entry/server/index.d.ts +5 -4
  27. package/esm/shuvi-app/entry/server/index.js +5 -4
  28. package/esm/shuvi-app/helper/serializeServerError.d.ts +2 -0
  29. package/esm/shuvi-app/helper/serializeServerError.js +21 -0
  30. package/esm/shuvi-app/react/AppContainer.d.ts +4 -5
  31. package/esm/shuvi-app/react/AppContainer.jsx +4 -5
  32. package/esm/shuvi-app/react/ApplicationContext.d.ts +7 -0
  33. package/esm/shuvi-app/react/{applicationContext.jsx → ApplicationContext.jsx} +0 -0
  34. package/esm/shuvi-app/react/Error.jsx +4 -1
  35. package/esm/shuvi-app/react/Link.d.ts +2 -1
  36. package/esm/shuvi-app/react/Link.jsx +1 -1
  37. package/esm/shuvi-app/react/getRoutes.d.ts +2 -2
  38. package/esm/shuvi-app/react/getRoutes.js +9 -8
  39. package/esm/shuvi-app/react/{redox-react → model}/RedoxWrapper.d.ts +3 -3
  40. package/esm/shuvi-app/react/{redox-react → model}/RedoxWrapper.jsx +3 -3
  41. package/esm/shuvi-app/react/model/runtime.d.ts +8 -0
  42. package/esm/shuvi-app/react/{redox-react → model}/runtime.js +8 -3
  43. package/esm/shuvi-app/react/store.d.ts +5 -0
  44. package/esm/shuvi-app/react/store.js +3 -0
  45. package/esm/shuvi-app/react/types.d.ts +0 -7
  46. package/esm/shuvi-app/react/useLoaderData.js +9 -20
  47. package/esm/shuvi-app/react/view/ReactView.client.jsx +34 -23
  48. package/esm/shuvi-app/react/view/ReactView.server.jsx +29 -14
  49. package/esm/shuvi-app/react/view/render.d.ts +8 -0
  50. package/esm/shuvi-app/react/view/{render-action.js → render.js} +6 -6
  51. package/lib/node/features/custom-server/index.d.ts +1 -1
  52. package/lib/node/features/custom-server/server.d.ts +1 -1
  53. package/lib/node/features/custom-server/server.js +20 -11
  54. package/lib/node/features/filesystem-routes/api/apiRouteHandler.d.ts +7 -7
  55. package/lib/node/features/filesystem-routes/api/apiRouteHandler.js +5 -5
  56. package/lib/node/features/filesystem-routes/api/middleware.d.ts +2 -2
  57. package/lib/node/features/filesystem-routes/api/middleware.js +5 -2
  58. package/lib/node/features/filesystem-routes/hooks.d.ts +2 -1
  59. package/lib/node/features/filesystem-routes/hooks.js +2 -1
  60. package/lib/node/features/filesystem-routes/index.d.ts +1 -13
  61. package/lib/node/features/filesystem-routes/index.js +55 -84
  62. package/lib/node/features/filesystem-routes/middleware/middleware.d.ts +2 -2
  63. package/lib/node/features/filesystem-routes/middleware/middleware.js +5 -2
  64. package/lib/node/features/filesystem-routes/page/routes.d.ts +3 -3
  65. package/lib/node/features/filesystem-routes/page/routes.js +25 -12
  66. package/lib/node/features/html-render/index.d.ts +4 -18
  67. package/lib/node/features/html-render/index.js +129 -16
  68. package/lib/node/features/{main → html-render/lib}/buildHtml.d.ts +0 -0
  69. package/lib/node/features/{main → html-render/lib}/buildHtml.js +2 -1
  70. package/lib/node/features/html-render/lib/generateFilesByRoutId.d.ts +3 -3
  71. package/lib/node/features/html-render/lib/generateFilesByRoutId.js +3 -3
  72. package/lib/node/features/{main → html-render/lib}/generateResource.d.ts +0 -0
  73. package/lib/node/features/{main → html-render/lib}/generateResource.js +12 -8
  74. package/lib/node/features/html-render/lib/getPageMiddleware.d.ts +2 -2
  75. package/lib/node/features/html-render/lib/getPageMiddleware.js +18 -13
  76. package/lib/node/features/html-render/lib/index.d.ts +0 -2
  77. package/lib/node/features/html-render/lib/index.js +1 -4
  78. package/lib/node/features/html-render/lib/renderToHTML.d.ts +2 -2
  79. package/lib/node/features/html-render/lib/renderToHTML.js +9 -49
  80. package/lib/node/features/html-render/lib/renderer/base.d.ts +7 -8
  81. package/lib/node/features/html-render/lib/renderer/base.js +19 -11
  82. package/lib/node/features/html-render/lib/renderer/index.d.ts +5 -4
  83. package/lib/node/features/html-render/lib/renderer/index.js +77 -8
  84. package/lib/node/features/html-render/lib/renderer/spa.d.ts +2 -2
  85. package/lib/node/features/html-render/lib/renderer/spa.js +4 -6
  86. package/lib/node/features/html-render/lib/renderer/ssr.d.ts +2 -2
  87. package/lib/node/features/html-render/lib/renderer/ssr.js +9 -11
  88. package/lib/node/features/html-render/lib/renderer/types.d.ts +10 -8
  89. package/lib/node/features/html-render/lib/webpack/build-manifest-plugin.d.ts +27 -0
  90. package/lib/node/features/html-render/lib/webpack/build-manifest-plugin.js +223 -0
  91. package/lib/node/features/html-render/server.d.ts +1 -1
  92. package/lib/node/features/html-render/serverHooks.d.ts +6 -1
  93. package/lib/node/features/html-render/serverHooks.js +1 -2
  94. package/lib/node/features/index.d.ts +3 -31
  95. package/lib/node/features/index.js +6 -7
  96. package/lib/node/features/middlewares.d.ts +1 -1
  97. package/lib/node/features/middlewares.js +12 -3
  98. package/lib/node/features/model/index.d.ts +1 -13
  99. package/lib/node/features/model/runtime.d.ts +3 -8
  100. package/lib/node/features/model/runtime.js +13 -18
  101. package/lib/node/features/model/server.js +2 -3
  102. package/lib/node/features/model/shuvi-app.d.ts +2 -2
  103. package/lib/node/features/on-demand-compile-page/index.d.ts +3 -13
  104. package/lib/node/features/on-demand-compile-page/index.js +4 -1
  105. package/lib/node/features/on-demand-compile-page/onDemandRouteManager.d.ts +3 -3
  106. package/lib/node/features/on-demand-compile-page/onDemandRouteManager.js +4 -6
  107. package/lib/node/index.d.ts +1 -0
  108. package/lib/node/index.js +17 -5
  109. package/lib/node/paths.js +0 -2
  110. package/lib/node/shuvi-runtime-server.d.ts +26 -0
  111. package/lib/{shared/serverTypes.js → node/shuvi-runtime-server.js} +0 -0
  112. package/lib/node/shuvi-type-extensions-node.d.ts +20 -23
  113. package/lib/node/targets/react/bundler/index.d.ts +1 -13
  114. package/lib/node/targets/react/bundler/index.js +19 -13
  115. package/lib/node/targets/react/index.d.ts +2 -27
  116. package/lib/node/targets/react/index.js +3 -7
  117. package/lib/node/targets/react/model/index.d.ts +6 -0
  118. package/lib/node/targets/react/{redox-react → model}/index.js +7 -6
  119. package/lib/node/version.d.ts +1 -0
  120. package/lib/node/version.js +13 -0
  121. package/lib/shared/appTypes.d.ts +12 -6
  122. package/lib/shared/configTypes.d.ts +1 -3
  123. package/lib/shared/constants.d.ts +8 -0
  124. package/lib/shared/constants.js +15 -0
  125. package/lib/shared/htmlRenderer.d.ts +33 -0
  126. package/lib/shared/htmlRenderer.js +2 -0
  127. package/lib/shared/index.d.ts +2 -1
  128. package/lib/shared/index.js +2 -1
  129. package/lib/shared/renderTypes.d.ts +8 -7
  130. package/lib/shared/routeTypes.d.ts +4 -9
  131. package/package.json +40 -26
  132. package/polyfills/polyfills.js +1 -0
  133. package/shuvi-env.d.ts +10 -0
  134. package/shuvi-image.d.ts +54 -0
  135. package/shuvi-type-extensions-node.js +1 -0
  136. package/shuvi-type-extensions-runtime.d.ts +2 -2
  137. package/esm/shared/serverTypes.d.ts +0 -6
  138. package/esm/shuvi-app/dev/webpackHotDevClient.d.ts +0 -5
  139. package/esm/shuvi-app/dev/webpackHotDevClient.js +0 -34
  140. package/esm/shuvi-app/react/applicationContext.d.ts +0 -7
  141. package/esm/shuvi-app/react/redox-react/runtime.d.ts +0 -2
  142. package/esm/shuvi-app/react/view/render-action.d.ts +0 -10
  143. package/esm/shuvi-app/shuvi-runtime-index.d.ts +0 -4
  144. package/esm/shuvi-app/shuvi-runtime-index.js +0 -2
  145. package/esm/shuvi-app/shuvi-runtime-server.d.ts +0 -6
  146. package/esm/shuvi-app/shuvi-runtime-server.js +0 -1
  147. package/lib/node/features/html-render/lib/pageLoader.d.ts +0 -1
  148. package/lib/node/features/html-render/lib/pageLoader.js +0 -42
  149. package/lib/node/features/main/index.d.ts +0 -3
  150. package/lib/node/features/main/index.js +0 -82
  151. package/lib/node/targets/react/redox-react/index.d.ts +0 -18
  152. package/lib/shared/serverTypes.d.ts +0 -6
@@ -1,7 +1,8 @@
1
1
  /// <reference types="react" />
2
2
  import { LinkProps } from '@shuvi/router-react';
3
- export declare const Link: ({ prefetch, onMouseEnter, to, ref, ...rest }: LinkWrapperProps) => JSX.Element;
3
+ export declare const Link: ({ to, ref, prefetch, onMouseEnter, ...rest }: LinkWrapperProps) => JSX.Element;
4
4
  interface LinkWrapperProps extends LinkProps {
5
+ prefetch?: boolean;
5
6
  ref?: any;
6
7
  }
7
8
  export {};
@@ -71,7 +71,7 @@ const isAbsoluteUrl = (url) => {
71
71
  return ABSOLUTE_URL_REGEX.test(url);
72
72
  };
73
73
  export const Link = function LinkWithPrefetch(_a) {
74
- var { prefetch, onMouseEnter, to, ref } = _a, rest = __rest(_a, ["prefetch", "onMouseEnter", "to", "ref"]);
74
+ var { to, ref, prefetch, onMouseEnter } = _a, rest = __rest(_a, ["to", "ref", "prefetch", "onMouseEnter"]);
75
75
  const isHrefValid = typeof to === 'string' && !isAbsoluteUrl(to);
76
76
  const previousHref = React.useRef(to);
77
77
  const [setIntersectionRef, isVisible, resetVisible] = useIntersection({});
@@ -1,2 +1,2 @@
1
- import { IPageRouteRecord, IRawPageRouteRecord } from '@shuvi/platform-shared/shared';
2
- export default function getRoutes(routes: IRawPageRouteRecord[]): IPageRouteRecord[];
1
+ import { IPageRouteRecord } from '@shuvi/platform-shared/shared';
2
+ export default function getRoutes(routes: IPageRouteRecord[]): IPageRouteRecord[];
@@ -13,18 +13,19 @@ import { loadRouteComponent } from './loadRouteComponent';
13
13
  export default function getRoutes(routes) {
14
14
  const getRoutesWithRequire = (routes) => routes.map(x => {
15
15
  const originalRoute = Object.assign({}, x);
16
- const { __componentSource__, __componentSourceWithAffix__, __import__, __resolveWeak__, children } = originalRoute, rest = __rest(originalRoute, ["__componentSource__", "__componentSourceWithAffix__", "__import__", "__resolveWeak__", "children"]);
17
- const route = Object.assign({}, rest);
16
+ const { __componentRawRequest__, __import__, __resolveWeak__, children } = originalRoute, route = __rest(originalRoute, ["__componentRawRequest__", "__import__", "__resolveWeak__", "children"]);
18
17
  if (children) {
19
18
  route.children = getRoutesWithRequire(children);
20
19
  }
21
- if (__componentSourceWithAffix__ && __import__) {
22
- route.component = loadRouteComponent(__import__, {
23
- webpack: __resolveWeak__,
24
- modules: [__componentSourceWithAffix__]
25
- });
20
+ if (__import__) {
21
+ route.component = loadRouteComponent(__import__, Object.assign({ webpack: __resolveWeak__ }, (__componentRawRequest__ && {
22
+ modules: [__componentRawRequest__]
23
+ })));
26
24
  }
27
- return Object.assign({ __componentSourceWithAffix__, __resolveWeak__ }, route);
25
+ if (__componentRawRequest__) {
26
+ route.__componentRawRequest__ = __componentRawRequest__;
27
+ }
28
+ return route;
28
29
  });
29
30
  const routesWithRequire = getRoutesWithRequire(routes || []);
30
31
  return routesWithRequire;
@@ -1,8 +1,8 @@
1
1
  /// <reference types="react" />
2
- import type { IStoreManager } from '@shuvi/redox';
2
+ import type { RedoxStore } from '@shuvi/redox';
3
3
  export declare const RedoxWrapper: (App: any, appContext: {
4
- storeManager: IStoreManager;
4
+ store: RedoxStore;
5
5
  }) => {
6
- (appProps: any): JSX.Element;
6
+ (): JSX.Element;
7
7
  displayName: string;
8
8
  };
@@ -1,9 +1,9 @@
1
1
  import * as React from 'react';
2
2
  import { RedoxRoot } from '@shuvi/redox-react';
3
3
  export const RedoxWrapper = (App, appContext) => {
4
- function RedoxAppWrapper(appProps) {
5
- return (<RedoxRoot storeManager={appContext.storeManager}>
6
- <App {...appProps}/>
4
+ function RedoxAppWrapper() {
5
+ return (<RedoxRoot store={appContext.store}>
6
+ <App />
7
7
  </RedoxRoot>);
8
8
  }
9
9
  RedoxAppWrapper.displayName = 'RedoxAppWrapper';
@@ -0,0 +1,8 @@
1
+ import { RedoxStore } from '@shuvi/redox';
2
+ declare module '@shuvi/runtime' {
3
+ interface CustomAppContext {
4
+ store: RedoxStore;
5
+ }
6
+ }
7
+ declare const _default: import("@shuvi/platform-shared/shared").IPluginInstance<import("@shuvi/platform-shared/shared").RuntimePluginHooks, void>;
8
+ export default _default;
@@ -7,10 +7,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { createRuntimePlugin } from '@shuvi/platform-shared/shared';
10
+ import { createRuntimePluginAfter } from '@shuvi/platform-shared/shared';
11
11
  import { RedoxWrapper } from './RedoxWrapper';
12
- export default createRuntimePlugin({
12
+ // this needs to be run last
13
+ export default createRuntimePluginAfter({
13
14
  appComponent: (App, appContext) => __awaiter(void 0, void 0, void 0, function* () {
14
- return RedoxWrapper(App, appContext);
15
+ return RedoxWrapper(App, {
16
+ store: appContext.store
17
+ });
15
18
  })
19
+ }, {
20
+ name: 'model-react'
16
21
  });
@@ -0,0 +1,5 @@
1
+ /// <reference types="react" />
2
+ declare const Provider: (props: import("react").PropsWithChildren<{
3
+ store?: import("@shuvi/redox").RedoxStore | undefined;
4
+ }>) => JSX.Element, useSharedModel: import("@shuvi/redox-react/esm/types").IUseModel, useStaticModel: import("@shuvi/redox-react/esm/types").IUseStaticModel;
5
+ export { Provider, useSharedModel, useStaticModel };
@@ -0,0 +1,3 @@
1
+ import { createContainer } from '@shuvi/redox-react';
2
+ const { Provider, useSharedModel, useStaticModel } = createContainer();
3
+ export { Provider, useSharedModel, useStaticModel };
@@ -1,14 +1,7 @@
1
- import { IAppState } from '@shuvi/platform-shared/shared';
2
1
  import { IHtmlTag, IViewClient, IViewServer } from '../../shared';
3
2
  export { IHtmlTag };
4
3
  export declare type IReactAppData = {
5
- appProps?: Record<string, any>;
6
- errorProps?: {
7
- notFound: boolean;
8
- };
9
4
  dynamicIds?: Array<string | number>;
10
- appState?: IAppState;
11
- loadersData: any;
12
5
  };
13
6
  export declare type IReactServerView = IViewServer<IReactAppData>;
14
7
  export declare type IReactClientView = IViewClient<IReactAppData>;
@@ -1,27 +1,16 @@
1
1
  import { useMatchedRoute } from '@shuvi/router-react';
2
- import { getLoaderManager } from '@shuvi/platform-shared/shared';
3
- import { useRef, useEffect, useReducer } from 'react';
2
+ import { loaderModel } from '@shuvi/platform-shared/shared';
3
+ import { useStaticModel } from './store';
4
4
  export const noLoaderMessage = 'Warning: no loader found. Please make sure the page component where `useLoaderData` is called has a `loader` export.';
5
+ const hasOwn = Object.prototype.hasOwnProperty;
5
6
  export const useLoaderData = () => {
6
- var _a;
7
7
  const currentMatch = useMatchedRoute();
8
- const loaderManager = getLoaderManager();
9
- const id = (_a = currentMatch.route) === null || _a === void 0 ? void 0 : _a.id;
10
- const data = loaderManager.getData(id);
11
- if (data === null) {
8
+ const id = currentMatch.route.id;
9
+ // we don't need to watch the model change, cause it always change with
10
+ // matched route
11
+ const [state] = useStaticModel(loaderModel);
12
+ if (!hasOwn.call(state.current.dataByRouteId, id)) {
12
13
  throw Error(noLoaderMessage);
13
14
  }
14
- const dataRef = useRef(data);
15
- const [_, forceUpdate] = useReducer(state => state * -1, 1);
16
- useEffect(() => {
17
- const cancel = loaderManager.subscribe(() => {
18
- const newData = loaderManager.getData(id);
19
- if (newData !== data) {
20
- dataRef.current = newData;
21
- forceUpdate();
22
- }
23
- });
24
- return cancel;
25
- }, []);
26
- return dataRef.current;
15
+ return state.current.dataByRouteId[id];
27
16
  };
@@ -10,54 +10,65 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import * as React from 'react';
11
11
  import { SHUVI_ERROR } from '@shuvi/shared/lib/constants';
12
12
  import { Router } from '@shuvi/router-react';
13
+ import { getServerError } from '@shuvi/error-overlay';
13
14
  import AppContainer from '../AppContainer';
14
15
  import { HeadManager, HeadManagerContext } from '../head';
15
16
  import Loadable from '../loadable';
16
- import { renderAction } from './render-action';
17
+ import { doRender } from './render';
17
18
  const headManager = new HeadManager();
18
19
  export class ReactClientView {
19
20
  constructor() {
20
21
  this._isInitialRender = true;
21
22
  this.renderApp = ({ appContainer, app, appData }) => __awaiter(this, void 0, void 0, function* () {
22
23
  const { _isInitialRender: isInitialRender } = this;
23
- const { router, appComponent: AppComponent, error } = app;
24
- let { ssr, appProps, dynamicIds } = appData;
25
- // For e2e test
26
- if (window.__SHUVI) {
27
- window.__SHUVI.router = router;
28
- }
29
- else {
30
- window.__SHUVI = { router };
31
- }
24
+ const { router, appComponent: AppComponent, setError: setAppError, error: appError } = app;
25
+ let { ssr, dynamicIds } = appData;
26
+ const shouldHydrate = ssr && isInitialRender;
32
27
  const TypedAppComponent = AppComponent;
33
- if (ssr) {
34
- yield Loadable.preloadReady(dynamicIds);
35
- yield router.ready;
28
+ if (ssr && isInitialRender) {
29
+ if (process.env.NODE_ENV === 'development') {
30
+ if (appError && appError.source === 'server') {
31
+ setTimeout(() => {
32
+ var _a;
33
+ let error;
34
+ try {
35
+ // Generate a new error object. We `throw` it because some browsers
36
+ // will set the `stack` when thrown, and we want to ensure ours is
37
+ // not overridden when we re-throw it below.
38
+ throw new Error(appError.message);
39
+ }
40
+ catch (e) {
41
+ error = e;
42
+ }
43
+ error.name = (_a = appError.name) !== null && _a !== void 0 ? _a : '';
44
+ error.stack = appError.stack;
45
+ throw getServerError(error);
46
+ });
47
+ }
48
+ }
49
+ yield Promise.all([Loadable.preloadReady(dynamicIds), router.ready]);
36
50
  }
37
51
  else {
38
52
  yield router.ready;
39
53
  const { matches } = router.current;
40
54
  if (!matches.length) {
41
55
  // no handler no matches
42
- error.error(SHUVI_ERROR.PAGE_NOT_FOUND);
56
+ setAppError(SHUVI_ERROR.PAGE_NOT_FOUND);
43
57
  }
44
58
  }
45
59
  const root = (<Router router={router}>
46
60
  <AppContainer app={app}>
47
61
  <HeadManagerContext.Provider value={headManager.updateHead}>
48
- <TypedAppComponent {...appProps}/>
62
+ <TypedAppComponent />
49
63
  </HeadManagerContext.Provider>
50
64
  </AppContainer>
51
65
  </Router>);
52
- const ssrCallback = () => {
53
- this._isInitialRender = false;
54
- };
55
- renderAction({
56
- ssr,
57
- isInitialRender,
66
+ doRender({
58
67
  root,
59
- callback: ssrCallback,
60
- appContainer
68
+ appContainer,
69
+ shouldHydrate
70
+ }, () => {
71
+ this._isInitialRender = false;
61
72
  });
62
73
  });
63
74
  }
@@ -9,32 +9,31 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import * as React from 'react';
11
11
  import { renderToString } from 'react-dom/server';
12
- import { getLoaderManager, redirect } from '@shuvi/platform-shared/shared';
12
+ import { redirect } from '@shuvi/platform-shared/shared';
13
13
  import { SHUVI_ERROR } from '@shuvi/shared/lib/constants';
14
14
  import { Router } from '@shuvi/router-react';
15
+ import logger from '@shuvi/utils/lib/logger';
15
16
  import Loadable, { LoadableContext } from '../loadable';
16
17
  import AppContainer from '../AppContainer';
17
18
  import { Head } from '../head';
19
+ import { serializeServerError } from '../../helper/serializeServerError';
18
20
  export class ReactServerView {
19
21
  constructor() {
20
- this.renderApp = ({ app, manifest, getAssetPublicUrl }) => __awaiter(this, void 0, void 0, function* () {
22
+ this.renderApp = ({ req, app, manifest }) => __awaiter(this, void 0, void 0, function* () {
21
23
  yield Loadable.preloadAll();
22
- const { storeManager, router, error: appError, appComponent: AppComponent } = app;
24
+ const { router, appComponent: AppComponent, setError: setAppError } = app;
23
25
  yield router.ready;
24
26
  // todo: move these into renderer
25
27
  let { pathname, matches, redirected } = router.current;
26
28
  // handler no matches
27
29
  if (!matches.length) {
28
- appError.error(SHUVI_ERROR.PAGE_NOT_FOUND);
30
+ setAppError(SHUVI_ERROR.PAGE_NOT_FOUND);
29
31
  }
30
32
  if (redirected) {
31
33
  return redirect(pathname);
32
34
  }
33
- // todo: move loader into app, avoid using global module
34
- const loaderManager = getLoaderManager();
35
- const loadersData = yield loaderManager.getAllData();
36
35
  const loadableModules = [];
37
- let htmlContent;
36
+ let htmlContent = undefined;
38
37
  let head;
39
38
  const RootApp = (<Router static router={router}>
40
39
  <AppContainer app={app}>
@@ -46,8 +45,14 @@ export class ReactServerView {
46
45
  try {
47
46
  htmlContent = renderToString(RootApp);
48
47
  }
48
+ catch (error) {
49
+ if (process.env.NODE_ENV === 'development') {
50
+ logger.error(error.stack);
51
+ }
52
+ setAppError(serializeServerError(error));
53
+ htmlContent = renderToString(RootApp); // Consistency on both server and client side
54
+ }
49
55
  finally {
50
- loaderManager.clearAllData();
51
56
  head = Head.rewind() || [];
52
57
  }
53
58
  const { loadble } = manifest;
@@ -67,12 +72,24 @@ export class ReactServerView {
67
72
  const preloadDynamicChunks = [];
68
73
  const styles = [];
69
74
  for (const file of dynamicImportChunkSet) {
75
+ // Safari Bug: https://bugs.webkit.org/show_bug.cgi?id=187726
76
+ // If a request is preloaded, Safari will always retrieve it from the
77
+ // cache, regardless of the cache headers for that request.
78
+ // disable preload for safari on dev
79
+ if (process.env.NODE_ENV === 'development') {
80
+ const ua = req.headers['user-agent'] || '';
81
+ if (/safari/i.test(ua) && !/chrome/i.test(ua)) {
82
+ if (/\.js$/.test(file)) {
83
+ continue;
84
+ }
85
+ }
86
+ }
70
87
  if (/\.js$/.test(file)) {
71
88
  preloadDynamicChunks.push({
72
89
  tagName: 'link',
73
90
  attrs: {
74
91
  rel: 'preload',
75
- href: getAssetPublicUrl(file),
92
+ href: req.getAssetUrl(file),
76
93
  as: 'script'
77
94
  }
78
95
  });
@@ -82,19 +99,17 @@ export class ReactServerView {
82
99
  tagName: 'link',
83
100
  attrs: {
84
101
  rel: 'stylesheet',
85
- href: getAssetPublicUrl(file)
102
+ href: req.getAssetUrl(file)
86
103
  }
87
104
  });
88
105
  }
89
106
  }
90
107
  const appData = {
91
- dynamicIds: [...dynamicImportIdSet],
92
- loadersData
108
+ dynamicIds: [...dynamicImportIdSet]
93
109
  };
94
110
  if (dynamicImportIdSet.size) {
95
111
  appData.dynamicIds = Array.from(dynamicImportIdSet);
96
112
  }
97
- appData.appState = storeManager.getState();
98
113
  return {
99
114
  appData,
100
115
  content: htmlContent,
@@ -0,0 +1,8 @@
1
+ import { ReactNode } from 'react';
2
+ declare type RenderActionParam = {
3
+ appContainer: Element | Document;
4
+ root?: ReactNode;
5
+ shouldHydrate?: boolean;
6
+ };
7
+ declare let doRender: (options: RenderActionParam, callback: () => void) => void;
8
+ export { doRender };
@@ -1,9 +1,9 @@
1
- let renderAction;
1
+ let doRender;
2
2
  if (process.env.__SHUVI__AFTER__REACT__18__) {
3
3
  const { createRoot, hydrateRoot } = require('react-dom/client');
4
4
  let renderRoot;
5
- renderAction = ({ ssr, isInitialRender, root, callback, appContainer }) => {
6
- if (ssr && isInitialRender) {
5
+ doRender = ({ root, appContainer, shouldHydrate }, callback) => {
6
+ if (shouldHydrate) {
7
7
  renderRoot = hydrateRoot(appContainer, root);
8
8
  callback === null || callback === void 0 ? void 0 : callback();
9
9
  }
@@ -17,8 +17,8 @@ if (process.env.__SHUVI__AFTER__REACT__18__) {
17
17
  }
18
18
  else {
19
19
  const { hydrate, render } = require('react-dom');
20
- renderAction = ({ ssr, isInitialRender, root, callback, appContainer }) => {
21
- if (ssr && isInitialRender) {
20
+ doRender = ({ root, appContainer, shouldHydrate }, callback) => {
21
+ if (shouldHydrate) {
22
22
  hydrate(root, appContainer, callback);
23
23
  }
24
24
  else {
@@ -26,4 +26,4 @@ else {
26
26
  }
27
27
  };
28
28
  }
29
- export { renderAction };
29
+ export { doRender };
@@ -1,4 +1,4 @@
1
1
  declare const _default: {
2
- server: import("@shuvi/hook").IPluginInstance<import("@shuvi/service/lib/server/plugin").BuiltInServerPluginHooks & import("@shuvi/service/lib/server/pluginTypes").CustomServerPluginHooks, import("@shuvi/service").IServerPluginContext>;
2
+ server: import("@shuvi/hook").IPluginInstance<import("@shuvi/service/lib/server/plugin").ServerPluginHooks, import("@shuvi/service").IServerPluginContext>;
3
3
  };
4
4
  export default _default;
@@ -1,2 +1,2 @@
1
- declare const _default: import("@shuvi/hook").IPluginInstance<import("@shuvi/service/lib/server/plugin").BuiltInServerPluginHooks & import("@shuvi/service/lib/server/pluginTypes").CustomServerPluginHooks, import("@shuvi/service").IServerPluginContext>;
1
+ declare const _default: import("@shuvi/hook").IPluginInstance<import("@shuvi/service/lib/server/plugin").ServerPluginHooks, import("@shuvi/service").IServerPluginContext>;
2
2
  export default _default;
@@ -8,21 +8,30 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
12
15
  const service_1 = require("@shuvi/service");
13
- const resources_1 = require("@shuvi/service/lib/resources");
16
+ const resources_1 = __importDefault(require("@shuvi/service/lib/resources"));
17
+ const logger_1 = __importDefault(require("@shuvi/utils/lib/logger"));
18
+ let isWarnedhandlePageRequest = false;
14
19
  exports.default = (0, service_1.createServerPlugin)({
15
- getPageData: (appContext, context) => {
16
- var _a, _b;
17
- return ((_b = (_a = resources_1.server === null || resources_1.server === void 0 ? void 0 : resources_1.server.server) === null || _a === void 0 ? void 0 : _a.getPageData) === null || _b === void 0 ? void 0 : _b.call(_a, appContext, context)) || {};
20
+ getPageData: appContext => {
21
+ var _a, _b, _c;
22
+ return ((_c = (_b = (_a = resources_1.default.server) === null || _a === void 0 ? void 0 : _a.server) === null || _b === void 0 ? void 0 : _b.getPageData) === null || _c === void 0 ? void 0 : _c.call(_b, appContext)) || {};
18
23
  },
19
- handlePageRequest: (originalHandlePageRequest, context) => {
20
- var _a, _b;
21
- return (((_b = (_a = resources_1.server === null || resources_1.server === void 0 ? void 0 : resources_1.server.server) === null || _a === void 0 ? void 0 : _a.handlePageRequest) === null || _b === void 0 ? void 0 : _b.call(_a, originalHandlePageRequest, context)) ||
22
- originalHandlePageRequest);
24
+ handlePageRequest: originalHandlePageRequest => {
25
+ var _a, _b, _c, _d, _e;
26
+ if (!isWarnedhandlePageRequest &&
27
+ ((_b = (_a = resources_1.default.server) === null || _a === void 0 ? void 0 : _a.server) === null || _b === void 0 ? void 0 : _b.handlePageRequest) !== undefined) {
28
+ isWarnedhandlePageRequest = true;
29
+ logger_1.default.warn('Warning: handlePageRequest is an experimental feature, please use with caution.');
30
+ }
31
+ return (((_e = (_d = (_c = resources_1.default.server) === null || _c === void 0 ? void 0 : _c.server) === null || _d === void 0 ? void 0 : _d.handlePageRequest) === null || _e === void 0 ? void 0 : _e.call(_d, originalHandlePageRequest)) || originalHandlePageRequest);
23
32
  },
24
- modifyHtml: (document, context, pluginContext) => __awaiter(void 0, void 0, void 0, function* () {
25
- var _a, _b;
26
- yield ((_b = (_a = resources_1.server === null || resources_1.server === void 0 ? void 0 : resources_1.server.server) === null || _a === void 0 ? void 0 : _a.modifyHtml) === null || _b === void 0 ? void 0 : _b.call(_a, document, context, pluginContext));
33
+ modifyHtml: (document, context) => __awaiter(void 0, void 0, void 0, function* () {
34
+ var _a, _b, _c;
35
+ yield ((_c = (_b = (_a = resources_1.default.server) === null || _a === void 0 ? void 0 : _a.server) === null || _b === void 0 ? void 0 : _b.modifyHtml) === null || _c === void 0 ? void 0 : _c.call(_b, document, context));
27
36
  })
28
37
  });
@@ -1,14 +1,14 @@
1
1
  /// <reference types="node" />
2
2
  import { IncomingMessage } from 'http';
3
- import { IResponse, IRequest } from '@shuvi/service';
3
+ import { ShuviRequest, ShuviResponse } from '@shuvi/service';
4
4
  import { IApiRequestHandler, IApiResponse } from '../../../../shared';
5
5
  export { IApiRequestHandler };
6
- export declare function apiRouteHandler(req: IRequest, res: IResponse, resolver: IApiRequestHandler, apiRoutesConfig: any): Promise<void>;
6
+ export declare function apiRouteHandler(req: ShuviRequest, res: ShuviResponse, resolver: IApiRequestHandler, apiRoutesConfig: any): Promise<void>;
7
7
  /**
8
8
  * Parse incoming message like `json` or `urlencoded`
9
9
  * @param req request object
10
10
  */
11
- export declare function parseBody(req: IRequest, limit: string | number): Promise<any>;
11
+ export declare function parseBody(req: ShuviRequest, limit: string | number): Promise<any>;
12
12
  /**
13
13
  * Parse cookies from `req` header
14
14
  * @param req request object
@@ -21,27 +21,27 @@ export declare function getCookieParser(req: IncomingMessage): {
21
21
  * @param res ServerResponse object
22
22
  * @param statusCode `HTTP` status code of response
23
23
  */
24
- export declare function sendStatusCode<IRes extends IApiResponse>(res: IResponse, statusCode: number): IRes;
24
+ export declare function sendStatusCode<IRes extends IApiResponse>(res: ShuviResponse, statusCode: number): IRes;
25
25
  /**
26
26
  *
27
27
  * @param res response object
28
28
  * @param [statusOrUrl] `HTTP` status code of redirect
29
29
  * @param url URL of redirect
30
30
  */
31
- export declare function redirect<IRes extends IApiResponse>(res: IResponse, statusOrUrl: string | number, url?: string): IRes;
31
+ export declare function redirect<IRes extends IApiResponse>(res: ShuviResponse, statusOrUrl: string | number, url?: string): IRes;
32
32
  /**
33
33
  * Send `any` body to response
34
34
  * @param req request object
35
35
  * @param res response object
36
36
  * @param body of response
37
37
  */
38
- export declare function sendData(req: IRequest, res: IResponse, body: any): void;
38
+ export declare function sendData(req: ShuviRequest, res: ShuviResponse, body: any): void;
39
39
  /**
40
40
  * Send `JSON` object
41
41
  * @param res response object
42
42
  * @param jsonBody of data
43
43
  */
44
- export declare function sendJson(req: IRequest, res: IResponse, jsonBody: any): void;
44
+ export declare function sendJson(req: ShuviRequest, res: ShuviResponse, jsonBody: any): void;
45
45
  /**
46
46
  * Custom error class
47
47
  */
@@ -31,6 +31,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
31
31
  step((generator = generator.apply(thisArg, _arguments || [])).next());
32
32
  });
33
33
  };
34
+ var __importDefault = (this && this.__importDefault) || function (mod) {
35
+ return (mod && mod.__esModule) ? mod : { "default": mod };
36
+ };
34
37
  Object.defineProperty(exports, "__esModule", { value: true });
35
38
  exports.ApiError = exports.sendJson = exports.sendData = exports.redirect = exports.sendStatusCode = exports.getCookieParser = exports.parseBody = exports.apiRouteHandler = void 0;
36
39
  const stream_1 = require("stream");
@@ -38,15 +41,12 @@ const querystring = __importStar(require("querystring"));
38
41
  const cookie = __importStar(require("cookie"));
39
42
  const getRawBody = require('raw-body');
40
43
  const contentType = __importStar(require("content-type"));
44
+ const logger_1 = __importDefault(require("@shuvi/utils/lib/logger"));
41
45
  function apiRouteHandler(req, res, resolver, apiRoutesConfig) {
42
46
  return __awaiter(this, void 0, void 0, function* () {
43
47
  try {
44
48
  const { bodyParser } = apiRoutesConfig || {};
45
- const { pathname, query, params } = req;
46
49
  const apiReq = {
47
- pathname,
48
- query,
49
- params,
50
50
  // Parsing of cookies
51
51
  cookies: getCookieParser(req)
52
52
  };
@@ -70,7 +70,7 @@ function apiRouteHandler(req, res, resolver, apiRoutesConfig) {
70
70
  if (process.env.NODE_ENV !== 'production' &&
71
71
  !(res.finished || res.headersSent) &&
72
72
  !wasPiped) {
73
- console.warn(`API resolved without sending a response for ${req.url}, this may result in stalled requests.`);
73
+ logger_1.default.warn(`API resolved without sending a response for ${req.url}, this may result in stalled requests.`);
74
74
  }
75
75
  }
76
76
  catch (err) {
@@ -1,2 +1,2 @@
1
- import { IServerPluginContext, IRequestHandlerWithNext } from '@shuvi/service';
2
- export declare function middleware(_ctx: IServerPluginContext): IRequestHandlerWithNext;
1
+ import { IServerPluginContext, ShuviRequestHandler } from '@shuvi/service';
2
+ export declare function middleware(_ctx: IServerPluginContext): ShuviRequestHandler;
@@ -8,15 +8,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
12
15
  exports.middleware = void 0;
13
16
  const router_1 = require("@shuvi/router");
14
- const resources_1 = require("@shuvi/service/lib/resources");
17
+ const resources_1 = __importDefault(require("@shuvi/service/lib/resources"));
15
18
  const apiRouteHandler_1 = require("./apiRouteHandler");
16
19
  function middleware(_ctx) {
17
20
  return function (req, res, next) {
18
21
  return __awaiter(this, void 0, void 0, function* () {
19
- const { apiRoutes } = resources_1.server;
22
+ const { apiRoutes } = resources_1.default.server;
20
23
  let tempApiModule;
21
24
  for (const { path, api } of apiRoutes) {
22
25
  const match = (0, router_1.matchPathname)(path, req.pathname);
@@ -1,3 +1,4 @@
1
- import { IPageRouteConfig, IMiddlewareRouteConfig } from '@shuvi/platform-shared/shared';
1
+ import { IPageRouteConfig, IMiddlewareRouteConfig, IApiRouteConfig } from '@shuvi/platform-shared/shared';
2
2
  export declare const addRoutes: import("@shuvi/hook").AsyncParallelHook<void, void, IPageRouteConfig[]>;
3
3
  export declare const addMiddlewareRoutes: import("@shuvi/hook").AsyncParallelHook<void, void, IMiddlewareRouteConfig[]>;
4
+ export declare const addApiRoutes: import("@shuvi/hook").AsyncParallelHook<void, void, IApiRouteConfig[]>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.addMiddlewareRoutes = exports.addRoutes = void 0;
3
+ exports.addApiRoutes = exports.addMiddlewareRoutes = exports.addRoutes = void 0;
4
4
  const hook_1 = require("@shuvi/hook");
5
5
  exports.addRoutes = (0, hook_1.createAsyncParallelHook)();
6
6
  exports.addMiddlewareRoutes = (0, hook_1.createAsyncParallelHook)();
7
+ exports.addApiRoutes = (0, hook_1.createAsyncParallelHook)();
@@ -3,18 +3,6 @@ import { middleware as getMiddlewareMiddleware } from './middleware';
3
3
  import { IApiRequestHandler, middleware as getApiMiddleware } from './api';
4
4
  export { IApiRequestHandler, getRoutes, getMiddlewareMiddleware, getApiMiddleware };
5
5
  declare const _default: {
6
- core: import("@shuvi/platform-shared/shared").IPluginInstance<{
7
- extendConfig: import("@shuvi/hook").SyncWaterfallHook<import("@shuvi/service").Config, void>;
8
- afterInit: import("@shuvi/hook").AsyncParallelHook<void, void, void>;
9
- afterBuild: import("@shuvi/hook").AsyncParallelHook<void, void, void>;
10
- afterDestroy: import("@shuvi/hook").AsyncParallelHook<void, void, void>;
11
- afterBundlerDone: import("@shuvi/hook").AsyncParallelHook<import("@shuvi/service/lib/core/lifecycleTypes").BundlerDoneExtra, void, void>;
12
- afterBundlerTargetDone: import("@shuvi/hook").AsyncParallelHook<import("@shuvi/service/lib/core/lifecycleTypes").BundlerTargetDoneExtra, void, void>;
13
- configWebpack: import("@shuvi/hook").AsyncSeriesWaterfallHook<import("@shuvi/service/lib/core/lifecycleTypes").WebpackChainType, import("@shuvi/service/lib/core/lifecycleTypes").ConfigWebpackAssistant>;
14
- addExtraTarget: import("@shuvi/hook").AsyncParallelHook<import("@shuvi/service/lib/core/lifecycleTypes").ExtraTargetAssistant, void, import("@shuvi/service/lib/core/lifecycleTypes").TargetChain>;
15
- addResource: import("@shuvi/hook").AsyncParallelHook<void, void, import("@shuvi/service/lib/core/lifecycleTypes").Resources | import("@shuvi/service/lib/core/lifecycleTypes").Resources[]>;
16
- addRuntimeFile: import("@shuvi/hook").AsyncParallelHook<void, import("@shuvi/service/lib/core/lifecycleTypes").AddRuntimeFileUtils, import("@shuvi/service/lib/project/index").FileOptions<any, any> | import("@shuvi/service/lib/project/index").FileOptions<any, any>[]>;
17
- addRuntimeService: import("@shuvi/hook").AsyncParallelHook<void, void, import("@shuvi/service/lib/core/lifecycleTypes").RuntimeService | import("@shuvi/service/lib/core/lifecycleTypes").RuntimeService[]>;
18
- } & import("@shuvi/service/lib/core/apiTypes").CustomCorePluginHooks, import("@shuvi/service").IPluginContext>;
6
+ core: import("@shuvi/platform-shared/shared").IPluginInstance<import("@shuvi/service/lib/core/plugin").PluginHooks, import("@shuvi/service").IPluginContext>;
19
7
  };
20
8
  export default _default;