@foxpage/foxpage-engine-react
Version:
foxpage react render engine
146 lines (145 loc) • 6.18 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.timeout = exports.renderToHtml = void 0;
const react_1 = require("react");
const server_1 = __importDefault(require("react-dom/server"));
const lodash_1 = require("lodash");
const components_1 = require("./components");
async function creator(node, ctx, opt) {
var _a, _b, _c, _d, _e;
try {
const { id, name, children = [] } = node;
const component = (_a = ctx.componentMap) === null || _a === void 0 ? void 0 : _a.get(id);
// component check
if (!component) {
const msg = `render node ${name}@${id} failed, component is empty`;
(_b = ctx.logger) === null || _b === void 0 ? void 0 : _b.warn(msg);
if (opt.errorThrow) {
throw new Error(msg);
}
return null;
}
const { factory, meta } = component;
// factory check
if (!factory) {
const msg = `render node ${name}@${id} failed, factory is empty.`;
(_c = ctx.logger) === null || _c === void 0 ? void 0 : _c.warn(msg);
if (opt.errorThrow) {
throw new Error(msg);
}
return null;
}
const structure = (_d = ctx.structureMap) === null || _d === void 0 ? void 0 : _d.get(id);
const isCSREntry = meta.isCSREntry;
const { ssrEnable = true, props } = structure || {};
let childrenElements = [];
if ((!isCSREntry && ssrEnable) || (isCSREntry && opt.ssrEnable && ssrEnable)) {
childrenElements = await Promise.all(children.map(item => creator(item, ctx, opt)));
}
let element = undefined;
// csr node will be rendered by ssr
// csr node children be rendered bt ssrEnable
if (isCSREntry || ssrEnable) {
// is sys decorated and not decorated
// decorated will be setter by component self
if (meta.sysDecorated && !meta.decorated) {
const $element = (0, react_1.createElement)(factory, (0, lodash_1.cloneDeep)(props || node.props || {}), ...childrenElements);
element = (0, react_1.createElement)('div', {
'data-foxpage-node-id': node.id,
'data-foxpage-node-type': node.name,
style: {
display: 'contents',
},
}, $element);
}
else {
element = (0, react_1.createElement)(factory, (0, lodash_1.cloneDeep)(props || node.props || {}), ...childrenElements);
}
}
return element;
}
catch (e) {
(_e = ctx.logger) === null || _e === void 0 ? void 0 : _e.error(`create element ${node.name}@${node.id} failed.`, e);
throw e;
}
}
async function build(schemas, ctx, opt) {
const elements = await Promise.all(schemas.map(item => creator(item, ctx, opt)));
return elements;
}
/**
* render
* @param dsl parsed dsl
* @param ctx render context
* @param opt render options
* @returns html
*/
const renderToHtml = async (dsl = [], ctx, _opt = {}) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
const sessionId = new Date().getTime();
const opt = {
errorThrow: ((_a = ctx.renderConfig) === null || _a === void 0 ? void 0 : _a.errorThrow) || _opt.errorThrow,
ssrEnable: !_opt.reRender,
};
try {
if (dsl.length === 0) {
(_b = ctx.logger) === null || _b === void 0 ? void 0 : _b.info('parsed schemas is empty');
return '';
}
const buildCost = (_c = ctx.performanceLogger) === null || _c === void 0 ? void 0 : _c.call(ctx, 'buildTime' + `_${sessionId}`);
const { beforePageBuild, afterPageBuild } = ctx.hooks || {};
if (typeof beforePageBuild === 'function') {
await beforePageBuild(ctx);
}
// build
const elements = await build(dsl, ctx, opt);
if (elements.length === 0) {
(_d = ctx.logger) === null || _d === void 0 ? void 0 : _d.info('build elements is empty');
return '';
}
// create
let rootElement = (0, react_1.createElement)(components_1.Container, { ctx }, ...elements);
if (typeof afterPageBuild === 'function') {
rootElement = await afterPageBuild(ctx, rootElement);
}
buildCost();
// render
const mainRenderCost = (_e = ctx.performanceLogger) === null || _e === void 0 ? void 0 : _e.call(ctx, 'mainRenderTime' + `_${sessionId}`);
const html = server_1.default.renderToStaticMarkup(rootElement);
mainRenderCost();
return html;
}
catch (e) {
const { message, stack } = e;
if (message.startsWith('[Foxpage-business-error]')) {
(_f = ctx.logger) === null || _f === void 0 ? void 0 : _f.warn('render page failed: ', (stack || 'Empty stack') + '\n' + message + '\n');
}
else {
(_g = ctx.logger) === null || _g === void 0 ? void 0 : _g.error('render page failed: ', e);
}
if (!_opt.reRender) {
const csr = (_j = Array.from(((_h = ctx.componentMap) === null || _h === void 0 ? void 0 : _h.values()) || [])) === null || _j === void 0 ? void 0 : _j.find(item => { var _a; return !!((_a = item.meta) === null || _a === void 0 ? void 0 : _a.isCSREntry); });
if (csr) {
(_k = ctx.logger) === null || _k === void 0 ? void 0 : _k.info('change ssr to csr:');
_opt.reRender = true;
return await (0, exports.renderToHtml)(dsl, ctx, _opt);
}
}
throw e;
}
};
exports.renderToHtml = renderToHtml;
function timeout(promise, time) {
return Promise.race([
promise,
new Promise((_resolve, reject) => {
setTimeout(() => {
reject(new Error('timeout' + `(${time})`));
}, time);
}),
]);
}
exports.timeout = timeout;