@modern-js/runtime 1.4.4 → 1.16.0
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/CHANGELOG.md +65 -0
- package/dist/js/modern/cli/index.js +6 -6
- package/dist/js/modern/core/app-config.js +10 -0
- package/dist/js/modern/core/compatible.js +241 -0
- package/dist/js/modern/core/index.js +7 -0
- package/dist/js/modern/core/loader/index.js +1 -0
- package/dist/js/modern/core/loader/loaderManager.js +189 -0
- package/dist/js/modern/core/loader/useLoader.js +105 -0
- package/dist/js/modern/core/plugin.js +63 -0
- package/dist/js/modern/core/runtime-context.js +2 -0
- package/dist/js/modern/exports/styled.js +2 -2
- package/dist/js/modern/index.js +1 -1
- package/dist/js/modern/router/runtime/plugin.js +1 -1
- package/dist/js/modern/router/runtime/utils.js +3 -1
- package/dist/js/modern/ssr/index.js +34 -13
- package/dist/js/modern/ssr/index.node.js +1 -1
- package/dist/js/modern/ssr/prefetch.js +2 -2
- package/dist/js/modern/ssr/react/withCallback/index.js +17 -0
- package/dist/js/modern/ssr/serverRender/helmet.js +2 -2
- package/dist/js/modern/ssr/serverRender/index.js +1 -1
- package/dist/js/modern/ssr/serverRender/styledComponent.js +1 -1
- package/dist/js/modern/ssr/utils.js +9 -3
- package/dist/js/modern/state/runtime/plugin.js +1 -1
- package/dist/js/node/cli/index.js +5 -5
- package/dist/js/node/core/app-config.js +22 -0
- package/dist/js/node/core/compatible.js +271 -0
- package/dist/js/node/core/index.js +111 -0
- package/dist/js/node/core/loader/index.js +15 -0
- package/dist/js/node/core/loader/loaderManager.js +201 -0
- package/dist/js/node/core/loader/useLoader.js +118 -0
- package/dist/js/node/core/plugin.js +79 -0
- package/dist/js/node/core/runtime-context.js +11 -0
- package/dist/js/node/exports/styled.js +5 -5
- package/dist/js/node/index.js +10 -10
- package/dist/js/node/router/runtime/plugin.js +3 -3
- package/dist/js/node/router/runtime/utils.js +3 -1
- package/dist/js/node/ssr/index.js +37 -15
- package/dist/js/node/ssr/index.node.js +2 -2
- package/dist/js/node/ssr/react/withCallback/index.js +27 -0
- package/dist/js/node/ssr/serverRender/helmet.js +2 -2
- package/dist/js/node/ssr/serverRender/index.js +2 -2
- package/dist/js/node/ssr/serverRender/styledComponent.js +2 -2
- package/dist/js/node/ssr/utils.js +9 -3
- package/dist/js/node/state/runtime/plugin.js +3 -3
- package/dist/js/treeshaking/cli/index.js +6 -6
- package/dist/js/treeshaking/core/app-config.js +13 -0
- package/dist/js/treeshaking/core/compatible.js +297 -0
- package/dist/js/treeshaking/core/index.js +7 -0
- package/dist/js/treeshaking/core/loader/index.js +1 -0
- package/dist/js/treeshaking/core/loader/loaderManager.js +267 -0
- package/dist/js/treeshaking/core/loader/useLoader.js +107 -0
- package/dist/js/treeshaking/core/plugin.js +105 -0
- package/dist/js/treeshaking/core/runtime-context.js +2 -0
- package/dist/js/treeshaking/exports/styled.js +2 -2
- package/dist/js/treeshaking/index.js +1 -1
- package/dist/js/treeshaking/router/runtime/plugin.js +1 -1
- package/dist/js/treeshaking/router/runtime/utils.js +3 -1
- package/dist/js/treeshaking/ssr/index.js +45 -33
- package/dist/js/treeshaking/ssr/index.node.js +1 -1
- package/dist/js/treeshaking/ssr/prefetch.js +2 -2
- package/dist/js/treeshaking/ssr/react/withCallback/index.js +16 -0
- package/dist/js/treeshaking/ssr/serverRender/helmet.js +2 -2
- package/dist/js/treeshaking/ssr/serverRender/index.js +1 -1
- package/dist/js/treeshaking/ssr/serverRender/styledComponent.js +1 -1
- package/dist/js/treeshaking/ssr/utils.js +8 -3
- package/dist/js/treeshaking/state/runtime/plugin.js +1 -1
- package/dist/types/core/app-config.d.ts +6 -0
- package/dist/types/core/compatible.d.ts +17 -0
- package/dist/types/core/index.d.ts +9 -0
- package/dist/types/core/loader/index.d.ts +2 -0
- package/dist/types/core/loader/loaderManager.d.ts +57 -0
- package/dist/types/core/loader/useLoader.d.ts +54 -0
- package/dist/types/core/plugin.d.ts +215 -0
- package/dist/types/core/runtime-context.d.ts +13 -0
- package/dist/types/exports/styled.d.ts +2 -2
- package/dist/types/index.d.ts +4 -9
- package/dist/types/router/runtime/plugin.d.ts +1 -1
- package/dist/types/ssr/index.d.ts +2 -2
- package/dist/types/ssr/index.node.d.ts +1 -1
- package/dist/types/ssr/prefetch.d.ts +2 -2
- package/dist/types/ssr/react/nossr/index.d.ts +1 -1
- package/dist/types/ssr/react/withCallback/index.d.ts +5 -0
- package/dist/types/ssr/serverRender/entry.d.ts +1 -1
- package/dist/types/ssr/serverRender/index.d.ts +1 -1
- package/dist/types/ssr/serverRender/type.d.ts +1 -1
- package/dist/types/state/runtime/plugin.d.ts +2 -2
- package/lib/types.d.ts +10 -0
- package/package.json +39 -27
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,70 @@
|
|
|
1
1
|
# @modern-js/runtime
|
|
2
2
|
|
|
3
|
+
## 1.16.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 1100dd58c: chore: support react 18
|
|
8
|
+
|
|
9
|
+
chore: 支持 React 18
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- a480d6ad0: fix: remove helmet regexp's global tag
|
|
14
|
+
fix: 删除 helmet 中正则匹配的全局标记
|
|
15
|
+
- Updated dependencies [641592f52]
|
|
16
|
+
- Updated dependencies [3904b30a5]
|
|
17
|
+
- Updated dependencies [1100dd58c]
|
|
18
|
+
- Updated dependencies [e04e6e76a]
|
|
19
|
+
- Updated dependencies [81c66e4a4]
|
|
20
|
+
- Updated dependencies [2c305b6f5]
|
|
21
|
+
- @modern-js/utils@1.16.0
|
|
22
|
+
- @modern-js/webpack@1.16.0
|
|
23
|
+
- @modern-js/plugin@1.16.0
|
|
24
|
+
|
|
25
|
+
## 1.15.0
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- 335c97c: fix: fix runtime context format bug
|
|
30
|
+
fix: 修复 runtimeContext 数据格式化时的问题
|
|
31
|
+
- a04a11b: fix: 修复 SSR 物理降级时,获取不到请求上下文的问题
|
|
32
|
+
fix: should get ssrContext anyway if entry is ssr enable
|
|
33
|
+
- Updated dependencies [8658a78]
|
|
34
|
+
- Updated dependencies [0df4970]
|
|
35
|
+
- Updated dependencies [05d4a4f]
|
|
36
|
+
- Updated dependencies [ad05af9]
|
|
37
|
+
- Updated dependencies [5d53d1c]
|
|
38
|
+
- Updated dependencies [37cd159]
|
|
39
|
+
- @modern-js/utils@1.15.0
|
|
40
|
+
- @modern-js/webpack@1.15.0
|
|
41
|
+
- @modern-js/plugin@1.15.0
|
|
42
|
+
|
|
43
|
+
## 1.5.0
|
|
44
|
+
|
|
45
|
+
### Minor Changes
|
|
46
|
+
|
|
47
|
+
- 59c941a: chore(runtime): merge `@modern-js/runtime-core` to `@modern-js/runtime`
|
|
48
|
+
|
|
49
|
+
chore(runtime): 合并 `@modern-js/runtime-core` 到 `@modern-js/runtime`
|
|
50
|
+
|
|
51
|
+
### Patch Changes
|
|
52
|
+
|
|
53
|
+
- e0cd14a: feat: support runtime router and state type
|
|
54
|
+
|
|
55
|
+
feat: 支持在 `modern.config.ts` 中提示 `runtime.router` and `runtime.state` 类型
|
|
56
|
+
|
|
57
|
+
- 287ac8b: fix(runtime): router plugin replace error
|
|
58
|
+
|
|
59
|
+
fix(runtime): router 插件 replace 报错
|
|
60
|
+
|
|
61
|
+
- Updated dependencies [79e83ef]
|
|
62
|
+
- Updated dependencies [5f1a231]
|
|
63
|
+
- Updated dependencies [22f4dca]
|
|
64
|
+
- Updated dependencies [7b9067f]
|
|
65
|
+
- @modern-js/utils@1.9.0
|
|
66
|
+
- @modern-js/webpack@1.12.4
|
|
67
|
+
|
|
3
68
|
## 1.4.3
|
|
4
69
|
|
|
5
70
|
### Patch Changes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import { PLUGIN_SCHEMAS, createRuntimeExportsUtils, cleanRequireCache } from '@modern-js/utils';
|
|
2
|
+
import { PLUGIN_SCHEMAS, createRuntimeExportsUtils, cleanRequireCache, isReact18 } from '@modern-js/utils';
|
|
3
3
|
import PluginState from "../state/cli";
|
|
4
4
|
import PluginSSR from "../ssr/cli";
|
|
5
5
|
import PluginRouter from "../router/cli";
|
|
@@ -11,8 +11,9 @@ export default (() => ({
|
|
|
11
11
|
let runtimeExportsUtils = {};
|
|
12
12
|
return {
|
|
13
13
|
config() {
|
|
14
|
-
const dir = api.useAppContext().internalDirectory;
|
|
14
|
+
const dir = api.useAppContext().internalDirectory || '';
|
|
15
15
|
runtimeExportsUtils = createRuntimeExportsUtils(dir, 'index');
|
|
16
|
+
process.env.IS_REACT18 = isReact18(path.join(dir, '../../')).toString();
|
|
16
17
|
return {
|
|
17
18
|
runtime: {},
|
|
18
19
|
runtimeByEntries: {},
|
|
@@ -25,10 +26,9 @@ export default (() => ({
|
|
|
25
26
|
* But it will not be installed under the user project.
|
|
26
27
|
* So need to add alias
|
|
27
28
|
*/
|
|
28
|
-
'styled-components': require.resolve('styled-components'
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
29
|
+
'styled-components': require.resolve('styled-components')
|
|
30
|
+
},
|
|
31
|
+
envVars: ['IS_REACT18']
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
34
|
},
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const APP_CONFIG_SYMBOL = 'config';
|
|
2
|
+
export const getConfig = Component => // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
3
|
+
// @ts-expect-error
|
|
4
|
+
Component[APP_CONFIG_SYMBOL];
|
|
5
|
+
export const defineConfig = (Component, config) => {
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
7
|
+
// @ts-expect-error
|
|
8
|
+
Component[APP_CONFIG_SYMBOL] = config;
|
|
9
|
+
return Component;
|
|
10
|
+
};
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
const _excluded = ["context"];
|
|
2
|
+
|
|
3
|
+
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
4
|
+
|
|
5
|
+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
6
|
+
|
|
7
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
8
|
+
|
|
9
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
10
|
+
|
|
11
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
12
|
+
|
|
13
|
+
import React, { useContext, useMemo } from 'react';
|
|
14
|
+
import defaultReactDOM from 'react-dom';
|
|
15
|
+
import hoistNonReactStatics from 'hoist-non-react-statics';
|
|
16
|
+
import { runtime } from "./plugin";
|
|
17
|
+
import { RuntimeReactContext } from "./runtime-context";
|
|
18
|
+
import { createLoaderManager } from "./loader/loaderManager";
|
|
19
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
20
|
+
const IS_REACT18 = process.env.IS_REACT18 === 'true';
|
|
21
|
+
|
|
22
|
+
function isClientArgs(id) {
|
|
23
|
+
return typeof id === 'string' || typeof HTMLElement !== 'undefined' && id instanceof HTMLElement;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const runnerMap = new WeakMap();
|
|
27
|
+
|
|
28
|
+
const getInitialContext = runner => ({
|
|
29
|
+
loaderManager: createLoaderManager({}),
|
|
30
|
+
runner,
|
|
31
|
+
isBrowser: true
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export const createApp = ({
|
|
35
|
+
plugins
|
|
36
|
+
}) => {
|
|
37
|
+
const appRuntime = runtime.clone();
|
|
38
|
+
appRuntime.usePlugin(...plugins);
|
|
39
|
+
return App => {
|
|
40
|
+
const runner = appRuntime.init();
|
|
41
|
+
|
|
42
|
+
const WrapperComponent = props => {
|
|
43
|
+
const element = /*#__PURE__*/React.createElement(App || React.Fragment, _objectSpread({}, props), props.children);
|
|
44
|
+
const context = useContext(RuntimeReactContext);
|
|
45
|
+
return runner.provide({
|
|
46
|
+
element,
|
|
47
|
+
props: _objectSpread({}, props),
|
|
48
|
+
context
|
|
49
|
+
}, {
|
|
50
|
+
onLast: ({
|
|
51
|
+
element
|
|
52
|
+
}) => element
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
if (App) {
|
|
57
|
+
hoistNonReactStatics(WrapperComponent, App);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const HOCApp = runner.hoc({
|
|
61
|
+
App: WrapperComponent
|
|
62
|
+
}, {
|
|
63
|
+
onLast: ({
|
|
64
|
+
App
|
|
65
|
+
}) => {
|
|
66
|
+
const WrapComponent = _ref => {
|
|
67
|
+
var _contextValue;
|
|
68
|
+
|
|
69
|
+
let {
|
|
70
|
+
context
|
|
71
|
+
} = _ref,
|
|
72
|
+
props = _objectWithoutProperties(_ref, _excluded);
|
|
73
|
+
|
|
74
|
+
let contextValue = context; // We should construct the context, when root component is not passed into `bootstrap`.
|
|
75
|
+
|
|
76
|
+
if (!((_contextValue = contextValue) !== null && _contextValue !== void 0 && _contextValue.runner)) {
|
|
77
|
+
contextValue = getInitialContext(runner);
|
|
78
|
+
runner.init({
|
|
79
|
+
context: contextValue
|
|
80
|
+
}, {
|
|
81
|
+
onLast: ({
|
|
82
|
+
context: context1
|
|
83
|
+
}) => {
|
|
84
|
+
var _App$init;
|
|
85
|
+
|
|
86
|
+
return App === null || App === void 0 ? void 0 : (_App$init = App.init) === null || _App$init === void 0 ? void 0 : _App$init.call(App, context1);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return /*#__PURE__*/_jsx(RuntimeReactContext.Provider, {
|
|
92
|
+
value: contextValue,
|
|
93
|
+
children: /*#__PURE__*/_jsx(App, _objectSpread({}, props))
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
return hoistNonReactStatics(WrapComponent, App);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
runnerMap.set(HOCApp, runner);
|
|
101
|
+
return HOCApp;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
export const bootstrap = async (BootApp,
|
|
105
|
+
/**
|
|
106
|
+
* When csr, id is root id.
|
|
107
|
+
* When ssr, id is serverContext
|
|
108
|
+
*/
|
|
109
|
+
id,
|
|
110
|
+
/**
|
|
111
|
+
* root.render need use root to run function
|
|
112
|
+
*/
|
|
113
|
+
root, render = defaultReactDOM.render, hydrate = defaultReactDOM.hydrate) => {
|
|
114
|
+
let App = BootApp;
|
|
115
|
+
let runner = runnerMap.get(App); // ensure Component used is created by `createApp`
|
|
116
|
+
|
|
117
|
+
if (!runner) {
|
|
118
|
+
App = createApp({
|
|
119
|
+
plugins: []
|
|
120
|
+
})(App);
|
|
121
|
+
runner = runnerMap.get(App);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const context = getInitialContext(runner);
|
|
125
|
+
|
|
126
|
+
const runInit = _context => runner.init({
|
|
127
|
+
context: _context
|
|
128
|
+
}, {
|
|
129
|
+
onLast: ({
|
|
130
|
+
context: context1
|
|
131
|
+
}) => {
|
|
132
|
+
var _App, _App$init2;
|
|
133
|
+
|
|
134
|
+
return (_App = App) === null || _App === void 0 ? void 0 : (_App$init2 = _App.init) === null || _App$init2 === void 0 ? void 0 : _App$init2.call(_App, context1);
|
|
135
|
+
}
|
|
136
|
+
}); // don't mount the App, let user in charge of it.
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
if (!id) {
|
|
140
|
+
return /*#__PURE__*/React.createElement(App, {
|
|
141
|
+
context
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const isBrowser = typeof window !== 'undefined' && window.name !== 'nodejs';
|
|
146
|
+
|
|
147
|
+
if (isBrowser) {
|
|
148
|
+
if (isClientArgs(id)) {
|
|
149
|
+
var _ssrData$data, _ssrData$data2;
|
|
150
|
+
|
|
151
|
+
const ssrData = window._SSR_DATA;
|
|
152
|
+
const loadersData = (ssrData === null || ssrData === void 0 ? void 0 : (_ssrData$data = ssrData.data) === null || _ssrData$data === void 0 ? void 0 : _ssrData$data.loadersData) || {};
|
|
153
|
+
const initialLoadersState = Object.keys(loadersData).reduce((res, key) => {
|
|
154
|
+
const loaderData = loadersData[key];
|
|
155
|
+
|
|
156
|
+
if (loaderData.loading !== false) {
|
|
157
|
+
return res;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
res[key] = loaderData;
|
|
161
|
+
return res;
|
|
162
|
+
}, {});
|
|
163
|
+
Object.assign(context, _objectSpread({
|
|
164
|
+
loaderManager: createLoaderManager(initialLoadersState, {
|
|
165
|
+
skipStatic: true
|
|
166
|
+
})
|
|
167
|
+
}, ssrData ? {
|
|
168
|
+
ssrContext: ssrData === null || ssrData === void 0 ? void 0 : ssrData.context
|
|
169
|
+
} : {}));
|
|
170
|
+
context.initialData = ssrData === null || ssrData === void 0 ? void 0 : (_ssrData$data2 = ssrData.data) === null || _ssrData$data2 === void 0 ? void 0 : _ssrData$data2.initialData;
|
|
171
|
+
const initialData = await runInit(context);
|
|
172
|
+
|
|
173
|
+
if (initialData) {
|
|
174
|
+
context.initialData = initialData;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const rootElement = typeof id !== 'string' ? id : document.getElementById(id || 'root'); // https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html
|
|
178
|
+
|
|
179
|
+
const ModernRender = App => {
|
|
180
|
+
if (IS_REACT18) {
|
|
181
|
+
root.render(App);
|
|
182
|
+
} else {
|
|
183
|
+
render(App, rootElement);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const ModernHydrate = (App, callback) => {
|
|
188
|
+
if (IS_REACT18) {
|
|
189
|
+
hydrate(rootElement, App);
|
|
190
|
+
} else {
|
|
191
|
+
hydrate(App, rootElement, callback);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
return runner.client({
|
|
196
|
+
App,
|
|
197
|
+
context,
|
|
198
|
+
ModernRender,
|
|
199
|
+
ModernHydrate
|
|
200
|
+
}, {
|
|
201
|
+
onLast: ({
|
|
202
|
+
App
|
|
203
|
+
}) => {
|
|
204
|
+
ModernRender( /*#__PURE__*/React.createElement(App, {
|
|
205
|
+
context
|
|
206
|
+
}));
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
} else {
|
|
210
|
+
throw Error('`bootstrap` needs id in browser environment, it needs to be string or element');
|
|
211
|
+
}
|
|
212
|
+
} else {
|
|
213
|
+
Object.assign(context, {
|
|
214
|
+
ssrContext: id,
|
|
215
|
+
isBrowser: false,
|
|
216
|
+
loaderManager: createLoaderManager({}, {
|
|
217
|
+
skipNonStatic: id.staticGenerate,
|
|
218
|
+
// if not static generate, only non-static loader can exec on prod env
|
|
219
|
+
skipStatic: process.env.NODE_ENV === 'production' && !id.staticGenerate
|
|
220
|
+
})
|
|
221
|
+
});
|
|
222
|
+
const initialData = await runInit(context);
|
|
223
|
+
context.initialData = initialData;
|
|
224
|
+
return runner.server({
|
|
225
|
+
App,
|
|
226
|
+
context
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
export const useRuntimeContext = () => {
|
|
231
|
+
const context = useContext(RuntimeReactContext);
|
|
232
|
+
const memoizedContext = useMemo(() => context.runner.pickContext({
|
|
233
|
+
context,
|
|
234
|
+
pickedContext: {}
|
|
235
|
+
}, {
|
|
236
|
+
onLast: ({
|
|
237
|
+
pickedContext
|
|
238
|
+
}) => pickedContext
|
|
239
|
+
}), [context]);
|
|
240
|
+
return memoizedContext;
|
|
241
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { createPlugin, createRuntime, runtime, registerInit, registerPrefetch } from "./plugin";
|
|
2
|
+
export { defineConfig, getConfig } from "./app-config";
|
|
3
|
+
// compatible
|
|
4
|
+
export * from "./compatible";
|
|
5
|
+
export { RuntimeReactContext } from "./runtime-context";
|
|
6
|
+
export * from "./loader";
|
|
7
|
+
export * from '@modern-js/plugin';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as useLoader } from "./useLoader";
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import invariant from 'invariant';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Calc id from string or object
|
|
5
|
+
*/
|
|
6
|
+
const createGetId = () => {
|
|
7
|
+
const idCache = new Map();
|
|
8
|
+
return objectId => {
|
|
9
|
+
const cachedId = idCache.get(objectId);
|
|
10
|
+
|
|
11
|
+
if (cachedId) {
|
|
12
|
+
return cachedId;
|
|
13
|
+
} // WARNING: id should be unique after serialize.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
const id = JSON.stringify(objectId);
|
|
17
|
+
invariant(id, 'params should be not null value');
|
|
18
|
+
idCache.set(objectId, id);
|
|
19
|
+
return id;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export let LoaderStatus;
|
|
24
|
+
|
|
25
|
+
(function (LoaderStatus) {
|
|
26
|
+
LoaderStatus[LoaderStatus["idle"] = 0] = "idle";
|
|
27
|
+
LoaderStatus[LoaderStatus["loading"] = 1] = "loading";
|
|
28
|
+
LoaderStatus[LoaderStatus["fulfilled"] = 2] = "fulfilled";
|
|
29
|
+
LoaderStatus[LoaderStatus["rejected"] = 3] = "rejected";
|
|
30
|
+
})(LoaderStatus || (LoaderStatus = {}));
|
|
31
|
+
|
|
32
|
+
const createLoader = (id, initialData = {
|
|
33
|
+
loading: false,
|
|
34
|
+
reloading: false,
|
|
35
|
+
data: undefined,
|
|
36
|
+
error: undefined
|
|
37
|
+
}, loaderFn, skip = false) => {
|
|
38
|
+
let promise;
|
|
39
|
+
let status = LoaderStatus.idle;
|
|
40
|
+
let {
|
|
41
|
+
data,
|
|
42
|
+
error
|
|
43
|
+
} = initialData;
|
|
44
|
+
let hasLoaded = false;
|
|
45
|
+
const handlers = new Set();
|
|
46
|
+
|
|
47
|
+
const load = async () => {
|
|
48
|
+
if (skip) {
|
|
49
|
+
return promise;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (status === LoaderStatus.loading) {
|
|
53
|
+
return promise;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
status = LoaderStatus.loading;
|
|
57
|
+
notify();
|
|
58
|
+
promise = loaderFn().then(value => {
|
|
59
|
+
data = value;
|
|
60
|
+
error = null;
|
|
61
|
+
status = LoaderStatus.fulfilled;
|
|
62
|
+
}).catch(e => {
|
|
63
|
+
error = e;
|
|
64
|
+
data = null;
|
|
65
|
+
status = LoaderStatus.rejected;
|
|
66
|
+
}).finally(() => {
|
|
67
|
+
promise = null;
|
|
68
|
+
hasLoaded = true;
|
|
69
|
+
notify();
|
|
70
|
+
});
|
|
71
|
+
return promise;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const getResult = () => ({
|
|
75
|
+
loading: !hasLoaded && status === LoaderStatus.loading,
|
|
76
|
+
reloading: hasLoaded && status === LoaderStatus.loading,
|
|
77
|
+
data,
|
|
78
|
+
error: error instanceof Error ? `${error.message}` : error,
|
|
79
|
+
// redundant fields for ssr log
|
|
80
|
+
_error: error
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const notify = () => {
|
|
84
|
+
// don't iterate handlers directly, since it could be modified during iteration
|
|
85
|
+
[...handlers].forEach(handler => {
|
|
86
|
+
handler(status, getResult());
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const onChange = handler => {
|
|
91
|
+
handlers.add(handler);
|
|
92
|
+
return () => {
|
|
93
|
+
handlers.delete(handler);
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
get result() {
|
|
99
|
+
return getResult();
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
get promise() {
|
|
103
|
+
return promise;
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
onChange,
|
|
107
|
+
load
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Create loaders manager. It's returned instance will add to context
|
|
113
|
+
* @param initialDataMap used to initialing loader data
|
|
114
|
+
*/
|
|
115
|
+
export const createLoaderManager = (initialDataMap, managerOptions = {}) => {
|
|
116
|
+
const {
|
|
117
|
+
skipStatic = false,
|
|
118
|
+
skipNonStatic = false
|
|
119
|
+
} = managerOptions;
|
|
120
|
+
const loadersMap = new Map();
|
|
121
|
+
const getId = createGetId();
|
|
122
|
+
|
|
123
|
+
const add = (loaderFn, loaderOptions) => {
|
|
124
|
+
const id = getId(loaderOptions.params);
|
|
125
|
+
let loader = loadersMap.get(id); // private property for opting out loader cache, maybe change in future
|
|
126
|
+
|
|
127
|
+
const cache = loaderOptions._cache;
|
|
128
|
+
|
|
129
|
+
if (!loader || cache === false) {
|
|
130
|
+
// ignore non-static loader on static phase
|
|
131
|
+
const ignoreNonStatic = skipNonStatic && !loaderOptions.static; // ignore static loader on non-static phase
|
|
132
|
+
|
|
133
|
+
const ignoreStatic = skipStatic && loaderOptions.static;
|
|
134
|
+
const skipExec = ignoreNonStatic || ignoreStatic;
|
|
135
|
+
loader = createLoader(id, typeof initialDataMap[id] !== 'undefined' ? initialDataMap[id] : {
|
|
136
|
+
data: loaderOptions.initialData
|
|
137
|
+
}, loaderFn, // Todo whether static loader is exec when CSR
|
|
138
|
+
skipExec);
|
|
139
|
+
loadersMap.set(id, loader);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return id;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const get = id => loadersMap.get(id); // check if there has pending loaders
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
const hasPendingLoaders = () => {
|
|
149
|
+
for (const loader of loadersMap.values()) {
|
|
150
|
+
const {
|
|
151
|
+
promise
|
|
152
|
+
} = loader;
|
|
153
|
+
|
|
154
|
+
if (promise instanceof Promise) {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return false;
|
|
160
|
+
}; // waiting for all pending loaders to be settled
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
const awaitPendingLoaders = async () => {
|
|
164
|
+
const pendingLoaders = [];
|
|
165
|
+
|
|
166
|
+
for (const [id, loader] of loadersMap) {
|
|
167
|
+
const {
|
|
168
|
+
promise
|
|
169
|
+
} = loader;
|
|
170
|
+
|
|
171
|
+
if (promise instanceof Promise) {
|
|
172
|
+
pendingLoaders.push([id, loader]);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
await Promise.all(pendingLoaders.map(item => item[1].promise));
|
|
177
|
+
return pendingLoaders.reduce((res, [id, loader]) => {
|
|
178
|
+
res[id] = loader.result;
|
|
179
|
+
return res;
|
|
180
|
+
}, {});
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
hasPendingLoaders,
|
|
185
|
+
awaitPendingLoaders,
|
|
186
|
+
add,
|
|
187
|
+
get
|
|
188
|
+
};
|
|
189
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
2
|
+
|
|
3
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
4
|
+
|
|
5
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
6
|
+
|
|
7
|
+
import { useContext, useRef, useMemo, useState, useCallback, useEffect } from 'react';
|
|
8
|
+
import invariant from 'invariant';
|
|
9
|
+
import { RuntimeReactContext } from "../runtime-context";
|
|
10
|
+
import { LoaderStatus } from "./loaderManager";
|
|
11
|
+
|
|
12
|
+
const useLoader = (loaderFn, options = {
|
|
13
|
+
params: undefined
|
|
14
|
+
}) => {
|
|
15
|
+
const context = useContext(RuntimeReactContext);
|
|
16
|
+
const isSSRRender = Boolean(context.ssr);
|
|
17
|
+
const {
|
|
18
|
+
loaderManager
|
|
19
|
+
} = context;
|
|
20
|
+
const loaderRef = useRef();
|
|
21
|
+
const unlistenLoaderChangeRef = useRef(null); // SSR render should ignore `_cache` prop
|
|
22
|
+
|
|
23
|
+
if (isSSRRender && Object.prototype.hasOwnProperty.call(options, '_cache')) {
|
|
24
|
+
delete options._cache;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const load = useCallback(params => {
|
|
28
|
+
var _unlistenLoaderChange, _window, _window$_SSR_DATA, _window$_SSR_DATA$dat, _window$_SSR_DATA$dat2, _loaderRef$current2;
|
|
29
|
+
|
|
30
|
+
if (typeof params === 'undefined') {
|
|
31
|
+
var _loaderRef$current;
|
|
32
|
+
|
|
33
|
+
return (_loaderRef$current = loaderRef.current) === null || _loaderRef$current === void 0 ? void 0 : _loaderRef$current.load();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const id = loaderManager.add(() => {
|
|
37
|
+
try {
|
|
38
|
+
const res = loaderFn(context, params);
|
|
39
|
+
|
|
40
|
+
if (res instanceof Promise) {
|
|
41
|
+
return res;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return Promise.resolve(res);
|
|
45
|
+
} catch (e) {
|
|
46
|
+
return Promise.reject(e);
|
|
47
|
+
}
|
|
48
|
+
}, _objectSpread(_objectSpread({}, options), {}, {
|
|
49
|
+
params
|
|
50
|
+
}));
|
|
51
|
+
loaderRef.current = loaderManager.get(id); // unsubscribe old loader onChange event
|
|
52
|
+
|
|
53
|
+
(_unlistenLoaderChange = unlistenLoaderChangeRef.current) === null || _unlistenLoaderChange === void 0 ? void 0 : _unlistenLoaderChange.call(unlistenLoaderChangeRef);
|
|
54
|
+
|
|
55
|
+
if (isSSRRender) {
|
|
56
|
+
return undefined;
|
|
57
|
+
} // skip this loader, then try to unlisten loader change
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
if (options.skip) {
|
|
61
|
+
return undefined;
|
|
62
|
+
} // do not load data again in CSR hydrate stage if SSR data exists
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
if (context._hydration && ((_window = window) === null || _window === void 0 ? void 0 : (_window$_SSR_DATA = _window._SSR_DATA) === null || _window$_SSR_DATA === void 0 ? void 0 : (_window$_SSR_DATA$dat = _window$_SSR_DATA.data) === null || _window$_SSR_DATA$dat === void 0 ? void 0 : (_window$_SSR_DATA$dat2 = _window$_SSR_DATA$dat.loadersData[id]) === null || _window$_SSR_DATA$dat2 === void 0 ? void 0 : _window$_SSR_DATA$dat2.error) === null) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const res = loaderRef.current.load();
|
|
70
|
+
unlistenLoaderChangeRef.current = (_loaderRef$current2 = loaderRef.current) === null || _loaderRef$current2 === void 0 ? void 0 : _loaderRef$current2.onChange((_status, _result) => {
|
|
71
|
+
setResult(_result);
|
|
72
|
+
|
|
73
|
+
if (_status === LoaderStatus.fulfilled) {
|
|
74
|
+
var _options$onSuccess;
|
|
75
|
+
|
|
76
|
+
options === null || options === void 0 ? void 0 : (_options$onSuccess = options.onSuccess) === null || _options$onSuccess === void 0 ? void 0 : _options$onSuccess.call(options, _result.data);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (_status === LoaderStatus.rejected) {
|
|
80
|
+
var _options$onError;
|
|
81
|
+
|
|
82
|
+
options === null || options === void 0 ? void 0 : (_options$onError = options.onError) === null || _options$onError === void 0 ? void 0 : _options$onError.call(options, _result.error);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return res;
|
|
86
|
+
}, [options.skip]);
|
|
87
|
+
useEffect(() => () => {
|
|
88
|
+
var _unlistenLoaderChange2;
|
|
89
|
+
|
|
90
|
+
(_unlistenLoaderChange2 = unlistenLoaderChangeRef.current) === null || _unlistenLoaderChange2 === void 0 ? void 0 : _unlistenLoaderChange2.call(unlistenLoaderChangeRef);
|
|
91
|
+
}, []);
|
|
92
|
+
useMemo(() => {
|
|
93
|
+
var _options$params;
|
|
94
|
+
|
|
95
|
+
const p = (_options$params = options.params) !== null && _options$params !== void 0 ? _options$params : loaderFn.id;
|
|
96
|
+
invariant(typeof p !== 'undefined' && p !== null, 'Params is required in useLoader');
|
|
97
|
+
load(p);
|
|
98
|
+
}, [options.params]);
|
|
99
|
+
const [result, setResult] = useState(loaderRef.current.result);
|
|
100
|
+
return _objectSpread(_objectSpread({}, result), {}, {
|
|
101
|
+
reload: load
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export default useLoader;
|