@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.
- package/esm/shared/appTypes.d.ts +12 -6
- package/esm/shared/configTypes.d.ts +1 -3
- package/esm/shared/constants.d.ts +8 -0
- package/esm/shared/constants.js +8 -0
- package/esm/shared/htmlRenderer.d.ts +33 -0
- package/esm/shared/{serverTypes.js → htmlRenderer.js} +0 -0
- package/esm/shared/index.d.ts +2 -1
- package/esm/shared/index.js +2 -1
- package/esm/shared/renderTypes.d.ts +8 -7
- package/esm/shared/routeTypes.d.ts +4 -9
- package/esm/shuvi-app/app/client.d.ts +2 -1
- package/esm/shuvi-app/app/client.js +13 -17
- package/esm/shuvi-app/app/server.js +13 -9
- package/esm/shuvi-app/dev/eventsource.d.ts +1 -0
- package/esm/shuvi-app/dev/eventsource.js +60 -0
- package/esm/shuvi-app/dev/hotDevClient.d.ts +32 -0
- package/esm/shuvi-app/dev/hotDevClient.js +327 -0
- package/esm/shuvi-app/dev/index.d.ts +3 -0
- package/esm/shuvi-app/dev/index.js +27 -0
- package/esm/shuvi-app/dev/websocket.d.ts +16 -0
- package/esm/shuvi-app/dev/websocket.js +61 -0
- package/esm/shuvi-app/entry/client/app.d.ts +2 -1
- package/esm/shuvi-app/entry/client/app.js +13 -6
- package/esm/shuvi-app/entry/client/index.js +1 -1
- package/esm/shuvi-app/entry/client/run.dev.js +15 -16
- package/esm/shuvi-app/entry/server/index.d.ts +5 -4
- package/esm/shuvi-app/entry/server/index.js +5 -4
- package/esm/shuvi-app/helper/serializeServerError.d.ts +2 -0
- package/esm/shuvi-app/helper/serializeServerError.js +21 -0
- package/esm/shuvi-app/react/AppContainer.d.ts +4 -5
- package/esm/shuvi-app/react/AppContainer.jsx +4 -5
- package/esm/shuvi-app/react/ApplicationContext.d.ts +7 -0
- package/esm/shuvi-app/react/{applicationContext.jsx → ApplicationContext.jsx} +0 -0
- package/esm/shuvi-app/react/Error.jsx +4 -1
- package/esm/shuvi-app/react/Link.d.ts +2 -1
- package/esm/shuvi-app/react/Link.jsx +1 -1
- package/esm/shuvi-app/react/getRoutes.d.ts +2 -2
- package/esm/shuvi-app/react/getRoutes.js +9 -8
- package/esm/shuvi-app/react/{redox-react → model}/RedoxWrapper.d.ts +3 -3
- package/esm/shuvi-app/react/{redox-react → model}/RedoxWrapper.jsx +3 -3
- package/esm/shuvi-app/react/model/runtime.d.ts +8 -0
- package/esm/shuvi-app/react/{redox-react → model}/runtime.js +8 -3
- package/esm/shuvi-app/react/store.d.ts +5 -0
- package/esm/shuvi-app/react/store.js +3 -0
- package/esm/shuvi-app/react/types.d.ts +0 -7
- package/esm/shuvi-app/react/useLoaderData.js +9 -20
- package/esm/shuvi-app/react/view/ReactView.client.jsx +34 -23
- package/esm/shuvi-app/react/view/ReactView.server.jsx +29 -14
- package/esm/shuvi-app/react/view/render.d.ts +8 -0
- package/esm/shuvi-app/react/view/{render-action.js → render.js} +6 -6
- package/lib/node/features/custom-server/index.d.ts +1 -1
- package/lib/node/features/custom-server/server.d.ts +1 -1
- package/lib/node/features/custom-server/server.js +20 -11
- package/lib/node/features/filesystem-routes/api/apiRouteHandler.d.ts +7 -7
- package/lib/node/features/filesystem-routes/api/apiRouteHandler.js +5 -5
- package/lib/node/features/filesystem-routes/api/middleware.d.ts +2 -2
- package/lib/node/features/filesystem-routes/api/middleware.js +5 -2
- package/lib/node/features/filesystem-routes/hooks.d.ts +2 -1
- package/lib/node/features/filesystem-routes/hooks.js +2 -1
- package/lib/node/features/filesystem-routes/index.d.ts +1 -13
- package/lib/node/features/filesystem-routes/index.js +55 -84
- package/lib/node/features/filesystem-routes/middleware/middleware.d.ts +2 -2
- package/lib/node/features/filesystem-routes/middleware/middleware.js +5 -2
- package/lib/node/features/filesystem-routes/page/routes.d.ts +3 -3
- package/lib/node/features/filesystem-routes/page/routes.js +25 -12
- package/lib/node/features/html-render/index.d.ts +4 -18
- package/lib/node/features/html-render/index.js +129 -16
- package/lib/node/features/{main → html-render/lib}/buildHtml.d.ts +0 -0
- package/lib/node/features/{main → html-render/lib}/buildHtml.js +2 -1
- package/lib/node/features/html-render/lib/generateFilesByRoutId.d.ts +3 -3
- package/lib/node/features/html-render/lib/generateFilesByRoutId.js +3 -3
- package/lib/node/features/{main → html-render/lib}/generateResource.d.ts +0 -0
- package/lib/node/features/{main → html-render/lib}/generateResource.js +12 -8
- package/lib/node/features/html-render/lib/getPageMiddleware.d.ts +2 -2
- package/lib/node/features/html-render/lib/getPageMiddleware.js +18 -13
- package/lib/node/features/html-render/lib/index.d.ts +0 -2
- package/lib/node/features/html-render/lib/index.js +1 -4
- package/lib/node/features/html-render/lib/renderToHTML.d.ts +2 -2
- package/lib/node/features/html-render/lib/renderToHTML.js +9 -49
- package/lib/node/features/html-render/lib/renderer/base.d.ts +7 -8
- package/lib/node/features/html-render/lib/renderer/base.js +19 -11
- package/lib/node/features/html-render/lib/renderer/index.d.ts +5 -4
- package/lib/node/features/html-render/lib/renderer/index.js +77 -8
- package/lib/node/features/html-render/lib/renderer/spa.d.ts +2 -2
- package/lib/node/features/html-render/lib/renderer/spa.js +4 -6
- package/lib/node/features/html-render/lib/renderer/ssr.d.ts +2 -2
- package/lib/node/features/html-render/lib/renderer/ssr.js +9 -11
- package/lib/node/features/html-render/lib/renderer/types.d.ts +10 -8
- package/lib/node/features/html-render/lib/webpack/build-manifest-plugin.d.ts +27 -0
- package/lib/node/features/html-render/lib/webpack/build-manifest-plugin.js +223 -0
- package/lib/node/features/html-render/server.d.ts +1 -1
- package/lib/node/features/html-render/serverHooks.d.ts +6 -1
- package/lib/node/features/html-render/serverHooks.js +1 -2
- package/lib/node/features/index.d.ts +3 -31
- package/lib/node/features/index.js +6 -7
- package/lib/node/features/middlewares.d.ts +1 -1
- package/lib/node/features/middlewares.js +12 -3
- package/lib/node/features/model/index.d.ts +1 -13
- package/lib/node/features/model/runtime.d.ts +3 -8
- package/lib/node/features/model/runtime.js +13 -18
- package/lib/node/features/model/server.js +2 -3
- package/lib/node/features/model/shuvi-app.d.ts +2 -2
- package/lib/node/features/on-demand-compile-page/index.d.ts +3 -13
- package/lib/node/features/on-demand-compile-page/index.js +4 -1
- package/lib/node/features/on-demand-compile-page/onDemandRouteManager.d.ts +3 -3
- package/lib/node/features/on-demand-compile-page/onDemandRouteManager.js +4 -6
- package/lib/node/index.d.ts +1 -0
- package/lib/node/index.js +17 -5
- package/lib/node/paths.js +0 -2
- package/lib/node/shuvi-runtime-server.d.ts +26 -0
- package/lib/{shared/serverTypes.js → node/shuvi-runtime-server.js} +0 -0
- package/lib/node/shuvi-type-extensions-node.d.ts +20 -23
- package/lib/node/targets/react/bundler/index.d.ts +1 -13
- package/lib/node/targets/react/bundler/index.js +19 -13
- package/lib/node/targets/react/index.d.ts +2 -27
- package/lib/node/targets/react/index.js +3 -7
- package/lib/node/targets/react/model/index.d.ts +6 -0
- package/lib/node/targets/react/{redox-react → model}/index.js +7 -6
- package/lib/node/version.d.ts +1 -0
- package/lib/node/version.js +13 -0
- package/lib/shared/appTypes.d.ts +12 -6
- package/lib/shared/configTypes.d.ts +1 -3
- package/lib/shared/constants.d.ts +8 -0
- package/lib/shared/constants.js +15 -0
- package/lib/shared/htmlRenderer.d.ts +33 -0
- package/lib/shared/htmlRenderer.js +2 -0
- package/lib/shared/index.d.ts +2 -1
- package/lib/shared/index.js +2 -1
- package/lib/shared/renderTypes.d.ts +8 -7
- package/lib/shared/routeTypes.d.ts +4 -9
- package/package.json +40 -26
- package/polyfills/polyfills.js +1 -0
- package/shuvi-env.d.ts +10 -0
- package/shuvi-image.d.ts +54 -0
- package/shuvi-type-extensions-node.js +1 -0
- package/shuvi-type-extensions-runtime.d.ts +2 -2
- package/esm/shared/serverTypes.d.ts +0 -6
- package/esm/shuvi-app/dev/webpackHotDevClient.d.ts +0 -5
- package/esm/shuvi-app/dev/webpackHotDevClient.js +0 -34
- package/esm/shuvi-app/react/applicationContext.d.ts +0 -7
- package/esm/shuvi-app/react/redox-react/runtime.d.ts +0 -2
- package/esm/shuvi-app/react/view/render-action.d.ts +0 -10
- package/esm/shuvi-app/shuvi-runtime-index.d.ts +0 -4
- package/esm/shuvi-app/shuvi-runtime-index.js +0 -2
- package/esm/shuvi-app/shuvi-runtime-server.d.ts +0 -6
- package/esm/shuvi-app/shuvi-runtime-server.js +0 -1
- package/lib/node/features/html-render/lib/pageLoader.d.ts +0 -1
- package/lib/node/features/html-render/lib/pageLoader.js +0 -42
- package/lib/node/features/main/index.d.ts +0 -3
- package/lib/node/features/main/index.js +0 -82
- package/lib/node/targets/react/redox-react/index.d.ts +0 -18
- 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: ({
|
|
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 {
|
|
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
|
|
2
|
-
export default function getRoutes(routes:
|
|
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 {
|
|
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 (
|
|
22
|
-
route.component = loadRouteComponent(__import__, {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
});
|
|
20
|
+
if (__import__) {
|
|
21
|
+
route.component = loadRouteComponent(__import__, Object.assign({ webpack: __resolveWeak__ }, (__componentRawRequest__ && {
|
|
22
|
+
modules: [__componentRawRequest__]
|
|
23
|
+
})));
|
|
26
24
|
}
|
|
27
|
-
|
|
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 {
|
|
2
|
+
import type { RedoxStore } from '@shuvi/redox';
|
|
3
3
|
export declare const RedoxWrapper: (App: any, appContext: {
|
|
4
|
-
|
|
4
|
+
store: RedoxStore;
|
|
5
5
|
}) => {
|
|
6
|
-
(
|
|
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(
|
|
5
|
-
return (<RedoxRoot
|
|
6
|
-
<App
|
|
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 {
|
|
10
|
+
import { createRuntimePluginAfter } from '@shuvi/platform-shared/shared';
|
|
11
11
|
import { RedoxWrapper } from './RedoxWrapper';
|
|
12
|
-
|
|
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,
|
|
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 };
|
|
@@ -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 {
|
|
3
|
-
import {
|
|
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
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
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 {
|
|
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,
|
|
25
|
-
|
|
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
|
-
|
|
35
|
-
|
|
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
|
-
|
|
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
|
|
62
|
+
<TypedAppComponent />
|
|
49
63
|
</HeadManagerContext.Provider>
|
|
50
64
|
</AppContainer>
|
|
51
65
|
</Router>);
|
|
52
|
-
|
|
53
|
-
this._isInitialRender = false;
|
|
54
|
-
};
|
|
55
|
-
renderAction({
|
|
56
|
-
ssr,
|
|
57
|
-
isInitialRender,
|
|
66
|
+
doRender({
|
|
58
67
|
root,
|
|
59
|
-
|
|
60
|
-
|
|
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 {
|
|
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
|
|
22
|
+
this.renderApp = ({ req, app, manifest }) => __awaiter(this, void 0, void 0, function* () {
|
|
21
23
|
yield Loadable.preloadAll();
|
|
22
|
-
const {
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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
|
|
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
|
-
|
|
6
|
-
if (
|
|
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
|
-
|
|
21
|
-
if (
|
|
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 {
|
|
29
|
+
export { doRender };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
declare const _default: {
|
|
2
|
-
server: import("@shuvi/hook").IPluginInstance<import("@shuvi/service/lib/server/plugin").
|
|
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").
|
|
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:
|
|
16
|
-
var _a, _b;
|
|
17
|
-
return ((_b = (_a = resources_1.server === null ||
|
|
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:
|
|
20
|
-
var _a, _b;
|
|
21
|
-
|
|
22
|
-
|
|
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
|
|
25
|
-
var _a, _b;
|
|
26
|
-
yield ((_b = (_a = resources_1.server === null ||
|
|
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 {
|
|
3
|
+
import { ShuviRequest, ShuviResponse } from '@shuvi/service';
|
|
4
4
|
import { IApiRequestHandler, IApiResponse } from '../../../../shared';
|
|
5
5
|
export { IApiRequestHandler };
|
|
6
|
-
export declare function apiRouteHandler(req:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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,
|
|
2
|
-
export declare function middleware(_ctx: IServerPluginContext):
|
|
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;
|