UNPKG

st-bundle

Version:

CLI for watching and bundling SpringType projects.

151 lines (150 loc) 6.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const convertSourceMap = require("convert-source-map"); const prettyTime = require("pretty-time"); const Bundle_1 = require("../bundle/Bundle"); const bundleStrings_1 = require("../bundle/bundleStrings"); const extensions_1 = require("../config/extensions"); const process_plugins_1 = require("../main/process_plugins"); const utils_1 = require("../utils/utils"); const MAX_FTL_MODULES = 5; function generateFTLJavaScript(modules) { const concat = utils_1.createConcat(true, '', '\n'); concat.add(null, bundleStrings_1.devStrings.openPackage('default', {})); for (const m of modules) { concat.add(null, bundleStrings_1.devStrings.openFile(m.props.fuseBoxPath)); concat.add(null, m.contents, m.sourceMap); concat.add(null, bundleStrings_1.devStrings.closeFile()); } concat.add(null, bundleStrings_1.devStrings.closePackage()); let stringContent = concat.content.toString(); let json = JSON.parse(concat.sourceMap); const sm = convertSourceMap.fromObject(json).toComment(); stringContent += '\n' + sm; return stringContent; } exports.generateFTLJavaScript = generateFTLJavaScript; function fasterThanLight(props) { const { ctx, bundleWriters, filePath } = props; if (ctx.config.target === 'server') { return; } if (!ctx.config.cache.enabled || !ctx.devServer) { return; } const cache = ctx.cache; const defaultPackage = ctx.packages.find(pkg => pkg.isDefaultPackage); const targetModule = defaultPackage.modules.find(item => item.props.absPath === filePath); if (targetModule) { // get the current cache (even if it's broken already) // we need to check if external dependencies didn't change const data = cache.getModuleCacheData(targetModule); if (!data) return; // check for FTL eligible extensions like CSS html and such if (extensions_1.FTL_ELIGIBLE_EXTENSIONS.indexOf(targetModule.props.extension) > -1) { // peform a full cylcle here ctx.log.info('FTL', `Entering FTL mode`); targetModule.read(true); targetModule.isCached = false; targetModule.captured = false; ctx.ict.sync('assemble_module_init', { module: targetModule }); // reset data so it can be read again an being not captured too. const ftlModules = ctx.assembleContext.getFTLModules(); if (ftlModules.length > MAX_FTL_MODULES) return; process_plugins_1.bundleResolveModule(targetModule); return ctx.ict.resolve().then(() => { ctx.assembleContext.setFTLModule(targetModule); return true; }); } // stop from accidentally working with a non-executable file if (!targetModule.isExecutable()) { return; } if (!data.fastAnalysis) { return; } ctx.ict.sync('assemble_module_init', { module: targetModule }); const targetBundle = bundleWriters.find(item => item.bundle.props.type === Bundle_1.BundleType.PROJECT_JS); if (!targetBundle) return; // it may happen that user just hit "save" without doing anything // isCached is set in attach_cache.ts in cache.restoreModule(module); // that's why this check followed by "assemble_module_init" it cannot happen earlier const oldAnalysis = data.fastAnalysis; targetModule.read(true); ctx.ict.sync('assemble_module_ftl_init', { module: targetModule }); const newAnalysis = targetModule.fastAnalyse(); // if there is a length difference - that's to continue if (oldAnalysis.imports.length !== newAnalysis.imports.length) return; // stop the difference // if arrays don't match we have some something changed for (let i = 0; i < oldAnalysis.imports.length; i++) { if (newAnalysis.imports[i].statement !== oldAnalysis.imports[i].statement) return; } const ftlModules = ctx.assembleContext.getFTLModules(); if (ftlModules.length > MAX_FTL_MODULES) return; ctx.log.info('FTL', `Entering FTL mode`); // restore replaceable, since we skip the assemble part + resolving the statements targetModule.fastAnalysis.replaceable = oldAnalysis.replaceable; targetModule.fastAnalysis.report.transpiled = false; ctx.ict.sync('assemble_fast_analysis', { module: targetModule }); targetModule.isCached = false; // manually triger the resolution for this module // skipping EVERYTHING else process_plugins_1.bundleResolveModule(targetModule); return ctx.ict.resolve().then(() => { ctx.assembleContext.setFTLModule(targetModule); return true; }); } } exports.fasterThanLight = fasterThanLight; function attachFTL(ctx) { let bundles; let packages; ctx.ict.on('soft_relod', props => { if (!bundles) return; const response = fasterThanLight({ ctx, filePath: props.info.filePath, bundleWriters: bundles }); if (response) { props.info.FTL = true; response.then(bundeResponse => { ctx.ict.sync('rebundle_complete', { bundles, packages, ctx, watcherAction: props.info.watcherProps.action, file: props.info.filePath, }); const l = ctx.assembleContext.getFTLModules().length; ctx.log.line(); ctx.log.echo(ctx.log.indent + '<bold><white><bgGreen> FTL SUCCESS </bgGreen></bold></white> in <bold>$time</bold> <dim>$total/$max in-memory</dim>', { time: prettyTime(process.hrtime(props.info.timeStart)), total: l, max: MAX_FTL_MODULES, }); ctx.log.line(); ctx.log.printBottomMessages(); }); } return props; }); ctx.ict.on('rebundle_complete', props => { bundles = props.bundles; packages = props.packages; return props; }); ctx.ict.on('complete', props => { bundles = props.bundles; packages = props.packages; return props; }); } exports.attachFTL = attachFTL;