You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

669 lines
19 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var ReactDOM = require('react-dom');
var React = require('react');
var React__default = _interopDefault(React);
var runtime = require('@umijs/runtime');
var reactRouterConfig = require('react-router-config');
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
function _asyncToGenerator(fn) {
return function () {
var self = this,
args = arguments;
return new Promise(function (resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
}
_next(undefined);
});
};
}
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;
}
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
if (i % 2) {
ownKeys(Object(source), true).forEach(function (key) {
_defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
}
return target;
}
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;
}
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;
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArrayLimit(arr, i) {
if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(n);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _createForOfIteratorHelper(o) {
if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) {
var i = 0;
var F = function () {};
return {
s: F,
n: function () {
if (i >= o.length) return {
done: true
};
return {
done: false,
value: o[i++]
};
},
e: function (e) {
throw e;
},
f: F
};
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var it,
normalCompletion = true,
didErr = false,
err;
return {
s: function () {
it = o[Symbol.iterator]();
},
n: function () {
var step = it.next();
normalCompletion = step.done;
return step;
},
e: function (e) {
didErr = true;
err = e;
},
f: function () {
try {
if (!normalCompletion && it.return != null) it.return();
} finally {
if (didErr) throw err;
}
}
};
}
function Switch(props) {
return /*#__PURE__*/React__default.createElement(runtime.__RouterContext.Consumer, null, function (context) {
var children = props.children,
extraProps = _objectWithoutProperties(props, ["children"]);
var location = context.location;
var element,
match = null;
React__default.Children.forEach(children, function (child) {
if (match === null && React__default.isValidElement(child)) {
element = child;
var path = child.props.path || child.props.from;
match = path ? runtime.matchPath(location.pathname, _objectSpread2({}, child.props, {
path: path
})) : context.match;
}
});
return match ? React__default.cloneElement(element, {
location: location,
computedMatch: match,
layoutProps: extraProps
}) : null;
});
}
function Route(props) {
return /*#__PURE__*/React__default.createElement(runtime.__RouterContext.Consumer, null, function (context) {
var location = context.location;
var match = props.computedMatch;
var newProps = _objectSpread2({}, context, {
location: location,
match: match
});
var render = props.render;
return /*#__PURE__*/React__default.createElement(runtime.__RouterContext.Provider, {
value: newProps
}, newProps.match ? render(_objectSpread2({}, props.layoutProps, {}, newProps)) : null);
});
}
function wrapInitialPropsFetch(route, opts) {
var component = route.component,
restRouteParams = _objectWithoutProperties(route, ["component"]);
var Component = route.component;
function ComponentWithInitialPropsFetch(props) {
var _useState = React.useState(function () {
return window.g_initialProps;
}),
_useState2 = _slicedToArray(_useState, 2),
initialProps = _useState2[0],
setInitialProps = _useState2[1];
React.useEffect(function () {
/**
* 1. 首次渲染时,此时 window.g_initialProps 变量存在,不需要再走一次 getInitialProps这样一次 SSR 就走了 2 次 getInitialProps
* 2. 但是路由切换时window.getInitialProps 会被赋为 null这时候就走 getInitialProps 逻辑
* 3. 如果任何时候都走 2 次,配置 forceInitial: true这个场景用于静态站点的首屏加载希望走最新数据
* 4. 开启动态加载后,会在执行 getInitialProps 前预加载下
*/
if (!window.g_initialProps) {
_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
var _Component;
var preloadComponent, defaultCtx, ctx, _initialProps;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (!Component.preload) {
_context.next = 5;
break;
}
_context.next = 3;
return Component.preload();
case 3:
preloadComponent = _context.sent;
// for test case, really use .default
Component = preloadComponent.default || preloadComponent;
case 5:
defaultCtx = _objectSpread2({
isServer: false,
match: props === null || props === void 0 ? void 0 : props.match,
route: route
}, opts.getInitialPropsCtx || {}, {}, restRouteParams);
if (!((_Component = Component) === null || _Component === void 0 ? void 0 : _Component.getInitialProps)) {
_context.next = 14;
break;
}
_context.next = 9;
return opts.plugin.applyPlugins({
key: 'ssr.modifyGetInitialPropsCtx',
type: runtime.ApplyPluginsType.modify,
initialValue: defaultCtx,
async: true
});
case 9:
ctx = _context.sent;
_context.next = 12;
return Component.getInitialProps(ctx || defaultCtx);
case 12:
_initialProps = _context.sent;
setInitialProps(_initialProps);
case 14:
case "end":
return _context.stop();
}
}
}, _callee);
}))();
}
}, [window.location.pathname, window.location.search]);
return /*#__PURE__*/React__default.createElement(Component, _extends({}, props, initialProps));
} // flag for having wrappered
ComponentWithInitialPropsFetch.wrapInitialPropsLoaded = true;
ComponentWithInitialPropsFetch.displayName = 'ComponentWithInitialPropsFetch';
return ComponentWithInitialPropsFetch;
}
function _render(_ref2) {
var route = _ref2.route,
opts = _ref2.opts,
props = _ref2.props;
var routes = renderRoutes(_objectSpread2({}, opts, {
routes: route.routes || [],
rootRoutes: opts.rootRoutes
}));
var Component = route.component,
wrappers = route.wrappers;
if (Component) {
var defaultPageInitialProps = opts.isServer ? {} : window.g_initialProps;
var newProps = _objectSpread2({}, props, {}, opts.extraProps, {}, opts.pageInitialProps || defaultPageInitialProps, {
route: route,
routes: opts.rootRoutes
}); // @ts-ignore
var ret = /*#__PURE__*/React__default.createElement(Component, newProps, routes); // route.wrappers
if (wrappers) {
var len = wrappers.length - 1;
while (len >= 0) {
ret = React__default.createElement(wrappers[len], newProps, ret);
len -= 1;
}
}
return ret;
} else {
return routes;
}
}
function getRouteElement(_ref3) {
var route = _ref3.route,
index = _ref3.index,
opts = _ref3.opts;
var routeProps = {
key: route.key || index,
exact: route.exact,
strict: route.strict,
sensitive: route.sensitive,
path: route.path
};
if (route.redirect) {
return /*#__PURE__*/React__default.createElement(runtime.Redirect, _extends({}, routeProps, {
from: route.path,
to: route.redirect
}));
} else {
var _route$component, _route$component2, _route$component3;
// avoid mount and unmount with url hash change
if ( // only when SSR config enable
opts.ssrProps && !opts.isServer && // make sure loaded once
!((_route$component = route.component) === null || _route$component === void 0 ? void 0 : _route$component.wrapInitialPropsLoaded) && (((_route$component2 = route.component) === null || _route$component2 === void 0 ? void 0 : _route$component2.getInitialProps) || ((_route$component3 = route.component) === null || _route$component3 === void 0 ? void 0 : _route$component3.preload))) {
// client Render for enable ssr, but not sure SSR success
route.component = wrapInitialPropsFetch(route, opts);
}
return /*#__PURE__*/React__default.createElement(Route, _extends({}, routeProps, {
render: function render(props) {
return _render({
route: route,
opts: opts,
props: props
});
}
}));
}
}
function renderRoutes(opts) {
return opts.routes ? /*#__PURE__*/React__default.createElement(Switch, null, opts.routes.map(function (route, index) {
return getRouteElement({
route: route,
index: index,
opts: _objectSpread2({}, opts, {
rootRoutes: opts.rootRoutes || opts.routes
})
});
})) : null;
}
function RouterComponent(props) {
var history = props.history,
renderRoutesProps = _objectWithoutProperties(props, ["history"]);
React.useEffect(function () {
// first time using window.g_initialProps
// switch route fetching data, if exact route reset window.getInitialProps
if (window.g_initialProps) {
window.g_initialProps = null;
}
function routeChangeHandler(location, action) {
var matchedRoutes = reactRouterConfig.matchRoutes(props.routes, location.pathname); // Set title
if (typeof document !== 'undefined' && renderRoutesProps.defaultTitle !== undefined) {
document.title = matchedRoutes.length && // @ts-ignore
matchedRoutes[matchedRoutes.length - 1].route.title || renderRoutesProps.defaultTitle || '';
}
props.plugin.applyPlugins({
key: 'onRouteChange',
type: runtime.ApplyPluginsType.event,
args: {
routes: props.routes,
matchedRoutes: matchedRoutes,
location: location,
action: action
}
});
}
routeChangeHandler(history.location, 'POP');
return history.listen(routeChangeHandler);
}, [history]);
return /*#__PURE__*/React__default.createElement(runtime.Router, {
history: history
}, renderRoutes(renderRoutesProps));
}
/**
* preload for SSR in dynamicImport
* exec preload Promise function before ReactDOM.hydrate
* @param Routes
*/
function preloadComponent(_x) {
return _preloadComponent.apply(this, arguments);
}
function _preloadComponent() {
_preloadComponent = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(readyRoutes) {
var pathname,
matchedRoutes,
_iterator,
_step,
_route$component,
matchRoute,
route,
_preloadComponent2,
_args = arguments;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
pathname = _args.length > 1 && _args[1] !== undefined ? _args[1] : window.location.pathname;
// using matched routes not load all routes
matchedRoutes = reactRouterConfig.matchRoutes(readyRoutes, pathname);
_iterator = _createForOfIteratorHelper(matchedRoutes);
_context.prev = 3;
_iterator.s();
case 5:
if ((_step = _iterator.n()).done) {
_context.next = 19;
break;
}
matchRoute = _step.value;
route = matchRoute.route; // load all preload function, because of only a chance to load
if (!((_route$component = route.component) === null || _route$component === void 0 ? void 0 : _route$component.preload)) {
_context.next = 13;
break;
}
_context.next = 11;
return route.component.preload();
case 11:
_preloadComponent2 = _context.sent;
route.component = _preloadComponent2.default || _preloadComponent2;
case 13:
if (!route.routes) {
_context.next = 17;
break;
}
_context.next = 16;
return preloadComponent(route.routes, pathname);
case 16:
route.routes = _context.sent;
case 17:
_context.next = 5;
break;
case 19:
_context.next = 24;
break;
case 21:
_context.prev = 21;
_context.t0 = _context["catch"](3);
_iterator.e(_context.t0);
case 24:
_context.prev = 24;
_iterator.f();
return _context.finish(24);
case 27:
return _context.abrupt("return", readyRoutes);
case 28:
case "end":
return _context.stop();
}
}
}, _callee, null, [[3, 21, 24, 27]]);
}));
return _preloadComponent.apply(this, arguments);
}
function renderClient(opts) {
var rootContainer = opts.plugin.applyPlugins({
type: runtime.ApplyPluginsType.modify,
key: 'rootContainer',
initialValue: /*#__PURE__*/React__default.createElement(RouterComponent, {
history: opts.history,
routes: opts.routes,
plugin: opts.plugin,
ssrProps: opts.ssrProps,
defaultTitle: opts.defaultTitle
}),
args: {
history: opts.history,
routes: opts.routes,
plugin: opts.plugin
}
});
if (opts.rootElement) {
var rootElement = typeof opts.rootElement === 'string' ? document.getElementById(opts.rootElement) : opts.rootElement;
var callback = opts.callback || function () {}; // flag showing SSR successed
if (window.g_useSSR) {
if (opts.dynamicImport) {
// dynamicImport should preload current route component
// first loades);
preloadComponent(opts.routes).then(function () {
ReactDOM.hydrate(rootContainer, rootElement, callback);
});
} else {
ReactDOM.hydrate(rootContainer, rootElement, callback);
}
} else {
ReactDOM.render(rootContainer, rootElement, callback);
}
} else {
return rootContainer;
}
}
exports.renderClient = renderClient;
exports.renderRoutes = renderRoutes;