#!/usr/bin/env node const parseArgs = require('minimist') const logger = require('../lib/helpers/logger'), log = logger('app:dev'), warn = logger('app:dev', 'red'), appPaths = require('../lib/app-paths') const argv = parseArgs(process.argv.slice(2), { alias: { m: 'mode', T: 'target', // cordova-mode only e: 'emulator', // cordova-mode only p: 'port', H: 'hostname', h: 'help' }, boolean: ['h'], string: ['m', 'T', 'H'], default: { m: 'spa' } }) if (argv.help) { console.log(` Description Starts the app in development mode (hot-code reloading, error reporting, etc) Usage $ quasar dev -p Options --mode, -m App mode [spa|ssr|pwa|cordova|electron] (default: spa) --port, -p A port number on which to start the application --hostname, -H A hostname to use for serving the application --help, -h Displays this message Only for Cordova mode: --target, -T (required) App target [android|ios|blackberry10|browser|osx|ubuntu|webos|windows] --emulator, -e (optional) Emulator name Example: iPhone-7, iPhone-X `) process.exit(0) } require('../lib/helpers/ensure-argv')(argv, 'dev') require('../lib/helpers/banner')(argv, 'dev') if (argv.mode !== 'spa') { require('../lib/mode/install-missing')(argv.mode, argv.target) } const ensureDeps = require('../lib/helpers/ensure-deps'), findPort = require('../lib/helpers/net').findClosestOpenPort async function parseAddress ({ host, port }) { if (this.chosenHost) { host = this.chosenHost } else { if (host && ['localhost', '127.0.0.1', '::1'].includes(host.toLowerCase())) { host = '0.0.0.0' } if (argv.mode === 'cordova' && (!host || host === '0.0.0.0')) { const getExternalIP = require('../lib/helpers/get-external-ip') host = await getExternalIP() this.chosenHost = host } } log(`Checking listening address availability (${host}:${port})...`) try { const openPort = await findPort(port, host) if (port !== openPort) { warn() warn(`Setting port to closest one available: ${openPort}`) warn() port = openPort } } catch (e) { warn() if (e.message === 'ERROR_NETWORK_PORT_NOT_AVAIL') { warn(`⚠️ Could not find an open port. Please configure a lower one to start searching with.`) } else if (e.message === 'ERROR_NETWORK_ADDRESS_NOT_AVAIL') { warn(`⚠️ Invalid host specified. No network address matches. Please specify another one.`) } else { warn(`⚠️ Unknown network error occured`) console.log(e) } warn() if (!this.running) { process.exit(1) } return null } this.running = true return { host, port } } async function goLive () { ensureDeps() const DevServer = require('../lib/dev-server'), QuasarConfig = require('../lib/quasar-config'), Generator = require('../lib/generator'), getQuasarCtx = require('../lib/helpers/get-quasar-ctx'), extensionRunner = require('../lib/app-extension/extensions-runner') const ctx = getQuasarCtx({ mode: argv.mode, target: argv.target, emulator: argv.emulator, dev: true }) // register app extensions await extensionRunner.registerExtensions(ctx) const quasarConfig = new QuasarConfig(ctx, { port: argv.port, host: argv.hostname, onAddress: parseAddress, onBuildChange () { log(`Build changes detected. Rebuilding app...`) dev = dev.then(startDev) }, onAppChange () { log(`App changes detected. Updating app...`) generator.build() } }) try { await quasarConfig.prepare() } catch (e) { console.log(e) warn(`[FAIL] quasar.conf.js has JS errors`) process.exit(1) } await quasarConfig.compile() buildConfig = quasarConfig.getBuildConfig() if (typeof buildConfig.build.beforeDev === 'function') { await buildConfig.build.beforeDev() } // run possible beforeDev hooks await extensionRunner.runHook('beforeDev', async hook => { log(`Extension(${hook.extId}): Running beforeDev hook...`) await hook.fn() }) const generator = new Generator(quasarConfig), Cordova = argv.mode === 'cordova' ? require('../lib/cordova') : false, Electron = argv.mode === 'electron' ? require('../lib/electron') : false generator.prepare() function startDev (oldDevServer) { let devServer return Promise.resolve() .then(() => devServer = new DevServer(quasarConfig)) .then(() => oldDevServer && oldDevServer.stop()) .then(() => generator.build()) // Update generated files .then(() => devServer.listen()) // Start listening .then(() => Electron && Electron.run(quasarConfig)) .then(() => Cordova && Cordova.run(quasarConfig)) .then(() => devServer) // Pass new builder to watch chain } let dev = startDev() } goLive()