UNPKG

fuse-box

Version:

Fuse-Box a bundler that does it right

251 lines (218 loc) • 8.06 kB
import { FuseBox } from "./FuseBox"; import { WorkFlowContext } from "./WorkflowContext"; import { BundleProducer } from "./BundleProducer"; import { FuseProcess } from "../FuseProcess"; import { HotReloadPlugin } from "../plugins/HotReloadPlugin"; import { SocketServer } from "../devServer/SocketServer"; import { File } from "./File"; import { BundleSplit } from "./BundleSplit"; import * as path from "path"; import { BundleTestRunner } from "../BundleTestRunner"; import { Config } from "../Config"; import { QuantumItem, QuantumSplitResolveConfiguration } from "../quantum/plugin/QuantumSplit"; import { BundleAbstraction } from "../quantum/core/BundleAbstraction"; import { PackageAbstraction } from "../quantum/core/PackageAbstraction"; export class Bundle { public context: WorkFlowContext; public watchRule: string; public arithmetics: string; public process: FuseProcess = new FuseProcess(this); public onDoneCallback: any; public webIndexPriority = 0; public generatedCode: Buffer; public bundleAbstraction: BundleAbstraction; public packageAbstraction: PackageAbstraction; public lastChangedFile: string; public webIndexed = true; public splitFiles: Map<string, File>; public bundleSplit: BundleSplit; public quantumItem: QuantumItem; constructor(public name: string, public fuse: FuseBox, public producer: BundleProducer) { this.context = fuse.context; this.context.bundle = this; // re-assign the parent producer fuse.producer = producer; this.setup(); } public watch(rules?: string): Bundle { this.watchRule = rules ? rules : "**"; return this; } public globals(globals: any): Bundle { this.context.globals = globals; return this; } public tsConfig(fpath: string): Bundle { this.context.tsConfig = fpath; return this; } public shim(shimConfig: any): Bundle { this.context.shim = shimConfig; return this; } /** Enable HMR in this bundle and inject HMR plugin */ public hmr(opts?: any): Bundle { if (!this.producer.hmrAllowed) { return this; } /** Only one is allowed to hava HMR related code */ if (!this.producer.hmrInjected) { opts = opts || {}; opts.port = this.producer.devServerOptions && this.producer.devServerOptions.port || 4444; let plugin = HotReloadPlugin({ port: opts.port, uri: opts.socketURI }); this.context.plugins = this.context.plugins || []; this.context.plugins.push(plugin); // Should happen only once! this.producer.hmrInjected = true; } /** * Whenever socket server is initialized * This will allow use to enable HMR on any bundle within current producer */ this.producer.sharedEvents.on("SocketServerReady", (server: SocketServer) => { this.fuse.context.sourceChangedEmitter.on((info) => { if (this.fuse.context.isFirstTime() === false) { this.fuse.context.log.echo(`Source changed for ${info.path}`); server.send("source-changed", info); } }); }); return this; } public alias(key: any, value: any): Bundle { this.context.addAlias(key, value); return this; } public split(rule: string, str: string): Bundle { const arithmetics = str.match(/(\S+)\s*>\s(\S+)/i) if (!arithmetics) { throw new Error("Can't parse split arithmetics. Should look like:") } const bundleName = arithmetics[1]; const mainFile = arithmetics[2]; if (this.context.experimentalFeaturesEnabled) { this.producer.fuse.context.quantumSplit(rule, bundleName, mainFile); } else { if (!this.bundleSplit) { this.bundleSplit = new BundleSplit(this); } this.bundleSplit.getFuseBoxInstance(bundleName, mainFile); this.bundleSplit.addRule(rule, bundleName); } return this; } /** Override cache option */ public cache(cache: boolean): Bundle { this.context.useCache = cache; return this; } public splitConfig(opts: QuantumSplitResolveConfiguration): Bundle { if (this.context.experimentalFeaturesEnabled) { this.producer.fuse.context.configureQuantumSplitResolving(opts); } else { if (!this.bundleSplit) { this.bundleSplit = new BundleSplit(this); } if (opts.browser) { this.bundleSplit.browserPath = opts.browser; } if (opts.server) { this.bundleSplit.serverPath = opts.server; } if (opts.dest) { this.bundleSplit.dest = opts.dest; } } return this; } /** Log */ public log(log: boolean): Bundle { this.context.doLog = log; this.context.log.printLog = log; return this; } /** * Adds a plugin or a chain of plugins * e.g * in case of one plugin * plugin(HTMLPlugin()) * In case of a chain: * * plugin("*.html", HTMLPlugin()) * @param args Plugin */ public plugin(...args): Bundle { this.context.plugins = this.context.plugins || []; this.context.plugins.push(args.length === 1 ? args[0] : args); return this; } /** * natives({ process : false }) * @param opts */ public natives(opts: any): Bundle { this.context.natives = opts; return this; } public instructions(arithmetics: string): Bundle { this.arithmetics = arithmetics; return this; } public target(target: string): Bundle { this.context.target = target; return this; } public sourceMaps(params: any): Bundle { this.context.setSourceMapsProperty(params); return this; } public test(str: string = "**/*.test.ts", opts: any) { opts = opts || {}; opts.reporter = opts.reporter || "fuse-test-reporter"; opts.exit = true; // include test files to the bundle const clonedOpts = Object.assign({}, this.fuse.opts); const testBundleFile = path.join(Config.TEMP_FOLDER, "tests", new Date().getTime().toString(), "/$name.js"); clonedOpts.output = testBundleFile; // adding fuse-test dependency to be bundled str += ` +fuse-test-runner ${opts.reporter} -ansi`; const fuse = FuseBox.init(clonedOpts); fuse.bundle("test") .instructions(str) .completed(proc => { const bundle = require(proc.filePath); let runner = new BundleTestRunner(bundle, opts); runner.start(); }); fuse.run(); } public exec(): Promise<Bundle> { return new Promise((resolve, reject) => { this.fuse .initiateBundle(this.arithmetics || "", () => { this.process.setFilePath(this.fuse.context.output.lastWrittenPath); if (this.onDoneCallback && this.producer.writeBundles === true) { this.onDoneCallback(this.process); } return resolve(this); }).then(source => { }).catch(e => { console.error(e); return reject(reject); }); return this; }); } public completed(fn: (process: FuseProcess) => void): Bundle { this.onDoneCallback = fn; return this; } private setup() { // modifying the output name this.context.output.setName(this.name); if (this.context.useCache) { this.context.initCache(); this.context.cache.initialize(); } } }