UNPKG

builder-isv

Version:

ISV 模块本地预览与云构建器

322 lines (282 loc) 9.97 kB
/** * @author 花七 * @description 根据模块信息获取渲染后的页面信息 * @param params, queries, abcInfo, packageInfo * */ 'use strict'; 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); } };