refactor(cli-serivce): use async functions when running service commands

This commit is contained in:
Evan You
2018-04-30 19:02:42 -04:00
parent da515acaf9
commit 69a6b0bbfe
3 changed files with 129 additions and 127 deletions
+2 -2
View File
@@ -112,7 +112,7 @@ module.exports = class Service {
}
}
run (name, args = {}, rawArgv = []) {
async run (name, args = {}, rawArgv = []) {
args._ = args._ || []
let command = this.commands[name]
if (!command && name) {
@@ -126,7 +126,7 @@ module.exports = class Service {
rawArgv.shift()
}
const { fn } = command
return Promise.resolve(fn(args, rawArgv))
await fn(args, rawArgv)
}
resolveChainableWebpackConfig () {
@@ -20,7 +20,7 @@ module.exports = (api, options) => {
'--target': `app | lib | wc | wc-async (default: ${defaults.target})`,
'--name': `name for lib or web-component mode (default: "name" in package.json or entry filename)`
}
}, args => {
}, async function build (args) {
args.entry = args.entry || args._[0]
for (const key in defaults) {
if (args[key] == null) {
@@ -122,49 +122,45 @@ module.exports = (api, options) => {
process.exit(1)
}
await fs.remove(targetDir)
return new Promise((resolve, reject) => {
fs.remove(targetDir, err => {
webpack(webpackConfig, (err, stats) => {
stopSpinner(false)
if (err) {
return reject(err)
}
webpack(webpackConfig, (err, stats) => {
stopSpinner(false)
if (err) {
return reject(err)
}
if (stats.hasErrors()) {
return reject(`Build failed with errors.`)
}
if (stats.hasErrors()) {
return reject(`Build failed with errors.`)
}
if (!args.silent) {
const targetDirShort = path.relative(
api.service.context,
targetDir
)
log(formatStats(stats, targetDirShort, api))
if (args.target === 'app') {
done(`Build complete. The ${chalk.cyan(targetDirShort)} directory is ready to be deployed.\n`)
if (
options.baseUrl === '/' &&
// only log the tips if this is the first build
!fs.existsSync(api.resolve('node_modules/.cache'))
) {
info(`The app is built assuming that it will be deployed at the root of a domain.`)
info(`If you intend to deploy it under a subpath, update the ${chalk.green('baseUrl')} option`)
info(`in your project config (${chalk.cyan(`vue.config.js`)} or ${chalk.green('"vue"')} field in ${chalk.cyan(`package.json`)}).\n`)
}
if (!args.silent) {
const targetDirShort = path.relative(
api.service.context,
targetDir
)
log(formatStats(stats, targetDirShort, api))
if (args.target === 'app') {
done(`Build complete. The ${chalk.cyan(targetDirShort)} directory is ready to be deployed.\n`)
if (
options.baseUrl === '/' &&
// only log the tips if this is the first build
!fs.existsSync(api.resolve('node_modules/.cache'))
) {
info(`The app is built assuming that it will be deployed at the root of a domain.`)
info(`If you intend to deploy it under a subpath, update the ${chalk.green('baseUrl')} option`)
info(`in your project config (${chalk.cyan(`vue.config.js`)} or ${chalk.green('"vue"')} field in ${chalk.cyan(`package.json`)}).\n`)
}
}
}
// test-only signal
if (process.env.VUE_CLI_TEST) {
console.log('Build complete.')
}
// test-only signal
if (process.env.VUE_CLI_TEST) {
console.log('Build complete.')
}
resolve()
})
resolve()
})
})
})
+97 -91
View File
@@ -1,6 +1,5 @@
const {
info,
error,
hasYarn,
openBrowser
} = require('@vue/cli-shared-utils')
@@ -23,7 +22,7 @@ module.exports = (api, options) => {
'--port': `specify port (default: ${defaults.port})`,
'--https': `use https (default: ${defaults.https})`
}
}, args => {
}, async function serve (args) {
info('Starting development server...')
api.setMode(args.mode || defaults.mode)
@@ -40,45 +39,109 @@ module.exports = (api, options) => {
const prepareProxy = require('../util/prepareProxy')
const launchEditorMiddleware = require('launch-editor-middleware')
// load user devServer options
const projectDevServerOptions = options.devServer || {}
// resolve webpack config
const webpackConfig = api.resolveWebpackConfig()
// inject dev & hot-reload middleware entries
if (!isProduction) {
const devClients = [
// dev server client
require.resolve(`webpack-dev-server/client`),
// hmr client
require.resolve(projectDevServerOptions.hotOnly
? 'webpack/hot/only-dev-server'
: 'webpack/hot/dev-server')
// TODO custom overlay client
// `@vue/cli-overlay/dist/client`
]
if (process.env.APPVEYOR) {
devClients.push(`webpack/hot/poll?500`)
}
// inject dev/hot client
addDevClientToEntry(webpackConfig, devClients)
}
// create compiler
const compiler = webpack(webpackConfig)
if (!process.env.VUE_CLI_TEST) {
compiler.apply(new webpack.ProgressPlugin())
}
// resolve server options
const useHttps = args.https || projectDevServerOptions.https || defaults.https
const host = args.host || process.env.HOST || projectDevServerOptions.host || defaults.host
portfinder.basePort = args.port || process.env.PORT || projectDevServerOptions.port || defaults.port
const port = await portfinder.getPortPromise()
const portPromise = portfinder.getPortPromise()
return portPromise.then(port => new Promise((resolve, reject) => {
const webpackConfig = api.resolveWebpackConfig()
const urls = prepareURLs(
useHttps ? 'https' : 'http',
host,
port
)
const urls = prepareURLs(
useHttps ? 'https' : 'http',
host,
port
)
const proxySettings = prepareProxy(
projectDevServerOptions.proxy,
api.resolve('public')
)
if (!isProduction) {
const devClients = [
// dev server client
require.resolve(`webpack-dev-server/client`),
// hmr client
require.resolve(projectDevServerOptions.hotOnly
? 'webpack/hot/only-dev-server'
: 'webpack/hot/dev-server')
// TODO custom overlay client
// `@vue/cli-overlay/dist/client`
]
if (process.env.APPVEYOR) {
devClients.push(`webpack/hot/poll?500`)
// create server
const server = new WebpackDevServer(compiler, Object.assign({
clientLogLevel: 'none',
historyApiFallback: {
disableDotRule: true
},
contentBase: api.resolve('public'),
watchContentBase: !isProduction,
hot: !isProduction,
quiet: true,
compress: isProduction,
publicPath: '/',
overlay: isProduction // TODO disable this
? false
: { warnings: false, errors: true }
}, projectDevServerOptions, {
https: useHttps,
proxy: proxySettings,
before (app) {
// launch editor support.
// this works with vue-devtools & @vue/cli-overlay
app.use('/__open-in-editor', launchEditorMiddleware(() => console.log(
`To specify an editor, sepcify the EDITOR env variable or ` +
`add "editor" field to your Vue project config.\n`
)))
// allow other plugins to register middlewares, e.g. PWA
api.service.devServerConfigFns.forEach(fn => fn(app))
// apply in project middlewares
projectDevServerOptions.before && projectDevServerOptions.before(app)
}
}))
;['SIGINT', 'SIGTERM'].forEach(signal => {
process.on(signal, () => {
server.close(() => {
process.exit(0)
})
})
})
// on appveyor, killing the process with SIGTERM causes execa to
// throw error
if (process.env.VUE_CLI_TEST) {
process.stdin.on('data', data => {
if (data.toString() === 'close') {
console.log('got close signal!')
server.close(() => {
process.exit(0)
})
}
// inject dev/hot client
addDevClientToEntry(webpackConfig, devClients)
}
const compiler = webpack(webpackConfig)
if (!process.env.VUE_CLI_TEST) {
compiler.apply(new webpack.ProgressPlugin())
}
})
}
return new Promise((resolve, reject) => {
// log instructions & open browser on first compilation complete
let isFirstCompile = true
compiler.plugin('done', stats => {
@@ -123,69 +186,12 @@ module.exports = (api, options) => {
}
})
const proxySettings = prepareProxy(
projectDevServerOptions.proxy,
api.resolve('public')
)
const server = new WebpackDevServer(compiler, Object.assign({
clientLogLevel: 'none',
historyApiFallback: {
disableDotRule: true
},
contentBase: api.resolve('public'),
watchContentBase: !isProduction,
hot: !isProduction,
quiet: true,
compress: isProduction,
publicPath: '/',
overlay: isProduction // TODO disable this
? false
: { warnings: false, errors: true }
}, projectDevServerOptions, {
https: useHttps,
proxy: proxySettings,
before (app) {
// launch editor support.
// this works with vue-devtools & @vue/cli-overlay
app.use('/__open-in-editor', launchEditorMiddleware(() => console.log(
`To specify an editor, sepcify the EDITOR env variable or ` +
`add "editor" field to your Vue project config.\n`
)))
// allow other plugins to register middlewares, e.g. PWA
api.service.devServerConfigFns.forEach(fn => fn(app))
// apply in project middlewares
projectDevServerOptions.before && projectDevServerOptions.before(app)
}
}))
;['SIGINT', 'SIGTERM'].forEach(signal => {
process.on(signal, () => {
server.close(() => {
process.exit(0)
})
})
})
// on appveyor, killing the process with SIGTERM causes execa to
// throw error
if (process.env.VUE_CLI_TEST) {
process.stdin.on('data', data => {
if (data.toString() === 'close') {
console.log('got close signal!')
server.close(() => {
process.exit(0)
})
}
})
}
server.listen(port, host, err => {
if (err) {
return error(err)
reject(err)
}
})
}))
})
})
}