UNPKG

fusox

Version:

Command line wrapper for fuse-box

284 lines (246 loc) 10.2 kB
const fsb = require('fuse-box') const {parseBoolean, findExistingFile, getTransparentCorsSnippet, printHeader, getFreePort} = require('../helpers') const {existsSync} = require('fs') const util = require('util') const path = require('path') const {spawn} = require('child_process') const {YAMLPlugin} = require('fuse-box-yaml') const requireGlobal = require('requireg') module.exports = {parseBuildElectronFlags, buildElectronCommand} function parseBuildElectronFlags (args, flags) { let electron = null try { // try to find electron in source's node_modules directory let electronPath = require.resolve('electron', {paths: [flags.nodeModulesPath]}) electron = require(electronPath) } catch (err) { try { // try to find electron globally electron = requireGlobal('electron') } catch (err) {} } if ( ! electron) { throw new Error('Could not find module "electron", make sure you have it installed') } let customMainFile = args.main let customIndexFile = args.index let customRendererFile = args.renderer let assetsDestinationPath = flags.destinationPath let assetsWebPathResolver = (f) => './' + f let assetsMainPath = 'dist' let assetsRendererPath = '.' let openApplicationInBrowser = args.open === undefined ? false : parseBoolean(args.open) let runDevServer = flags.runApplication || openApplicationInBrowser let watchForChanges = args.watch === undefined ? runDevServer : parseBoolean(args.watch) // let treeshakeCode = args.treeshake === undefined ? true : parseBoolean(args.treeshake) let hashFileNames = args.hash === undefined ? false : parseBoolean(args.hash) let customMainFilePath = customMainFile && flags.resolveSourcePath(customMainFile) let defaultMainFilePath = flags.resolveSourcePath('index.ts') let mainFilePath = findExistingFile(customMainFilePath, defaultMainFilePath) if (!mainFilePath || !existsSync(mainFilePath)) { throw new Error(util.format( 'Could not find main file at "%s" or "%s", see "--main" option', flags.resolveSourcePathRelative(customMainFilePath), flags.resolveSourcePathRelative(defaultMainFilePath) )) } let mainFile = mainFilePath && path.basename(mainFilePath) let mainFilePathRelative = mainFilePath.replace(flags.sourcePath + '/', '') let customRendererFilePath = customRendererFile && flags.resolveSourcePath(customRendererFile) let defaultRendererFilePath = flags.resolveSourcePath('renderer.tsx') let alternateRendererFilePath = flags.resolveSourcePath('renderer.ts') let rendererFilePath = findExistingFile(customRendererFilePath, defaultRendererFilePath, alternateRendererFilePath) let rendererFile = rendererFilePath && path.basename(rendererFilePath) if (!rendererFilePath || !existsSync(rendererFilePath)) { throw new Error('Could not find the renderer file, see "--renderer" option') } if (!rendererFilePath || !existsSync(rendererFilePath)) { throw new Error(util.format( 'Could not find renderer file at "%s" or "%s" or "%s", see "--renderer" option', flags.resolveSourcePathRelative(customRendererFilePath), flags.resolveSourcePathRelative(defaultRendererFilePath), flags.resolveSourcePathRelative(alternateRendererFilePath) )) } let rendererFilePathRelative = rendererFilePath.replace(flags.sourcePath + '/', '') let customIndexFilePath = customIndexFile && flags.resolveSourcePath(customIndexFile) let defaultIndexFilePath = flags.resolveSourcePath('index.html') let fallbackIndexFilePath = path.resolve(__dirname, '../assets/electron.html') let indexFilePath = findExistingFile(customIndexFilePath, defaultIndexFilePath, fallbackIndexFilePath) let indexFile = indexFilePath && path.basename(indexFilePath) let indexFileAssetsPath = '.' if (!indexFilePath || !existsSync(indexFilePath)) { throw new Error('Could not find the index file, see "--index" option') } let appName = flags.appName || rendererFile.replace(path.extname(rendererFile), '') return { ...flags, electron, mainFile, mainFilePath, mainFilePathRelative, indexFile, indexFilePath, indexFileAssetsPath, rendererFile, rendererFilePath, rendererFilePathRelative, assetsDestinationPath, assetsWebPathResolver, assetsMainPath, appName, assetsRendererPath, runDevServer, watchForChanges, openApplicationInBrowser, // treeshakeCode, hashFileNames } } function buildElectronCommand (flags) { return Promise.all([ buildForElectronMain(flags), buildForElectronRenderer(flags) ]).then(() => { if (flags.runApplication) { let mainBundlePath = path.resolve(flags.destinationPath, 'index.js') let child = spawn(flags.electron, ['.'], { shell: true, cwd: flags.destinationPath, stdio: 'inherit' }) // close process if user quits electron application child.on('close', (code) => process.exit(code)) } }) } function buildForElectronMain (flags) { let fuse = fsb.FuseBox.init({ target: 'server', homeDir: flags.sourcePath, modulesFolder: flags.nodeModulesPath, output: util.format('%s/$name.js', flags.destinationPath), tsConfig: flags.tsconfigPath, sourceMaps: flags.generateSourceMaps, hash: flags.hashFileNames, cache: flags.useCache, ensureTsConfig: false, plugins: [ YAMLPlugin(), // fsb.EnvPlugin(flags.envConfig), fsb.CopyPlugin({ useDefault: false, files: flags.assetFilesExtensions, dest: '.', resolve: flags.assetsMainPath }), fsb.ReplacePlugin(flags.processEnvConfig), flags.mode === 'production' && flags.uglifyCode && fsb.UglifyESPlugin(), // flags.mode === 'production' && fsb.QuantumPlugin({ // target: 'server', // treeshake: flags.treeshakeCode, // uglify: flags.uglifyCode, // bakeApiIntoBundle: 'main', // }) ] }) let mainBundle = fuse.bundle('index') .target('server') .instructions(util.format('> [%s]', flags.mainFilePathRelative)) if (flags.watchForChanges) { mainBundle.watch() } printHeader('Launching fuse-box for "electron main"') return fuse.run() } function buildForElectronRenderer (flags) { return getFreePort(flags.defaultDevServerPort) .then((devServerPort) => { flags.devServerPort = devServerPort if (flags.globalName) { printHeader('Renderer package exported as window["%s"] in browser', flags.globalName) } let fuse = fsb.FuseBox.init({ homeDir: flags.sourcePath, modulesFolder: flags.nodeModulesPath, output: util.format('%s/$name.js', flags.destinationPath), tsConfig: flags.tsconfigPath, sourceMaps: flags.generateSourceMaps, hash: flags.hashFileNames, cache: flags.useCache, ensureTsConfig: false, globals: flags.globalName ? {default: flags.globalName} : null, plugins: [ YAMLPlugin(), fsb.WebIndexPlugin({ template: flags.indexFilePath, path: flags.indexFileAssetsPath }), [fsb.StylusPlugin(), fsb.PostCSSPlugin(flags.postCssConfig), fsb.CSSResourcePlugin({ dist: flags.assetsDestinationPath, resolve: flags.assetsWebPathResolver }), fsb.CSSPlugin()], [fsb.SassPlugin(), fsb.PostCSSPlugin(flags.postCssConfig), fsb.CSSResourcePlugin({ dist: flags.assetsDestinationPath, resolve: flags.assetsWebPathResolver }), fsb.CSSPlugin()], [fsb.LESSPlugin(), fsb.PostCSSPlugin(flags.postCssConfig), fsb.CSSResourcePlugin({ dist: flags.assetsDestinationPath, resolve: flags.assetsWebPathResolver }), fsb.CSSPlugin()], [fsb.PostCSSPlugin(flags.postCssConfig), fsb.CSSResourcePlugin({ dist: flags.assetsDestinationPath, resolve: flags.assetsWebPathResolver }), fsb.CSSPlugin()], // fsb.EnvPlugin(flags.envConfig), fsb.CopyPlugin({ useDefault: false, files: flags.assetFilesExtensions, dest: '.', resolve: flags.assetsRendererPath }), fsb.JSONPlugin(), fsb.ReplacePlugin(flags.processEnvConfig), flags.mode === 'production' && flags.uglifyCode && fsb.UglifyESPlugin(), // flags.mode === 'production' && fsb.QuantumPlugin({ // target: 'browser', // treeshake: flags.treeshakeCode, // uglify: flags.uglifyCode, // bakeApiIntoBundle: flags.appName // }) ] }) // todo: bundle splitting disabled until a fix is available https://github.com/fuse-box/fuse-box/issues/1119 // let rendererVendorsBundle = fuse.bundle('vendors') // .target('browser') // .instructions(util.format('~ %s', flags.rendererFilePathRelative)) // // let rendererBundle = fuse.bundle('renderer') // .target('browser') // .instructions(util.format('!> [%s]', flags.rendererFilePathRelative)) let rendererBundle = fuse.bundle('renderer') .target('browser') .instructions(util.format('> %s %s', flags.rendererFilePathRelative, flags.dynamicFilesInstructions)) if (flags.runCorsProxy) { rendererBundle.plugin(fsb.BannerPlugin(getTransparentCorsSnippet( flags.envConfig.CORS_PROXY_HOST, flags.envConfig.CORS_PROXY_PORT, flags.envConfig.NODE_ENV ))) } if (flags.runDevServer) { if (flags.defaultDevServerPort !== flags.devServerPort) { printHeader('Dev server port "%s" already in use, fallback to "%s"', flags.defaultDevServerPort, flags.devServerPort) } fuse.dev({ port: flags.devServerPort, open: flags.openApplicationInBrowser }) } if (flags.watchForChanges) { rendererBundle.watch().hmr({port: flags.devServerPort}) } printHeader('Launching fuse-box for "electron renderer"') return fuse.run() }) }