diff --git a/ext/build.js b/ext/build.js index ff309aa..ceea454 100644 --- a/ext/build.js +++ b/ext/build.js @@ -1,65 +1,112 @@ const fs = require("fs-extra"); const path = require("path"); -const { spawn } = require("child_process"); const minimist = require("minimist"); +const webpack = require("webpack"); +const webExt = require("web-ext").default; + + +const DIST_PATH = path.join(__dirname, "../dist/ext"); +const UNPACKED_PATH = path.join(DIST_PATH, "unpacked"); const argv = minimist(process.argv.slice(2), { boolean: [ "package", "watch" ] , string: [ "mirroringAppId", "mode" ] , default: { - package: false - , watch: false - , mirroringAppId: "19A6F4AE" - , mode: "development" + package: false // Should package with web-ext + , watch: false // Should run webpack in watch mode + , mirroringAppId: "19A6F4AE" // Chromecast mirroring receiver app ID + , mode: "development" // webpack mode } }); +if (argv.package && argv.watch) { + console.error("Cannot package whilst watching files."); + process.exit(1); +} + +// If packaging, use production mode if (argv.package) { argv.mode = "production"; - argv.watch = false; } -const extensionName = "fx_cast"; -const extensionId = "fx_cast@matt.tf"; -const extensionVersion = "0.0.1"; +// Import webpack config and specify env values +const webpackConfig = require("./webpack.config.js")({ + extensionName: "fx_cast" + , extensionId: "fx_cast@matt.tf" + , extensionVersion: "0.0.1" + , mirroringAppId: argv.mirroringAppId +}); + +// Add mode to config +webpackConfig.mode = argv.mode; + +/** + * If watching files, output directly to dist. Unpacked + * directory is used as a staging area for web-ext builds. + */ +webpackConfig.output.path = argv.package + ? UNPACKED_PATH + : DIST_PATH; -const DIST_PATH = path.join(__dirname, "../dist/ext"); -const UNPACKED_PATH = path.join(DIST_PATH, "unpacked"); // Clean fs.removeSync(DIST_PATH); -const buildCmd = `web-ext build --overwrite-dest ` - + `--source-dir ${UNPACKED_PATH} ` - + `--artifacts-dir ${DIST_PATH} `; -const child = spawn( - `webpack --env.extensionName=${extensionName} ` - + `--env.extensionId=${extensionId} ` - + `--env.extensionVersion=${extensionVersion} ` - + `--env.mirroringAppId=${argv.mirroringAppId} ` - + `--mode=${argv.mode} ` - + `${argv.watch ? "--watch" : ""} ` - + `${argv.package ? "&&" + buildCmd : ""} ` - , { shell: true } -); +// Create webpack compiler instance +const compiler = webpack(webpackConfig); -child.stdout.pipe(process.stdout); -child.stderr.pipe(process.stderr); +if (argv.watch) { + // Start webpack watch + compiler.watch({}, handleCompilerOutput); +} else { + compiler.run((...args) => { + handleCompilerOutput(...args); -child.on("exit", () => { - if (argv.package) { - fs.remove(UNPACKED_PATH); - } else { - for (const file of fs.readdirSync(UNPACKED_PATH)) { - fs.moveSync(path.join(UNPACKED_PATH, file) - , path.join(DIST_PATH, file) - , { overwrite: true }); + if (argv.package) { + webExt.cmd.build({ + /** + * Webpack output at sourceDir is built into an extension + * archive at artifactsDir. + */ + sourceDir: UNPACKED_PATH + , artifactsDir: DIST_PATH + , overwriteDest: true + }, { + // Prevent auto-exit + shouldExitProgram: false + + }).then(() => { + // Only need the built extension archive + fs.remove(UNPACKED_PATH); + }) + } + }); +} + +/** + * Log errors and output formatted compilation info. + */ +function handleCompilerOutput (err, stats) { + // If there are fatal errors, log and exit + if (err) { + console.error(err.stack || err); + if (err.details) { + console.error(err.details); } - // Remove empty unpacked directory - fs.remove(UNPACKED_PATH); + return; } -}); + + // Get compilation info + const info = stats.toJson(); + + // Log errors/warnings + if (stats.hasErrors()) console.error(info.errors); + if (stats.hasWarnings()) console.warn(info.warnings); + + // Log formatted output + console.log(stats.toString()); +}