UNPKG

builder-isv

Version:

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

165 lines (142 loc) 4.75 kB
/** * @author 龙喜<xiaolong.lxl@alibaba-inc.com> * @description 渲染器工厂 */ 'use strict'; const fs = require('fs'); const path = require('path'); const config = require('../config'); const Renderer = require('./renderer'); const moduleFactory = new (require('./moduleFactory')); const utils = require('../lib/utils'); // https://nodejs.org/dist/latest-v6.x/docs/api/events.html const EventEmitter = require('events'); const Base = require('./base'); let singleton; module.exports = class RendererFactory extends EventEmitter { constructor(invokeType) { if (singleton) { return singleton; } super(); singleton = this; this.invokeType = invokeType || Base.INVOKE_TYPE_PREVIEW; /** * 渲染器上下文 pool * @type {Renderer[]} rendererPool */ this.rendererPool = []; // renderer 等待队列,优先满足最先等待者 this.rendererWaiters = []; } // pool renderer 最大数量 // 使用 getter 的方式兼容 Node.js 4.x.x static get MAX_RENDERER() { return 3; } /** * 获取匹配的渲染器上下文 * @param type 模块类型 * @param name 模块名称 * @param inputDir INVOKE_TYPE_BUILD 情况下传递 * @param outputDir INVOKE_TYPE_BUILD 情况下传递 * @returns {*} */ *getRenderer(type, name, inputDir, outputDir) { let module = moduleFactory.getModule(type, name, inputDir); // 预览 if (this.invokeType === Base.INVOKE_TYPE_PREVIEW) { let rendererContext = yield this.getRendererFromPool(module); if (rendererContext.id === `${module.moduleType}/${module.moduleName}`) { utils.log.verbose('获取到上次使用的渲染器实例'); return rendererContext; } else { utils.log.verbose('获取到渲染器实例,重新设置上下文'); rendererContext.config(module); try { rendererContext.build(); } catch (e) { utils.log.verbose('构建器已经运行过了'); } return rendererContext; } } else { // 云构建 module.outputDir = outputDir; return this.createRendererContext(module); } } /** * 从渲染器上下文 pool 获取匹配的渲染器上下文(受限于 MAX_RENDERER,可能会阻塞) * @param module * @returns {*} */ *getRendererFromPool(module) { // 如果匹配到上次此模块使用的 renderer,直接复用 let nameMatchedRenderer = this.rendererPool.filter((rendererContext) => { return rendererContext.id === `${module.moduleType}/${module.moduleName}`; }); if (nameMatchedRenderer.length) { return nameMatchedRenderer[0]; } // 否则,如果未达到 pool 最大值,新增匹配的 renderer if (this.rendererPool.length < RendererFactory.MAX_RENDERER) { utils.log.verbose('新增渲染器到渲染器池'); this.rendererPool.push(this.createRendererContext(module)); return this.rendererPool[this.rendererPool.length - 1]; } else { // 获取空闲的 renderer let idleRenderer = this.rendererPool.filter((rendererContext) => { return rendererContext.status !== 1; }); if (idleRenderer.length) { utils.log.verbose('找到空闲的渲染器'); return idleRenderer[0]; } else { utils.log.verbose('等待渲染器释放'); // 等待空闲的 renderer return new Promise((resolve, reject) => { this.rendererWaiters.push({ module: module, callback: (rendererContext) => { if (rendererContext) { resolve(rendererContext); } else { reject(new Error('找不到匹配的渲染器')); } } }); }); } } } /** * 创建一个 renderer context * @returns {*|exports|module.exports} */ createRendererContext(module) { let rendererContext = new Renderer(module); if (this.invokeType === Base.INVOKE_TYPE_PREVIEW) { rendererContext.addListener('compileFinished', () => { utils.log.verbose('渲染器释放,通知等待队列'); this.distributeIdleRenderers(); }); } rendererContext.build(); return rendererContext; } /** * 将空闲的 renderer 分配给等待者 */ distributeIdleRenderers() { // 获取空闲的 renderer let idleRenderer = this.rendererPool.filter((rendererContext) => { return rendererContext.status !== 1; }); while (this.rendererWaiters.length > 0 && idleRenderer.length > 0) { this.rendererWaiters[0].callback(idleRenderer[0]); this.rendererWaiters.shift(); idleRenderer.shift(); } } };