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) process.exit(0)
} }
// Start dev const config = () => {
let dev = startDev() // Force development mode for add hot reloading and watching changes
return Object.assign(loadNuxtConfig(argv), { dev: true })
}
function startDev(oldInstance) { const errorHandler = (err, instance) => {
// Error handler instance && instance.builder.watchServer()
const onError = (err, instance) => {
consola.error(err) consola.error(err)
return Promise.resolve(instance) // Wait for next reload }
}
// Load options // Start dev
let options = {} (function startDev(oldInstance) {
try { let nuxt, builder
options = loadAndAugmentNuxtConfig()
} catch (err) {
return onError(err, oldInstance)
}
// Create nuxt and builder instance
let nuxt
let builder
let instance
try { try {
nuxt = new Nuxt(options) nuxt = new Nuxt(config())
builder = new Builder(nuxt) 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) { } 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 // Get latest environment variables
const { port, host } = nuxt.options.server const { port, host } = nuxt.options.server
return ( return (
Promise.resolve() Promise.resolve()
.then(() => { .then(() => oldInstance && oldInstance.nuxt.clearHook('watch:fileChanged'))
if (oldInstance && oldInstance.builder) { .then(() => oldInstance && oldInstance.builder.unwatch())
return oldInstance.builder.unwatch()
} else {
return nuxt.listen(port, host)
}
})
// Start build // Start build
.then(() => builder.build()) .then(() => builder.build())
// Close old nuxt after successful build // Close old nuxt no mater if build successfully
.then( .catch((err) => {
() => oldInstance && oldInstance.nuxt.close()
oldInstance && oldInstance.nuxt // Jump to eventHandler
? oldInstance.nuxt.close() throw err
: Promise.resolve()
)
// Start listening
.then(() => {
if (oldInstance) {
return nuxt.listen(port, host)
} else {
return Promise.resolve()
}
}) })
// Pass new nuxt to watch chain .then(() => oldInstance && oldInstance.nuxt.close())
.then(() => instance) // 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 // 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({ consola.info({
message: 'Building project', message: 'Building project',
badge: true, badge: true,
clear: true clear: !this.options.dev
}) })
// Wait for nuxt ready // Wait for nuxt ready
@ -589,11 +589,11 @@ export default class Builder {
this.nuxt.renderer.webpackHotMiddleware = this.webpackHotMiddleware this.nuxt.renderer.webpackHotMiddleware = this.webpackHotMiddleware
} }
// Start watching files // Start watching client files
this.watchFiles() this.watchClient()
} }
watchFiles() { watchClient() {
const src = this.options.srcDir const src = this.options.srcDir
let patterns = [ let patterns = [
r(src, this.options.dir.layouts), r(src, this.options.dir.layouts),
@ -611,9 +611,7 @@ export default class Builder {
} }
patterns = _.map(patterns, upath.normalizeSafe) patterns = _.map(patterns, upath.normalizeSafe)
const options = Object.assign({}, this.options.watchers.chokidar, { const options = this.options.watchers.chokidar
ignoreInitial: true
})
/* istanbul ignore next */ /* istanbul ignore next */
const refreshFiles = _.debounce(() => this.generateRoutesAndFiles(), 200) const refreshFiles = _.debounce(() => this.generateRoutesAndFiles(), 200)
@ -632,22 +630,21 @@ export default class Builder {
this.watchers.custom = chokidar this.watchers.custom = chokidar
.watch(customPatterns, options) .watch(customPatterns, options)
.on('change', refreshFiles) .on('change', refreshFiles)
}
// Watch for nuxt.config.js and user-defined changes watchServer() {
const restartServer = _.debounce((fname) => {
this.nuxt.callHook('watch:fileChanged', fname)
})
const nuxtRestartWatch = _.concat( const nuxtRestartWatch = _.concat(
this.options.serverMiddleware.map(this.nuxt.resolveAlias), this.options.serverMiddleware.map(this.nuxt.resolveAlias),
this.options.watch.map(this.nuxt.resolveAlias), this.options.watch.map(this.nuxt.resolveAlias),
path.join(this.options.rootDir, 'nuxt.config.js') path.join(this.options.rootDir, 'nuxt.config.js')
) )
this.watchers.restart = chokidar this.watchers.restart = chokidar
.watch(nuxtRestartWatch, options) .watch(nuxtRestartWatch, this.options.watchers.chokidar)
.on('change', (_path) => { .on('change', (_path) => {
const parsedPath = path.parse(_path) this.watchers.restart.close()
restartServer(`${parsedPath.name}${parsedPath.ext}`) 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()) const hasErrors = Object.values(states).some(state => state.stats.hasErrors())
if (!hasErrors) { if (!hasErrors) {
this.nuxt.showReady() this.nuxt.showReady(false)
} }
} }
} }

View File

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

View File

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