builder-isv
Version:
ISV 模块本地预览与云构建器
322 lines (282 loc) • 9.97 kB
JavaScript
/**
* @author 花七
* @description 根据模块信息获取渲染后的页面信息
* @param params, queries, abcInfo, packageInfo
* */
;
const utils = require('./utils');
const moduleFactory = new (require('../models/moduleFactory'));
const fs = require('fs');
const _ = require('lodash');
const path = require('path');
const pageJsonToXtpl = require('isv-page-json-to-xtpl');
const zebraRender = require('isv-zebra-page-generator');
const raxRender = require('isv-rax-page-render');
const air = require('isv-page-json-to-xtpl/lib/air');
module.exports = function*(params, queries, headers, abcInfo, packageInfo) {
let type = params.type;
let name = params.name;
let moduleObj = moduleFactory.getModule(type, name);
let modulePath = moduleObj.modulePath;
//伪装个页面数据
let pageData = {
"spmA": "spmA",
"spmB": "spmB",
"keywords": ["demo"],
"description": "demo",
"title": "demo",
"extraLib": abcInfo.info && abcInfo.info.extraLib,
"platform": abcInfo.info && abcInfo.info.platform,
"guideName": packageInfo.upx && packageInfo.upx.guideName,
"layout": {
"version": "v1",
"modules": [
{
"group": abcInfo.group,
"name": abcInfo.name,
"version": '_dev'
}
]
},
"abs": {
"solution": {
"default": {
"assets": packageInfo.upx && packageInfo.upx.assets,
"terminalType": "mobile",
"language": "zh-cn",
"charset": "utf8",
"dev": true
}
}
}
};
pageData.abs.solution.default.dev = true;
var module = pageData.layout.modules[0];
var isBaseUpx = !!pageData.guideName; // 是否是基于upx的模块
if (!fs.existsSync(modulePath)) {
throw new Error('模块' + name + '不存在');
}
//本地模块
var depMap = {};
try {
depMap = JSON.parse(fs.readFileSync(path.join(modulePath, 'deps.json'), 'utf-8'));
} catch (e) {
throw new Error('读取 deps.json 失败,请尝试重启服务');
}
module.base = 'http://' + headers.host + '/' + type + '/' + name;
module.version = packageInfo.version;
module.versionForZebra = packageInfo.version;
module.depMap = depMap;
// module.id = _.uniqueId('');
var mockData = JSON.parse(fs.readFileSync(path.join(modulePath, 'mock', 'data.json')));
var mockAttr = JSON.parse(fs.readFileSync(path.join(modulePath, 'mock', 'attrs.json')));
module.data = mockData;
module.attrs = mockAttr;
//斑马
if (packageInfo.upx) {
if (packageInfo.upx.zebra) {
module.isZebraModule = true; // 添加斑马模块的标志
module.multiTceEntryPoint = true;
module.tceConfig = module.data;
module.dataSourceType = "tce";
}
module.terminalType = packageInfo.upx.terminalType; // 终端类型
}
var options = abcInfo.options;
if (options) {
//
// // 新增斑马solution 站点相关配置
module.solutionName = options.solutionName;
module.solutionBranch = options.solutionBranch;
//
// //存在调试vd配置
// //调试 vd 只有在本地绑定域名的情况下才会生效
var vd = options.devVd || options.vd;
if (vd) {
module = _.merge(module, vd);
}
//
// //调试TCE配置
var tceConfig = options.tceConfig;
if (tceConfig) {
module = _.merge(module, {tceConfig: tceConfig, dataSourceType: 'tce'});
if (!module.tceEntryPoint) {
module.tceEntryPoint = "data";
}
}
if (options.dataSourceType) {
module.dataSourceType = options.dataSourceType;
}
//数据源类型
//使用 vd 还是 tce
if (options.dataSourceType) {
module.dataSourceType = options.dataSourceType;
}
// 配置是否使用wormhole预览
module.disableZRender = options.disableZRender;
}
//
// // 将info字段复给modules
module.info = abcInfo.info;
//
// // debug('module:',module);
// //是否存在index.xtpl(静态渲染)
var xtplPath = path.join(modulePath, 'index.xtpl');
// debugMini('=====> xtplPath:', xtplPath);
var isExistModXtpl = fs.existsSync(xtplPath);
if (isExistModXtpl) {
//存在静态渲染,需要触发渲染,然后注入
module.dev = true;
module.modPath = module.name;
var moduleXtpl = fs.readFileSync(xtplPath);
var dataPolyfill = '{{set(attrs=$data.attrs)}}{{set(data=$data.data)}}';
var xtplString = dataPolyfill + moduleXtpl;
// 如果是基于新upx的,需要设置遍历,这样用于就可以直接获取 schema 变量了;
if (isBaseUpx) {
xtplString = '{{#each([$data.data])}}' + moduleXtpl + '{{/each}}';
}
//debug(xtplString);
if (module.data.attrs) {
utils.log.error('模块的 data 不能包含 attrs 字段');
module.data.attrs = module.attrs;
} else {
module.data.attrs = module.attrs;
}
var airParams = yield air.params(xtplString,
{
modules: [module],
$data: {attrs: module.attrs, data: module.data}
}
);
var airResult = yield air.render(pageJsonToXtpl.airPath, airParams);
var html = '';
//debug('airResult');
//debug(airResult);
if (airResult.success) {
html = airResult;
if (airResult.content.indexOf('AIR 渲染异常') >= 0) {
throw new Error('AIR 渲染异常:' + airResult.content);
}
} else {
html = yield pageJsonToXtpl.renderXtpl(xtplPath, {attrs: module.attrs, data: module.data});
}
module.html = html.content;
}
//
//
// var pageUrl = req.url;
var ua = headers['user-agent'];
var isAppClient = ua.indexOf('Weex') >= 0;
//
if (queries['wh_ttid'] === 'native' || (queries['wh_weex'] === 'true' && isAppClient)) {
pageJsonToXtpl.type = 'rx-bundle';
// 增加 weex 链路判断
if (pageData.extraLib === 'weex') {
pageJsonToXtpl.type = 'weex';
}
// res.header("Content-Type", "application/javascript;charset=utf-8");
} else if (queries['wh_block'] || queries['wh_chunk']) {
pageJsonToXtpl.type = 'rx';
// res.header("Content-Type", "application/javascript;charset=utf-8");
} else if (pageData.extraLib === 'weex') { // 如果是 weex 的话,使用指定的 solution
pageJsonToXtpl.type = 'weex-h5';
} else {
pageJsonToXtpl.type = pageJsonToXtpl.getSolutionType(pageData.abs.solution.default.assets);
}
//
// debugMini('pageData:', pageData);
//
var runConfig = {};
if (queries['wh_ttid'] === 'pc' || (module && module.terminalType === 'pc')) {
runConfig = {transformLayoutType: 'fiz', terminalType: 'pc'};
}
if (queries['wh_ttid'] === 'native' || (queries['wh_weex'] === 'true' && isAppClient)) {
runConfig.wh_ttid = 'native';
}
if (queries['wh_block'] || queries['wh_chunk']) {
runConfig.wh_chunk = 'true';
}
if (queries['debug']) {
runConfig.dev = true;
pageData.abs.solution.default.inline = true;
}
//
// debugMini('=====> runConfig:', runConfig);
//
//
// // === start: 斑马模块判断 ===
// // = 如果是斑马模块就走天猫那边的渲染逻辑
// var notZebraRender = [];
// modules.forEach(function (mod) {
//
// var isZebra = mod.isZebraModule;
// // var isUseTmallSolution = (mod.info.extraLib === 'reactjs' || (mod.info.platform && mod.info.platform[0] === 'pc')); // 要么是rx模块,要么是pc模块
// if (!isZebra) {
// debugMini('模块:', mod.name, '不是斑马模块');
// notZebraRender.push(mod); // 缓存起来
// }
//
// // if(!isUseTmallSolution){
// // debugMini('模块:',mod.name,'不是rx 或者 pc 模块');
// // notZebraRender.push(mod); // 缓存起来
// // }
//
// if (mod.disableZRender) {
// debugMini('模块:', mod.name, 'disable Zebra Render');
// notZebraRender.push(mod); // 缓存起来
// }
//
// });
// debugMini('====> notZebraRender:', notZebraRender);
// // === end ====
//
var result = {};
/**
* 渲染策略
* 1. 如果是斑马模块(无论是否基于upx),走斑马渲染逻辑
* 2. 否则,如果是 基于upx 的模块,则走 rax 渲染逻辑
* 3. 否则,就走 abs 渲染逻辑
*/
// 斑马渲染逻辑
if (module.isZebraModule) {
var str = '所调试的模块';
// if (isPageDev) { // 如果是页面级别的调试
// str = '\n=== 所调试的页面';
// if (pageAbcJSON.options) {
// runConfig.siteName = pageAbcJSON.options.solutionName;
// runConfig.siteBranch = pageAbcJSON.options.solutionBranch;
// }
// } else {
// 简单处理,使用第一个模块的solution配置
runConfig.siteName = module.solutionName;
runConfig.siteBranch = module.solutionBranch;
// }
utils.log.info(str + '将使用 tmall solution 渲染系统');
result = yield zebraRender.render(pageData, runConfig);
} else if (isBaseUpx) { // 使用基于 rax 的渲染逻辑
utils.log.info('模块使用 UPX 新规范渲染');
//console.log(pageData, runConfig);
result = yield raxRender.render(pageData, runConfig);
} else {
// var notRenderList = notZebraRender.map(function (mod) {
// return mod.name
// }).join(',');
// var str = '\n=== 模块' + notRenderList + ' ';
//
// if (runConfig.disableZRender) { // 页面级别disable
// str = '\n=== 所调试的页面主动关闭斑马渲染,';
// } else if (isPageDev && notZebraRender.length) {
// str = '\n=== 所调试的页面中模块' + notRenderList + '不开启斑马渲染,故';
// }
utils.log.info('仍旧使用原来的 solution 渲染模式');
// 使用 AIR 渲染
result = yield pageJsonToXtpl.run(pageData, runConfig);
}
//console.log(result);
if (result.success) {
var content = result.content;
return content;
} else {
throw new Error('渲染失败,错误信息:' + result.content);
}
};