@shuvi/platform-web 0.0.1-rc.34 → 1.0.0-rc.2
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 +15 -0
- package/esm/shared/appTypes.js +1 -0
- package/esm/shared/configTypes.d.ts +14 -0
- package/esm/shared/configTypes.js +1 -0
- package/esm/shared/index.d.ts +5 -0
- package/esm/shared/index.js +5 -0
- package/esm/shared/renderTypes.d.ts +44 -0
- package/esm/shared/renderTypes.js +1 -0
- package/esm/shared/routeTypes.d.ts +47 -0
- package/esm/shared/routeTypes.js +1 -0
- package/esm/shared/serverTypes.d.ts +6 -0
- package/esm/shared/serverTypes.js +1 -0
- package/esm/shuvi-app/app/client.d.ts +2 -0
- package/esm/shuvi-app/app/client.js +125 -0
- package/esm/shuvi-app/app/server.d.ts +2 -0
- package/esm/shuvi-app/app/server.js +67 -0
- package/{shuvi-app → esm/shuvi-app}/dev/webpackHotDevClient.d.ts +0 -0
- package/{shuvi-app → esm/shuvi-app}/dev/webpackHotDevClient.js +2 -1
- package/esm/shuvi-app/entry/client/app.d.ts +2 -0
- package/esm/shuvi-app/entry/client/app.js +57 -0
- package/esm/shuvi-app/entry/client/index.d.ts +2 -0
- package/esm/shuvi-app/entry/client/index.js +12 -0
- package/{shuvi-app → esm/shuvi-app}/entry/client/run.dev.d.ts +0 -0
- package/{shuvi-app → esm/shuvi-app}/entry/client/run.dev.js +2 -2
- package/{shuvi-app → esm/shuvi-app}/entry/client/run.prod.d.ts +0 -0
- package/esm/shuvi-app/entry/client/run.prod.js +3 -0
- package/{shuvi-app → esm/shuvi-app}/entry/client/setup-env.d.ts +1 -1
- package/esm/shuvi-app/entry/client/setup-env.js +17 -0
- package/esm/shuvi-app/entry/server/index.d.ts +6 -0
- package/esm/shuvi-app/entry/server/index.js +7 -0
- package/esm/shuvi-app/react/AppComponent.d.ts +4 -0
- package/esm/shuvi-app/react/AppComponent.jsx +6 -0
- package/esm/shuvi-app/react/AppContainer.d.ts +6 -0
- package/esm/shuvi-app/react/AppContainer.jsx +23 -0
- package/esm/shuvi-app/react/Error.d.ts +5 -0
- package/esm/shuvi-app/react/Error.jsx +38 -0
- package/esm/shuvi-app/react/ErrorBoundary.d.ts +16 -0
- package/esm/shuvi-app/react/ErrorBoundary.jsx +25 -0
- package/esm/shuvi-app/react/ErrorPage.d.ts +5 -0
- package/esm/shuvi-app/react/ErrorPage.jsx +7 -0
- package/esm/shuvi-app/react/Link.d.ts +7 -0
- package/esm/shuvi-app/react/Link.jsx +115 -0
- package/esm/shuvi-app/react/applicationContext.d.ts +7 -0
- package/esm/shuvi-app/react/applicationContext.jsx +10 -0
- package/esm/shuvi-app/react/dynamic.d.ts +31 -0
- package/esm/shuvi-app/react/dynamic.jsx +62 -0
- package/esm/shuvi-app/react/getRoutes.d.ts +2 -0
- package/esm/shuvi-app/react/getRoutes.js +31 -0
- package/esm/shuvi-app/react/head/head-manager-context.d.ts +2 -0
- package/esm/shuvi-app/react/head/head-manager-context.js +2 -0
- package/esm/shuvi-app/react/head/head-manager.d.ts +10 -0
- package/esm/shuvi-app/react/head/head-manager.js +93 -0
- package/esm/shuvi-app/react/head/head.d.ts +33 -0
- package/esm/shuvi-app/react/head/head.jsx +178 -0
- package/esm/shuvi-app/react/head/index.d.ts +4 -0
- package/esm/shuvi-app/react/head/index.js +4 -0
- package/esm/shuvi-app/react/head/side-effect.d.ts +30 -0
- package/esm/shuvi-app/react/head/side-effect.jsx +44 -0
- package/esm/shuvi-app/react/head/types.d.ts +15 -0
- package/esm/shuvi-app/react/head/types.js +1 -0
- package/esm/shuvi-app/react/index.d.ts +4 -0
- package/esm/shuvi-app/react/index.js +4 -0
- package/esm/shuvi-app/react/loadRouteComponent.d.ts +4 -0
- package/esm/shuvi-app/react/loadRouteComponent.jsx +9 -0
- package/esm/shuvi-app/react/loadable/index.d.ts +2 -0
- package/esm/shuvi-app/react/loadable/index.js +2 -0
- package/esm/shuvi-app/react/loadable/loadable-context.d.ts +4 -0
- package/esm/shuvi-app/react/loadable/loadable-context.js +3 -0
- package/esm/shuvi-app/react/loadable/loadable.d.ts +30 -0
- package/esm/shuvi-app/react/loadable/loadable.js +277 -0
- package/esm/shuvi-app/react/redox-react/RedoxWrapper.d.ts +8 -0
- package/esm/shuvi-app/react/redox-react/RedoxWrapper.jsx +11 -0
- package/esm/shuvi-app/react/redox-react/runtime.d.ts +2 -0
- package/esm/shuvi-app/react/redox-react/runtime.js +16 -0
- package/esm/shuvi-app/react/shuvi-runtime-api.d.ts +5 -0
- package/esm/shuvi-app/react/shuvi-runtime-api.js +5 -0
- package/esm/shuvi-app/react/types.d.ts +14 -0
- package/esm/shuvi-app/react/types.js +1 -0
- package/esm/shuvi-app/react/useLoaderData.d.ts +2 -0
- package/esm/shuvi-app/react/useLoaderData.js +27 -0
- package/esm/shuvi-app/react/utils/getDisplayName.d.ts +2 -0
- package/esm/shuvi-app/react/utils/getDisplayName.js +3 -0
- package/esm/shuvi-app/react/utils/requestIdleCallback.d.ts +2 -0
- package/esm/shuvi-app/react/utils/requestIdleCallback.js +20 -0
- package/esm/shuvi-app/react/utils/useIntersection.d.ts +8 -0
- package/esm/shuvi-app/react/utils/useIntersection.jsx +91 -0
- package/esm/shuvi-app/react/view/ReactView.client.d.ts +5 -0
- package/esm/shuvi-app/react/view/ReactView.client.jsx +64 -0
- package/esm/shuvi-app/react/view/ReactView.server.d.ts +4 -0
- package/esm/shuvi-app/react/view/ReactView.server.jsx +109 -0
- package/esm/shuvi-app/react/view/clientView.d.ts +3 -0
- package/esm/shuvi-app/react/view/clientView.js +2 -0
- package/esm/shuvi-app/react/view/index.d.ts +2 -0
- package/esm/shuvi-app/react/view/index.js +7 -0
- package/esm/shuvi-app/react/view/render-action.d.ts +10 -0
- package/esm/shuvi-app/react/view/render-action.js +29 -0
- package/esm/shuvi-app/react/view/serverView.d.ts +3 -0
- package/esm/shuvi-app/react/view/serverView.js +2 -0
- package/esm/shuvi-app/react/view/transformRoutes.d.ts +2 -0
- package/esm/shuvi-app/react/view/transformRoutes.js +3 -0
- package/esm/shuvi-app/shuvi-runtime-index.d.ts +4 -0
- package/esm/shuvi-app/shuvi-runtime-index.js +2 -0
- package/esm/shuvi-app/shuvi-runtime-server.d.ts +6 -0
- package/esm/shuvi-app/shuvi-runtime-server.js +1 -0
- package/lib/node/features/custom-server/index.d.ts +4 -0
- package/lib/node/features/custom-server/index.js +9 -0
- package/lib/node/features/custom-server/server.d.ts +2 -0
- package/lib/node/features/custom-server/server.js +28 -0
- package/lib/node/features/filesystem-routes/api/apiRouteHandler.d.ts +51 -0
- package/lib/node/features/filesystem-routes/api/apiRouteHandler.js +237 -0
- package/lib/node/features/filesystem-routes/api/apiRoutes.d.ts +7 -0
- package/lib/node/features/filesystem-routes/api/apiRoutes.js +35 -0
- package/lib/node/features/filesystem-routes/api/index.d.ts +3 -0
- package/lib/node/features/filesystem-routes/api/index.js +7 -0
- package/lib/node/features/filesystem-routes/api/middleware.d.ts +2 -0
- package/lib/node/features/filesystem-routes/api/middleware.js +44 -0
- package/lib/node/features/filesystem-routes/hooks.d.ts +3 -0
- package/lib/node/features/filesystem-routes/hooks.js +6 -0
- package/lib/node/features/filesystem-routes/index.d.ts +20 -0
- package/lib/node/features/filesystem-routes/index.js +180 -0
- package/lib/node/features/filesystem-routes/middleware/index.d.ts +2 -0
- package/lib/node/features/filesystem-routes/middleware/index.js +7 -0
- package/lib/node/features/filesystem-routes/middleware/middleware.d.ts +2 -0
- package/lib/node/features/filesystem-routes/middleware/middleware.js +42 -0
- package/lib/node/features/filesystem-routes/middleware/routes.d.ts +9 -0
- package/lib/node/features/filesystem-routes/middleware/routes.js +34 -0
- package/lib/node/features/filesystem-routes/page/index.d.ts +2 -0
- package/lib/node/features/filesystem-routes/page/index.js +21 -0
- package/lib/node/features/filesystem-routes/page/routes.d.ts +8 -0
- package/lib/node/features/filesystem-routes/page/routes.js +83 -0
- package/lib/node/features/filesystem-routes/page/store.d.ts +3 -0
- package/lib/node/features/filesystem-routes/page/store.js +10 -0
- package/lib/node/features/html-render/index.d.ts +19 -0
- package/lib/node/features/html-render/index.js +28 -0
- package/lib/node/features/html-render/lib/generateFilesByRoutId.d.ts +3 -0
- package/lib/node/features/html-render/lib/generateFilesByRoutId.js +13 -0
- package/lib/node/features/html-render/lib/getPageMiddleware.d.ts +2 -0
- package/lib/node/features/html-render/lib/getPageMiddleware.js +56 -0
- package/lib/node/features/html-render/lib/index.d.ts +4 -0
- package/lib/node/features/html-render/lib/index.js +23 -0
- package/lib/node/features/html-render/lib/pageLoader.d.ts +1 -0
- package/lib/node/features/html-render/lib/pageLoader.js +42 -0
- package/lib/node/features/html-render/lib/renderToHTML.d.ts +6 -0
- package/lib/node/features/html-render/lib/renderToHTML.js +81 -0
- package/lib/node/features/html-render/lib/renderer/base.d.ts +17 -0
- package/lib/node/features/html-render/lib/renderer/base.js +70 -0
- package/lib/node/features/html-render/lib/renderer/htmlTag.d.ts +4 -0
- package/lib/node/features/html-render/lib/renderer/htmlTag.js +70 -0
- package/lib/node/features/html-render/lib/renderer/index.d.ts +15 -0
- package/lib/node/features/html-render/lib/renderer/index.js +48 -0
- package/lib/node/features/html-render/lib/renderer/spa.d.ts +5 -0
- package/lib/node/features/html-render/lib/renderer/spa.js +26 -0
- package/lib/node/features/html-render/lib/renderer/ssr.d.ts +5 -0
- package/lib/node/features/html-render/lib/renderer/ssr.js +70 -0
- package/lib/node/features/html-render/lib/renderer/types.d.ts +20 -0
- package/lib/node/features/html-render/lib/renderer/types.js +2 -0
- package/lib/node/features/html-render/lib/viewTemplate.d.ts +5 -0
- package/lib/node/features/html-render/lib/viewTemplate.js +37 -0
- package/lib/node/features/html-render/server.d.ts +2 -0
- package/lib/node/features/html-render/server.js +9 -0
- package/lib/node/features/html-render/serverHooks.d.ts +10 -0
- package/lib/node/features/html-render/serverHooks.js +13 -0
- package/lib/node/features/html-render/shuvi-app.d.ts +6 -0
- package/lib/node/features/html-render/shuvi-app.js +2 -0
- package/lib/node/features/index.d.ts +32 -0
- package/lib/node/features/index.js +25 -0
- package/lib/node/features/main/buildHtml.d.ts +8 -0
- package/lib/node/features/main/buildHtml.js +64 -0
- package/lib/node/features/main/generateResource.d.ts +3 -0
- package/lib/node/features/main/generateResource.js +56 -0
- package/lib/node/features/main/index.d.ts +3 -0
- package/lib/node/features/main/index.js +82 -0
- package/lib/node/features/middlewares.d.ts +4 -0
- package/lib/node/features/middlewares.js +23 -0
- package/lib/node/features/model/index.d.ts +21 -0
- package/lib/node/features/model/index.js +54 -0
- package/lib/node/features/model/runtime.d.ts +13 -0
- package/lib/node/features/model/runtime.js +47 -0
- package/lib/node/features/model/server.d.ts +3 -0
- package/lib/node/features/model/server.js +12 -0
- package/lib/node/features/model/shuvi-app.d.ts +6 -0
- package/lib/node/features/model/shuvi-app.js +2 -0
- package/lib/node/features/on-demand-compile-page/emptyComponent.d.ts +1 -0
- package/lib/node/features/on-demand-compile-page/emptyComponent.js +7 -0
- package/lib/node/features/on-demand-compile-page/index.d.ts +15 -0
- package/lib/node/features/on-demand-compile-page/index.js +36 -0
- package/lib/node/features/on-demand-compile-page/onDemandRouteManager.d.ts +11 -0
- package/lib/node/features/on-demand-compile-page/onDemandRouteManager.js +104 -0
- package/lib/node/index.d.ts +6 -0
- package/lib/node/index.js +38 -0
- package/lib/{paths.d.ts → node/paths.d.ts} +1 -2
- package/lib/node/paths.js +36 -0
- package/lib/node/shuvi-type-extensions-node.d.ts +42 -0
- package/lib/node/shuvi-type-extensions-node.js +3 -0
- package/lib/node/targets/react/bundler/index.d.ts +16 -0
- package/lib/node/targets/react/bundler/index.js +102 -0
- package/lib/node/targets/react/index.d.ts +32 -0
- package/lib/node/targets/react/index.js +28 -0
- package/lib/node/targets/react/redox-react/index.d.ts +18 -0
- package/lib/node/targets/react/redox-react/index.js +50 -0
- package/lib/shared/appTypes.d.ts +15 -0
- package/lib/shared/appTypes.js +2 -0
- package/lib/shared/configTypes.d.ts +14 -0
- package/lib/shared/configTypes.js +2 -0
- package/lib/shared/index.d.ts +5 -0
- package/lib/shared/index.js +21 -0
- package/lib/shared/renderTypes.d.ts +44 -0
- package/lib/shared/renderTypes.js +2 -0
- package/lib/shared/routeTypes.d.ts +47 -0
- package/lib/shared/routeTypes.js +2 -0
- package/lib/shared/serverTypes.d.ts +6 -0
- package/lib/shared/serverTypes.js +2 -0
- package/package.json +78 -15
- package/shuvi-type-extensions-node.d.ts +2 -0
- package/shuvi-type-extensions-runtime.d.ts +36 -0
- package/lib/index.d.ts +0 -3
- package/lib/index.js +0 -44
- package/lib/paths.js +0 -7
- package/shuvi-app/application/client/create-application-factory.d.ts +0 -3
- package/shuvi-app/application/client/create-application-factory.js +0 -70
- package/shuvi-app/application/client/create-application-history-browser.d.ts +0 -1
- package/shuvi-app/application/client/create-application-history-browser.js +0 -3
- package/shuvi-app/application/client/create-application-history-hash.d.ts +0 -1
- package/shuvi-app/application/client/create-application-history-hash.js +0 -3
- package/shuvi-app/application/client/create-application-history-memory.d.ts +0 -1
- package/shuvi-app/application/client/create-application-history-memory.js +0 -3
- package/shuvi-app/application/server/create-application-spa.d.ts +0 -2
- package/shuvi-app/application/server/create-application-spa.js +0 -8
- package/shuvi-app/application/server/create-application.d.ts +0 -2
- package/shuvi-app/application/server/create-application.js +0 -25
- package/shuvi-app/entry/client/index.d.ts +0 -1
- package/shuvi-app/entry/client/index.js +0 -11
- package/shuvi-app/entry/client/run.prod.js +0 -3
- package/shuvi-app/entry/client/setup-app.d.ts +0 -3
- package/shuvi-app/entry/client/setup-app.js +0 -38
- package/shuvi-app/entry/client/setup-env.js +0 -27
- package/shuvi-app/entry/server/index.d.ts +0 -6
- package/shuvi-app/entry/server/index.js +0 -7
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { requestIdleCallback, cancelIdleCallback } from './requestIdleCallback';
|
|
3
|
+
const hasIntersectionObserver = typeof IntersectionObserver !== 'undefined';
|
|
4
|
+
export default function useIntersection({ rootRef, rootMargin = '0px', disabled }) {
|
|
5
|
+
const isDisabled = disabled || !hasIntersectionObserver;
|
|
6
|
+
const unobserve = useRef();
|
|
7
|
+
const [visible, setVisible] = useState(false);
|
|
8
|
+
const [root, setRoot] = useState(rootRef ? rootRef.current : null);
|
|
9
|
+
const setRef = useCallback((el) => {
|
|
10
|
+
if (unobserve.current) {
|
|
11
|
+
unobserve.current();
|
|
12
|
+
unobserve.current = undefined;
|
|
13
|
+
}
|
|
14
|
+
if (isDisabled || visible)
|
|
15
|
+
return;
|
|
16
|
+
if (el && el.tagName) {
|
|
17
|
+
unobserve.current = observe(el, isVisible => isVisible && setVisible(isVisible), { root, rootMargin });
|
|
18
|
+
}
|
|
19
|
+
}, [isDisabled, root, rootMargin, visible]);
|
|
20
|
+
const resetVisible = useCallback(() => {
|
|
21
|
+
setVisible(false);
|
|
22
|
+
}, []);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (!hasIntersectionObserver) {
|
|
25
|
+
if (!visible) {
|
|
26
|
+
const idleCallback = requestIdleCallback(() => setVisible(true));
|
|
27
|
+
return () => cancelIdleCallback(idleCallback);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return () => { };
|
|
31
|
+
}, [visible]);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (rootRef)
|
|
34
|
+
setRoot(rootRef.current);
|
|
35
|
+
}, [rootRef]);
|
|
36
|
+
return [setRef, visible, resetVisible];
|
|
37
|
+
}
|
|
38
|
+
function observe(element, callback, options) {
|
|
39
|
+
const { id, observer, elements } = createObserver(options);
|
|
40
|
+
elements.set(element, callback);
|
|
41
|
+
observer.observe(element);
|
|
42
|
+
return function unobserve() {
|
|
43
|
+
elements.delete(element);
|
|
44
|
+
observer.unobserve(element);
|
|
45
|
+
// Destroy observer when there's nothing left to watch:
|
|
46
|
+
if (elements.size === 0) {
|
|
47
|
+
observer.disconnect();
|
|
48
|
+
observers.delete(id);
|
|
49
|
+
let index = idList.findIndex(obj => obj.root === id.root && obj.margin === id.margin);
|
|
50
|
+
if (index > -1) {
|
|
51
|
+
idList.splice(index, 1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const observers = new Map();
|
|
57
|
+
const idList = [];
|
|
58
|
+
function createObserver(options) {
|
|
59
|
+
const id = {
|
|
60
|
+
root: options.root || null,
|
|
61
|
+
margin: options.rootMargin || ''
|
|
62
|
+
};
|
|
63
|
+
let existing = idList.find(obj => obj.root === id.root && obj.margin === id.margin);
|
|
64
|
+
let instance;
|
|
65
|
+
if (existing) {
|
|
66
|
+
instance = observers.get(existing);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
instance = observers.get(id);
|
|
70
|
+
idList.push(id);
|
|
71
|
+
}
|
|
72
|
+
if (instance) {
|
|
73
|
+
return instance;
|
|
74
|
+
}
|
|
75
|
+
const elements = new Map();
|
|
76
|
+
const observer = new IntersectionObserver(entries => {
|
|
77
|
+
entries.forEach(entry => {
|
|
78
|
+
const callback = elements.get(entry.target);
|
|
79
|
+
const isVisible = entry.isIntersecting || entry.intersectionRatio > 0;
|
|
80
|
+
if (callback && isVisible) {
|
|
81
|
+
callback(isVisible);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}, options);
|
|
85
|
+
observers.set(id, (instance = {
|
|
86
|
+
id,
|
|
87
|
+
observer,
|
|
88
|
+
elements
|
|
89
|
+
}));
|
|
90
|
+
return instance;
|
|
91
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import * as React from 'react';
|
|
11
|
+
import { SHUVI_ERROR } from '@shuvi/shared/lib/constants';
|
|
12
|
+
import { Router } from '@shuvi/router-react';
|
|
13
|
+
import AppContainer from '../AppContainer';
|
|
14
|
+
import { HeadManager, HeadManagerContext } from '../head';
|
|
15
|
+
import Loadable from '../loadable';
|
|
16
|
+
import { renderAction } from './render-action';
|
|
17
|
+
const headManager = new HeadManager();
|
|
18
|
+
export class ReactClientView {
|
|
19
|
+
constructor() {
|
|
20
|
+
this._isInitialRender = true;
|
|
21
|
+
this.renderApp = ({ appContainer, app, appData }) => __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
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
|
+
}
|
|
32
|
+
const TypedAppComponent = AppComponent;
|
|
33
|
+
if (ssr) {
|
|
34
|
+
yield Loadable.preloadReady(dynamicIds);
|
|
35
|
+
yield router.ready;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
yield router.ready;
|
|
39
|
+
const { matches } = router.current;
|
|
40
|
+
if (!matches.length) {
|
|
41
|
+
// no handler no matches
|
|
42
|
+
error.error(SHUVI_ERROR.PAGE_NOT_FOUND);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const root = (<Router router={router}>
|
|
46
|
+
<AppContainer app={app}>
|
|
47
|
+
<HeadManagerContext.Provider value={headManager.updateHead}>
|
|
48
|
+
<TypedAppComponent {...appProps}/>
|
|
49
|
+
</HeadManagerContext.Provider>
|
|
50
|
+
</AppContainer>
|
|
51
|
+
</Router>);
|
|
52
|
+
const ssrCallback = () => {
|
|
53
|
+
this._isInitialRender = false;
|
|
54
|
+
};
|
|
55
|
+
renderAction({
|
|
56
|
+
ssr,
|
|
57
|
+
isInitialRender,
|
|
58
|
+
root,
|
|
59
|
+
callback: ssrCallback,
|
|
60
|
+
appContainer
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import * as React from 'react';
|
|
11
|
+
import { renderToString } from 'react-dom/server';
|
|
12
|
+
import { getLoaderManager, redirect } from '@shuvi/platform-shared/shared';
|
|
13
|
+
import { SHUVI_ERROR } from '@shuvi/shared/lib/constants';
|
|
14
|
+
import { Router } from '@shuvi/router-react';
|
|
15
|
+
import Loadable, { LoadableContext } from '../loadable';
|
|
16
|
+
import AppContainer from '../AppContainer';
|
|
17
|
+
import { Head } from '../head';
|
|
18
|
+
export class ReactServerView {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.renderApp = ({ app, manifest, getAssetPublicUrl }) => __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
yield Loadable.preloadAll();
|
|
22
|
+
const { storeManager, router, error: appError, appComponent: AppComponent } = app;
|
|
23
|
+
yield router.ready;
|
|
24
|
+
// todo: move these into renderer
|
|
25
|
+
let { pathname, matches, redirected } = router.current;
|
|
26
|
+
// handler no matches
|
|
27
|
+
if (!matches.length) {
|
|
28
|
+
appError.error(SHUVI_ERROR.PAGE_NOT_FOUND);
|
|
29
|
+
}
|
|
30
|
+
if (redirected) {
|
|
31
|
+
return redirect(pathname);
|
|
32
|
+
}
|
|
33
|
+
// todo: move loader into app, avoid using global module
|
|
34
|
+
const loaderManager = getLoaderManager();
|
|
35
|
+
const loadersData = yield loaderManager.getAllData();
|
|
36
|
+
const loadableModules = [];
|
|
37
|
+
let htmlContent;
|
|
38
|
+
let head;
|
|
39
|
+
const RootApp = (<Router static router={router}>
|
|
40
|
+
<AppContainer app={app}>
|
|
41
|
+
<LoadableContext.Provider value={moduleName => loadableModules.push(moduleName)}>
|
|
42
|
+
<AppComponent />
|
|
43
|
+
</LoadableContext.Provider>
|
|
44
|
+
</AppContainer>
|
|
45
|
+
</Router>);
|
|
46
|
+
try {
|
|
47
|
+
htmlContent = renderToString(RootApp);
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
loaderManager.clearAllData();
|
|
51
|
+
head = Head.rewind() || [];
|
|
52
|
+
}
|
|
53
|
+
const { loadble } = manifest;
|
|
54
|
+
const dynamicImportIdSet = new Set();
|
|
55
|
+
const dynamicImportChunkSet = new Set();
|
|
56
|
+
for (const mod of loadableModules) {
|
|
57
|
+
const manifestItem = loadble[mod];
|
|
58
|
+
if (manifestItem) {
|
|
59
|
+
manifestItem.files.forEach(file => {
|
|
60
|
+
dynamicImportChunkSet.add(file);
|
|
61
|
+
});
|
|
62
|
+
manifestItem.children.forEach(item => {
|
|
63
|
+
dynamicImportIdSet.add(item.id);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const preloadDynamicChunks = [];
|
|
68
|
+
const styles = [];
|
|
69
|
+
for (const file of dynamicImportChunkSet) {
|
|
70
|
+
if (/\.js$/.test(file)) {
|
|
71
|
+
preloadDynamicChunks.push({
|
|
72
|
+
tagName: 'link',
|
|
73
|
+
attrs: {
|
|
74
|
+
rel: 'preload',
|
|
75
|
+
href: getAssetPublicUrl(file),
|
|
76
|
+
as: 'script'
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
else if (/\.css$/.test(file)) {
|
|
81
|
+
styles.push({
|
|
82
|
+
tagName: 'link',
|
|
83
|
+
attrs: {
|
|
84
|
+
rel: 'stylesheet',
|
|
85
|
+
href: getAssetPublicUrl(file)
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const appData = {
|
|
91
|
+
dynamicIds: [...dynamicImportIdSet],
|
|
92
|
+
loadersData
|
|
93
|
+
};
|
|
94
|
+
if (dynamicImportIdSet.size) {
|
|
95
|
+
appData.dynamicIds = Array.from(dynamicImportIdSet);
|
|
96
|
+
}
|
|
97
|
+
appData.appState = storeManager.getState();
|
|
98
|
+
return {
|
|
99
|
+
appData,
|
|
100
|
+
content: htmlContent,
|
|
101
|
+
htmlAttrs: {},
|
|
102
|
+
headBeginTags: [...head, ...preloadDynamicChunks],
|
|
103
|
+
headEndTags: [...styles],
|
|
104
|
+
bodyBeginTags: [],
|
|
105
|
+
bodyEndTags: []
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
declare type RenderActionParam = {
|
|
3
|
+
ssr?: boolean;
|
|
4
|
+
isInitialRender?: boolean;
|
|
5
|
+
root?: ReactNode;
|
|
6
|
+
callback?: () => unknown;
|
|
7
|
+
appContainer?: Element | Document;
|
|
8
|
+
};
|
|
9
|
+
declare let renderAction: (options: RenderActionParam) => void;
|
|
10
|
+
export { renderAction };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
let renderAction;
|
|
2
|
+
if (process.env.__SHUVI__AFTER__REACT__18__) {
|
|
3
|
+
const { createRoot, hydrateRoot } = require('react-dom/client');
|
|
4
|
+
let renderRoot;
|
|
5
|
+
renderAction = ({ ssr, isInitialRender, root, callback, appContainer }) => {
|
|
6
|
+
if (ssr && isInitialRender) {
|
|
7
|
+
renderRoot = hydrateRoot(appContainer, root);
|
|
8
|
+
callback === null || callback === void 0 ? void 0 : callback();
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
if (!renderRoot) {
|
|
12
|
+
renderRoot = createRoot(appContainer);
|
|
13
|
+
}
|
|
14
|
+
renderRoot.render(root);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
const { hydrate, render } = require('react-dom');
|
|
20
|
+
renderAction = ({ ssr, isInitialRender, root, callback, appContainer }) => {
|
|
21
|
+
if (ssr && isInitialRender) {
|
|
22
|
+
hydrate(root, appContainer, callback);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
render(root, appContainer);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export { renderAction };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { IServerModule as _IServerModule } from '../shared';
|
|
2
|
+
declare type ServerModule = Required<_IServerModule>;
|
|
3
|
+
export declare type GetPageDataFunction = ServerModule['getPageData'];
|
|
4
|
+
export declare type HandlePageRequestFunction = ServerModule['handlePageRequest'];
|
|
5
|
+
export declare type ModifyHtmlFunction = ServerModule['modifyHtml'];
|
|
6
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
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>;
|
|
3
|
+
};
|
|
4
|
+
export default _default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const server_1 = __importDefault(require("./server"));
|
|
7
|
+
exports.default = {
|
|
8
|
+
server: server_1.default
|
|
9
|
+
};
|
|
@@ -0,0 +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>;
|
|
2
|
+
export default _default;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const service_1 = require("@shuvi/service");
|
|
13
|
+
const resources_1 = require("@shuvi/service/lib/resources");
|
|
14
|
+
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)) || {};
|
|
18
|
+
},
|
|
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);
|
|
23
|
+
},
|
|
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));
|
|
27
|
+
})
|
|
28
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { IncomingMessage } from 'http';
|
|
3
|
+
import { IResponse, IRequest } from '@shuvi/service';
|
|
4
|
+
import { IApiRequestHandler, IApiResponse } from '../../../../shared';
|
|
5
|
+
export { IApiRequestHandler };
|
|
6
|
+
export declare function apiRouteHandler(req: IRequest, res: IResponse, resolver: IApiRequestHandler, apiRoutesConfig: any): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Parse incoming message like `json` or `urlencoded`
|
|
9
|
+
* @param req request object
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseBody(req: IRequest, limit: string | number): Promise<any>;
|
|
12
|
+
/**
|
|
13
|
+
* Parse cookies from `req` header
|
|
14
|
+
* @param req request object
|
|
15
|
+
*/
|
|
16
|
+
export declare function getCookieParser(req: IncomingMessage): {
|
|
17
|
+
[key: string]: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @param res ServerResponse object
|
|
22
|
+
* @param statusCode `HTTP` status code of response
|
|
23
|
+
*/
|
|
24
|
+
export declare function sendStatusCode<IRes extends IApiResponse>(res: IResponse, statusCode: number): IRes;
|
|
25
|
+
/**
|
|
26
|
+
*
|
|
27
|
+
* @param res response object
|
|
28
|
+
* @param [statusOrUrl] `HTTP` status code of redirect
|
|
29
|
+
* @param url URL of redirect
|
|
30
|
+
*/
|
|
31
|
+
export declare function redirect<IRes extends IApiResponse>(res: IResponse, statusOrUrl: string | number, url?: string): IRes;
|
|
32
|
+
/**
|
|
33
|
+
* Send `any` body to response
|
|
34
|
+
* @param req request object
|
|
35
|
+
* @param res response object
|
|
36
|
+
* @param body of response
|
|
37
|
+
*/
|
|
38
|
+
export declare function sendData(req: IRequest, res: IResponse, body: any): void;
|
|
39
|
+
/**
|
|
40
|
+
* Send `JSON` object
|
|
41
|
+
* @param res response object
|
|
42
|
+
* @param jsonBody of data
|
|
43
|
+
*/
|
|
44
|
+
export declare function sendJson(req: IRequest, res: IResponse, jsonBody: any): void;
|
|
45
|
+
/**
|
|
46
|
+
* Custom error class
|
|
47
|
+
*/
|
|
48
|
+
export declare class ApiError extends Error {
|
|
49
|
+
readonly statusCode: number;
|
|
50
|
+
constructor(statusCode: number, message: string);
|
|
51
|
+
}
|