builder-isv
Version:
ISV 模块本地预览与云构建器
154 lines (130 loc) • 3.91 kB
JavaScript
/**
* @author 龙喜<xiaolong.lxl@alibaba-inc.com>
* @description Renderer
*/
'use strict';
// https://nodejs.org/dist/latest-v6.x/docs/api/events.html
const EventEmitter = require('events');
const path = require('path');
const os = require('os');
const renderConfigLoader = require('../lib/renderConfigLoader');
const config = require('../config');
const utils = require('../lib/utils');
const Base = require('./base');
module.exports = class Renderer extends EventEmitter {
/**
* 构造一个构建器
* @param module 模块信息
*/
constructor(module) {
super();
// 设置上下文
this.config(module);
}
/**
* 配置上下文
* @param module 模块信息(INVOKE_TYPE_BUILD 情况下有 outputDir 属性)
*/
config(module) {
let rendererConfig = Renderer.getMatchedRendererConfig(module);
this.id = `${module.moduleType}/${module.moduleName}`;
// status: -1(错误) / 0(就绪) / 1(编译中)/ 2(编译成功)
this.status = 0;
this.module = module;
this.rendererConfig = rendererConfig;
this.outputDir = module.outputDir || path.join(config.defOptions.tmpPreviewDir, module.moduleType);
utils.log.verbose('outputDir', this.outputDir);
// 构建器匹配
if (this.builder && this.rendererConfig.match(module.abcInfo, module.packageInfo)) {
utils.log.verbose('构建器类型匹配,切换构建入口(entry)');
this.builder.changeEntry(module);
} else {
if (this.builder) {
this.builder.stop();
this.builder.destroy();
}
let Builder = rendererConfig.getBuilder();
this.builder = new Builder(module.outputDir ? Base.INVOKE_TYPE_BUILD : Base.INVOKE_TYPE_PREVIEW);
// 所有事件透传
this.builder.addListener('compileFailed', (err) => {
this.status = -1;
this.error = err;
this.emit('compileFailed', err);
});
this.builder.addListener('compileStart', () => {
this.status = 1;
this.emit('compileStart');
});
this.builder.addListener('compileSucceed', () => {
this.status = 2;
this.error = null;
this.emit('compileSucceed');
});
this.builder.addListener('compileFinished', () => {
this.emit('compileFinished');
});
}
}
/**
* 页面渲染器
* @param params
* @param queries
* @param headers
* @param {JSONStore} abcInfo
* @param {JSONStore} packageInfo
*/
*render(params, queries, headers, abcInfo, packageInfo) {
return yield this.rendererConfig.render(params, queries, headers, abcInfo, packageInfo);
}
/**
* 开始构建
*/
build() {
if (this.status !== 0) {
throw new Error('构建器已经运行过了');
}
this.status = 1;
// 开始构建
this.builder.start({
cwd: this.module.modulePath,
module: this.module,
outputDir: this.outputDir
});
}
/**
* 等待构建完成,构建错误抛出
* @returns {Promise}
*/
waitUntilBundleFinished() {
return new Promise((resolve, reject) => {
if (this.status === 0 || this.status === 1) {
this.once('compileFinished', () => {
if (this.status === -1) {
reject(this.error);
} else {
resolve();
}
});
} else if (this.status === -1) {
reject(this.error);
} else {
resolve();
}
});
}
/**
* 获取匹配的渲染器配置
* @param module
* @returns {*}
*/
static getMatchedRendererConfig(module) {
let abcInfo = module.abcInfo;
let packageInfo = module.packageInfo;
for (let i = 0, renderers = renderConfigLoader.renderers; i < renderers.length; ++i) {
if (renderers[i].match(abcInfo, packageInfo)) {
return renderers[i];
}
}
throw new Error('找不到匹配的渲染器');
}
};