refactor: nuxt dev watcher (#3732)

This commit is contained in:
Clark Du 2018-08-15 12:48:34 +01:00 committed by Sébastien Chopin
parent 61c0976cd2
commit 1492a13162
5 changed files with 57 additions and 85 deletions

View File

@ -49,86 +49,53 @@ if (argv.help) {
process.exit(0)
}
// Start dev
let dev = startDev()
const config = () => {
// Force development mode for add hot reloading and watching changes
return Object.assign(loadNuxtConfig(argv), { dev: true })
}
function startDev(oldInstance) {
// Error handler
const onError = (err, instance) => {
const errorHandler = (err, instance) => {
instance && instance.builder.watchServer()
consola.error(err)
return Promise.resolve(instance) // Wait for next reload
}
}
// Load options
let options = {}
try {
options = loadAndAugmentNuxtConfig()
} catch (err) {
return onError(err, oldInstance)
}
// Start dev
(function startDev(oldInstance) {
let nuxt, builder
// Create nuxt and builder instance
let nuxt
let builder
let instance
try {
nuxt = new Nuxt(options)
nuxt = new Nuxt(config())
builder = new Builder(nuxt)
instance = { nuxt, builder }
nuxt.hook('watch:fileChanged', (builder, fname) => {
consola.debug(`[${fname}] changed, Rebuilding the app...`)
startDev({ nuxt: builder.nuxt, builder })
})
} catch (err) {
return onError(err, oldInstance)
return errorHandler(err, oldInstance)
}
nuxt.hook('watch:fileChanged', (fname) => {
consola.debug(`[${fname}] changed`)
dev = dev.then((instance) => {
consola.debug('Rebuilding the app...')
return startDev(instance)
})
})
// Get latest environment variables
const { port, host } = nuxt.options.server
return (
Promise.resolve()
.then(() => {
if (oldInstance && oldInstance.builder) {
return oldInstance.builder.unwatch()
} else {
return nuxt.listen(port, host)
}
})
.then(() => oldInstance && oldInstance.nuxt.clearHook('watch:fileChanged'))
.then(() => oldInstance && oldInstance.builder.unwatch())
// Start build
.then(() => builder.build())
// Close old nuxt after successful build
.then(
() =>
oldInstance && oldInstance.nuxt
? oldInstance.nuxt.close()
: Promise.resolve()
)
// Start listening
.then(() => {
if (oldInstance) {
return nuxt.listen(port, host)
} else {
return Promise.resolve()
}
// Close old nuxt no mater if build successfully
.catch((err) => {
oldInstance && oldInstance.nuxt.close()
// Jump to eventHandler
throw err
})
// Pass new nuxt to watch chain
.then(() => instance)
.then(() => oldInstance && oldInstance.nuxt.close())
// Start listening
.then(() => nuxt.listen(port, host))
// Show ready message first time, others will be shown through WebpackBar
.then(() => !oldInstance && nuxt.showReady(false))
.then(() => builder.watchServer())
// Handle errors
.catch(err => onError(err, instance))
.catch(err => errorHandler(err, {builder, nuxt}))
)
}
function loadAndAugmentNuxtConfig() {
const options = loadNuxtConfig(argv)
// Force development mode for add hot reloading and watching changes
options.dev = true
return options
}
})()

View File

@ -103,7 +103,7 @@ export default class Builder {
consola.info({
message: 'Building project',
badge: true,
clear: true
clear: !this.options.dev
})
// Wait for nuxt ready
@ -589,11 +589,11 @@ export default class Builder {
this.nuxt.renderer.webpackHotMiddleware = this.webpackHotMiddleware
}
// Start watching files
this.watchFiles()
// Start watching client files
this.watchClient()
}
watchFiles() {
watchClient() {
const src = this.options.srcDir
let patterns = [
r(src, this.options.dir.layouts),
@ -611,9 +611,7 @@ export default class Builder {
}
patterns = _.map(patterns, upath.normalizeSafe)
const options = Object.assign({}, this.options.watchers.chokidar, {
ignoreInitial: true
})
const options = this.options.watchers.chokidar
/* istanbul ignore next */
const refreshFiles = _.debounce(() => this.generateRoutesAndFiles(), 200)
@ -632,22 +630,21 @@ export default class Builder {
this.watchers.custom = chokidar
.watch(customPatterns, options)
.on('change', refreshFiles)
}
// Watch for nuxt.config.js and user-defined changes
const restartServer = _.debounce((fname) => {
this.nuxt.callHook('watch:fileChanged', fname)
})
watchServer() {
const nuxtRestartWatch = _.concat(
this.options.serverMiddleware.map(this.nuxt.resolveAlias),
this.options.watch.map(this.nuxt.resolveAlias),
path.join(this.options.rootDir, 'nuxt.config.js')
)
this.watchers.restart = chokidar
.watch(nuxtRestartWatch, options)
.watch(nuxtRestartWatch, this.options.watchers.chokidar)
.on('change', (_path) => {
const parsedPath = path.parse(_path)
restartServer(`${parsedPath.name}${parsedPath.ext}`)
this.watchers.restart.close()
const {name, ext} = path.parse(_path)
this.nuxt.callHook('watch:fileChanged', this, `${name}${ext}`)
})
}

View File

@ -235,7 +235,7 @@ export default class WebpackBaseConfig {
const hasErrors = Object.values(states).some(state => state.stats.hasErrors())
if (!hasErrors) {
this.nuxt.showReady()
this.nuxt.showReady(false)
}
}
}

View File

@ -214,7 +214,9 @@ export default {
watch: [],
watchers: {
webpack: {},
chokidar: {}
chokidar: {
ignoreInitial: true
}
},
editor: undefined,
hooks: null,

View File

@ -99,6 +99,12 @@ export default class Nuxt {
}
}
clearHook(name) {
if (name) {
delete this._hooks[name]
}
}
addObjectHooks(hooksObj) {
Object.keys(hooksObj).forEach((name) => {
let hooks = hooksObj[name]
@ -144,7 +150,7 @@ export default class Nuxt {
() =>
new Promise((resolve, reject) => {
// Destroy server by forcing every connection to be closed
server.destroy((err) => {
server.listening && server.destroy((err) => {
consola.debug('server closed')
/* istanbul ignore if */
if (err) {