UNPKG

@foxpage/foxpage-engine-react

Version:

foxpage react render engine

146 lines (145 loc) 6.18 kB
"use strict"; 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;