UNPKG

isv-zebra-page-generator

Version:

斑马页面(solution)生成器

265 lines (241 loc) 10.5 kB
var fs = require('fs'); var path = require('path'); var Debug = require('debug'); var debug = Debug('zebra'); var debugMini = Debug('zebra:mini'); var debugError = Debug('zebra:error'); var debugExtra = Debug('zebra:extra'); var _ = require('lodash'); var request = require('sync-request'); var Client = require('isv-module-info'); var upxClient = Client.upxClient('production'); // 通过gitlab方式获取 // 例如:http://gitlab.alibaba-inc.com/zebra-solution/tb-rx/raw/master/build/index-native.xtpl var URL_SOLUTION_BASE = 'http://gitlab.alibaba-inc.com/zebra-solution/${siteName}/raw/${branch}/build/${fileName}'; function readFileOrEmpty(path) { try { debugMini('=====> 读取 ' + path + '文件内容'); return fs.readFileSync(path, 'utf8'); } catch (err) { debugError('=====> 读取 ' + path + '文件内容失败:', err); return ""; } } function removeDeps(deps){ // 去除pc端公共的库引用,比如io等,因为这些都是通过 solution 引入了; var str = JSON.stringify(deps); // 转换成str var list = ['loader','node','util','dom','event-gesture','event-dom','event-custom','event','io','ua','querystring','promise','path','json','feature','base','attribute','anim','url','cookie','@ali/lib-promise/build/polyfillB']; list.forEach(function(modName){ var reg = new RegExp('\"'+modName+'\"','g'); str = str.replace(reg,'\"\"'); }); debug('=====> 去除公共模块之后的依赖(字符串):',str); debug('=====> 去除公共模块之后的依赖(json);',JSON.parse(str)); return JSON.parse(str); } function writeFileOrNone(path, data) { fs.writeFile(path, data, 'utf8', function(err) { if (err) { console.log('=====> 写入数据到' + path + '失败:', err); debugError('=====> 想要写入的数据:' + data); return; } debugMini('=====> 已将数据写入到:' + path); debug('=====> 文件内容:' + data); }); } // 计算同步执行callback所花费的时间 function calcTime(fn, msg) { var oStart = new Date(); fn(); var oEnd = new Date(); console.log(msg, ':', (oEnd - oStart) / 1000, 's'); } function parseOrFalse(str) { var json = {} try { if (str.length) { json = JSON.parse(str); debugMini('=====> 将字符串解析成 JSON 成功'); debug('=====> 获得的 JSON 的内容:' + json); return json; } else { return false; } } catch (err) { debugError('=====> 将字符串解析成 JSON 失败:', err); debugError('=====> 原字符串内容:' + str); return false; } } // 获取远程站点上的文件,如果不存在就在本地solution文件夹下获取 // siteName: 站点名字,比如 'tb-rx' // fileName: 想要获取的文件 // isJsonFile: 是否是json文件 function getFileContent(siteName, branch, fileName, isJsonFile) { var filePath = path.join(__dirname, 'solution', fileName); var targetUrl = URL_SOLUTION_BASE.replace('${siteName}', siteName).replace('${branch}', branch).replace('${fileName}', fileName); var res = request('GET', targetUrl); var result = res.getBody().toString(); debug('=====> ' + targetUrl + '请求结果:', result); var filePath = path.join(__dirname, 'solution', fileName); // 如果解析失败,使用之前缓存的文件 // result = false; if (!result) { // 使用本地备用的 console.log('获取站点', siteName, '下的' + fileName + '失败,改用缓存文件:', filePath); result = readFileOrEmpty(filePath); if (!result) { // 如果读取不到本地文件内容,需要提示其重试 console.log('==== 本地缓存solution文件读取为空,将渲染失败,请重新dev !! ===='); } debug('=====> 内置备用的' + fileName + '内容', result); } else { // 如果解析成功就缓存到本地文件 debug('=====> 获取站点', siteName, '下的' + fileName + '成功:', result); writeFileOrNone(filePath, result); } // 如果是json文件,需要解析成json格式 if (isJsonFile) { result = parseOrFalse(result); } return result; } // 根据配置获取xtpl模板的后缀 function getPageSuffix(runConfig) { var suffix = ''; // 默认是无线页面 if (runConfig.terminalType === 'pc') { suffix = '-pc'; } else if (runConfig.wh_ttid === 'native') { suffix = '-native'; } return suffix; } function getXtpl(siteName, branch, runConfig, seed, pageData) { var modules = pageData.layout.modules; // 获取modules var suffix = getPageSuffix(runConfig); var xtplName = 'index' + suffix + '.xtpl'; // 获取xtpl文件 var xtpl = getFileContent(siteName, branch, xtplName); // 貌似不能直接设置$zebra,自定义字段 xtpl = "{{set($zebra = $data.$zebra)}}{{set($pageData = $data.$pageData)}}" + xtpl; // ======= kimi6 & kissy: 也需要替换 block("body") ====== var platform = pageData.platform && pageData.platform[0]; // console.log('44444,', platform, pageData.extraLib); if (platform === 'pc' || (platform === 'mobile' && pageData.extraLib == 'null')) { // console.log('5555', platform, pageData.extraLib); var REG_PC_HTML = /\{{3}block\s*\(\"body\"\)\}{3}/g; // 同时需要将 {{{block ("body")}}} 元素替换成 特定的 html片段 var htmlCode = '{{#each($zebra.components)}}<div class="module-wrap J_Mod {{name}}" data-spm="{{spmC}}" id="J_{{moduleId}}" data-name="{{name}}" data-group="{{group}}" data-version="{{version}}">{{{html}}}</div>{{/each}}'; xtpl = xtpl.replace(REG_PC_HTML, htmlCode); // ===== end ====== } // 如果是pc端的文件,默认引用资源文件 index-pc.js,本地调试需要临时替换成 index.js if (runConfig.terminalType === 'pc') { // 匹配模板的名字声明 var REG_PC = /\'\/index-pc\'/g; xtpl = xtpl.replace(REG_PC, "'/index'"); // 替换成pc } else if (runConfig.wh_ttid === 'native') { // 如果是native var requires = []; modules.forEach(function(mod) { requires = requires.concat(seed.modules[mod.group + '/' + mod.name + '/index-native.xtpl'].requires); }); var strReq = ''; _.uniq(requires).forEach(function(req) { strReq += '{{require("' + req + '")}}'; }); var REG_NATIVE_SOURCE = /\{{3}sourceCode\}{3}/g; xtpl = xtpl.replace(REG_NATIVE_SOURCE, strReq + '{{{sourceCode}}}'); // 替换成pc debugMini('=====> 获取的依赖表:', strReq); } var HACK_REG = /set\(modName= /; xtpl = xtpl.replace(HACK_REG, "set\(modName= 'upx/tb-mod/' + "); return xtpl; } // 组装成斑马渲染参数 function zebraParams(seed, xtpl, zebraData) { return { "page": { "templates": { "index.xtpl": xtpl, //模板入口,必选 "seed.json": seed && JSON.stringify(seed) } }, "data": { "$zebra": zebraData, "page": zebraData.$pageData }, "intranet": true //是否内网,默认true (可选) } } // 重新装配用于斑马模块的渲染数据 // 主要是映射数据关系 function reassemble(pageData, runConfig) { var isBaseUpx = !!pageData.guideName; var newData = {}; newData.isLocal = true; newData.spma = pageData.spmA; newData.spmb = pageData.spmB; newData.keywords = pageData.keywords && pageData.keywords.join(','); newData.description = pageData.description; newData.title = pageData.title; newData.$pageData = {}; newData.components = pageData.layout.modules.map(function(mod) { var newMod = {}; newMod.name = mod.name; newMod.fullName = isBaseUpx ? ['upx', mod.group, mod.name].join('/') : [mod.group, mod.name].join('/'); newMod.version = mod.versionForZebra; newMod.moduleId = "module_" + mod.id; newMod.config = mod.attrs; newMod.dataId = mod.id; newMod.rmcId = mod.id; newMod.html = mod.html; newMod.group = mod.group; newData.$pageData[mod.id] = mod.data; // tce 相关配置 newMod.dataSourceType = mod.dataSourceType; newMod.tceEntryPoint = mod.tceEntryPoint; newMod.tceConfig = mod.tceConfig; // 针对native,增加sourceCode字段,用于直接输出 if (runConfig.wh_ttid === 'native') { var cwd = process.cwd(); // 获取当前工作目录 // native 缓存文件 var cacheDir = path.join(cwd, 'mod', mod.name, CACHE_DIR); var targetNativePath = path.join(cacheDir, CACHE_SOURCE_NATIVE); // native 源码 var targetOriginPath = path.join(cacheDir, CACHE_SOURCE_ORIGIN); // index 源码 newMod.sourceCode = readFileOrEmpty(targetNativePath); debugMini('=====> 读取缓存源码(打包后)路径', targetNativePath); debug('=====> 读取到的打包文件内容:', newMod.sourceCode); // 做一层兼容,如果读取不到 native 源码,就去读index源码 if (!newMod.sourceCode) { console.log('从', targetNativePath, '读取到的内容为空,转而读取', targetOriginPath); newMod.sourceCode = readFileOrEmpty(targetOriginPath); debug('=====> 读取到的打包文件内容:', newMod.sourceCode); } } return newMod; }); newData.modules = _.clone(newData.components); // 用于native渲染的字段 return newData; } function getEndType(runConfig){ var endType = 'web'; if(runConfig.terminalType === 'pc'){ endType = 'pc'; } else if(runConfig.wh_ttid === 'native') { endType = 'native'; } return endType; } module.exports = { readFileOrEmpty: readFileOrEmpty, writeFileOrNone: writeFileOrNone, calcTime: calcTime, getFileContent: getFileContent, getPageSuffix: getPageSuffix, upxClient: upxClient, getXtpl: getXtpl, zebraParams: zebraParams, reassemble: reassemble, getEndType: getEndType, parseOrFalse: parseOrFalse, removeDeps: removeDeps }