UNPKG

@quasar/app-webpack

Version:

Quasar Framework App CLI with Webpack

156 lines (127 loc) 4.53 kB
const { readFileSync } = require('node:fs') const { join, dirname } = require('node:path') const cloneDeep = require('lodash/cloneDeep.js') const webpack = require('webpack') const WebpackDevServer = require('webpack-dev-server') const { AppDevserver } = require('../../app-devserver.js') const { log, warn, fatal } = require('../../utils/logger.js') const { spawn } = require('../../utils/spawn.js') const { getPackagePath } = require('../../utils/get-package-path.js') const { quasarElectronConfig } = require('./electron-config.js') function wait (time) { return new Promise(resolve => { setTimeout(resolve, time) }) } module.exports.QuasarModeDevserver = class QuasarModeDevserver extends AppDevserver { #pid = 0 #server = null #watcherList = [] #killedPid = false #electronExecutable constructor (opts) { super(opts) const electronPkgPath = getPackagePath('electron/package.json', this.ctx.appPaths.appDir) const electronPkg = JSON.parse( readFileSync(electronPkgPath, 'utf-8') ) this.#electronExecutable = join(dirname(electronPkgPath), electronPkg.bin.electron) this.registerDiff('electron', (quasarConf, diffMap) => [ quasarConf.devServer, quasarConf.electron.extendElectronMainConf, quasarConf.electron.extendElectronPreloadConf, quasarConf.electron.inspectPort, quasarConf.electron.preloadScripts, quasarConf.sourceFiles.electronMain, // extends 'esbuild' diff ...diffMap.esbuild(quasarConf) ]) } run (quasarConf, __isRetry) { const { diff, queue } = super.run(quasarConf, __isRetry) if (diff('webpack', quasarConf)) { return queue(() => this.#runWebpack(quasarConf)) } if (diff('electron', quasarConf)) { return queue(() => this.#runElectronFiles(quasarConf)) } } async #runWebpack (quasarConf) { if (this.#server !== null) { await this.#server.stop() this.#server = null } const webpackConf = await quasarElectronConfig.webpack(quasarConf) let started = false return new Promise(resolve => { const compiler = webpack(webpackConf) compiler.hooks.done.tap('done-compiling', stats => { if (started === true) return // start dev server if there are no errors if (stats.hasErrors() === true) return started = true resolve() }) // start building & launch server // deep clone to avoid webpack-dev-server mutating the original config which causes double compilation this.#server = new WebpackDevServer(cloneDeep(quasarConf.devServer), compiler) this.#server.start() }) } async #runElectronFiles (quasarConf) { await this.clearWatcherList(this.#watcherList, () => { this.#watcherList = [] }) let isReady = false const cfgMain = await quasarElectronConfig.main(quasarConf) const cfgPreloadList = await quasarElectronConfig.preloadScriptList(quasarConf) const cfgList = [ { banner: 'Electron Main', cfg: cfgMain }, ...cfgPreloadList.map(preloadScript => { return { banner: `Electron Preload (${ preloadScript.scriptName })`, cfg: preloadScript.esbuildConfig } }) ].map(({ banner, cfg }) => { return this.watchWithEsbuild(banner, cfg, () => { if (isReady === true) { this.#runElectron(quasarConf) } }).then(esbuildCtx => { this.#watcherList.push({ close: esbuildCtx.dispose }) }) }) return Promise.all(cfgList).then(() => { isReady = true return this.#runElectron(quasarConf) }) } async #runElectron (quasarConf) { if (this.#pid) { log('Shutting down Electron process...') process.kill(this.#pid) this.#pid = 0 this.#killedPid = true // on some OSes a small delay is needed // so that resources are freed on kill await wait(100) } this.#pid = spawn( this.#electronExecutable, [ '--inspect=' + quasarConf.electron.inspectPort, this.ctx.appPaths.resolve.entry('electron-main.js') ].concat(this.argv._), { cwd: this.ctx.appPaths.appDir }, code => { if (this.#killedPid === true) { this.#killedPid = false } else if (code) { warn() fatal(`Electron process ended with error code: ${ code }`) } else { // else it wasn't killed by us warn() fatal('Electron process was killed. Exiting...') } } ) } }