|
|
@@ -28,7 +28,7 @@ let router
|
|
|
// Try to rehydrate SSR data from window
|
|
|
const NUXT = window.__NUXT__ || {}
|
|
|
|
|
|
-Object.assign(Vue.config, {"silent":true,"performance":false})
|
|
|
+Object.assign(Vue.config, {"silent":false,"performance":true})
|
|
|
|
|
|
// Setup global Vue error handler
|
|
|
if (!Vue.config.$nuxt) {
|
|
|
@@ -468,6 +468,9 @@ function fixPrepatch(to, ___) {
|
|
|
}
|
|
|
})
|
|
|
showNextPage.call(this, to)
|
|
|
+
|
|
|
+ // Hot reloading
|
|
|
+ setTimeout(() => hotReloadAPI(this), 100)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
@@ -488,6 +491,101 @@ function nuxtReady(_app) {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+// Special hot reload with asyncData(context)
|
|
|
+function getNuxtChildComponents($parent, $components = []) {
|
|
|
+ $parent.$children.forEach(($child) => {
|
|
|
+ if ($child.$vnode.data.nuxtChild && !$components.find(c =>(c.$options.__file === $child.$options.__file))) {
|
|
|
+ $components.push($child)
|
|
|
+ }
|
|
|
+ if ($child.$children && $child.$children.length) {
|
|
|
+ getNuxtChildComponents($child, $components)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return $components
|
|
|
+}
|
|
|
+
|
|
|
+function hotReloadAPI(_app) {
|
|
|
+ if (!module.hot) return
|
|
|
+
|
|
|
+ let $components = getNuxtChildComponents(_app.$nuxt, [])
|
|
|
+
|
|
|
+ $components.forEach(addHotReload.bind(_app))
|
|
|
+}
|
|
|
+
|
|
|
+function addHotReload($component, depth) {
|
|
|
+ if ($component.$vnode.data._hasHotReload) return
|
|
|
+ $component.$vnode.data._hasHotReload = true
|
|
|
+
|
|
|
+ var _forceUpdate = $component.$forceUpdate.bind($component.$parent)
|
|
|
+
|
|
|
+ $component.$vnode.context.$forceUpdate = async () => {
|
|
|
+ let Components = getMatchedComponents(router.currentRoute)
|
|
|
+ let Component = Components[depth]
|
|
|
+ if (!Component) return _forceUpdate()
|
|
|
+ if (typeof Component === 'object' && !Component.options) {
|
|
|
+ // Updated via vue-router resolveAsyncComponents()
|
|
|
+ Component = Vue.extend(Component)
|
|
|
+ Component._Ctor = Component
|
|
|
+ }
|
|
|
+ this.error()
|
|
|
+ let promises = []
|
|
|
+ const next = function (path) {
|
|
|
+ this.$loading.finish && this.$loading.finish()
|
|
|
+ router.push(path)
|
|
|
+ }
|
|
|
+ await setContext(app, {
|
|
|
+ route: router.currentRoute,
|
|
|
+ isHMR: true,
|
|
|
+ next: next.bind(this)
|
|
|
+ })
|
|
|
+ const context = app.context
|
|
|
+
|
|
|
+ if (this.$loading.start && !this.$loading.manual) this.$loading.start()
|
|
|
+
|
|
|
+ callMiddleware.call(this, Components, context)
|
|
|
+ .then(() => {
|
|
|
+ // If layout changed
|
|
|
+ if (depth !== 0) return Promise.resolve()
|
|
|
+ let layout = Component.options.layout || 'default'
|
|
|
+ if (typeof layout === 'function') {
|
|
|
+ layout = layout(context)
|
|
|
+ }
|
|
|
+ if (this.layoutName === layout) return Promise.resolve()
|
|
|
+ let promise = this.loadLayout(layout)
|
|
|
+ promise.then(() => {
|
|
|
+ this.setLayout(layout)
|
|
|
+ Vue.nextTick(() => hotReloadAPI(this))
|
|
|
+ })
|
|
|
+ return promise
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ return callMiddleware.call(this, Components, context, this.layout)
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ // Call asyncData(context)
|
|
|
+ let pAsyncData = promisify(Component.options.asyncData || noopData, context)
|
|
|
+ pAsyncData.then((asyncDataResult) => {
|
|
|
+ applyAsyncData(Component, asyncDataResult)
|
|
|
+ this.$loading.increase && this.$loading.increase(30)
|
|
|
+ })
|
|
|
+ promises.push(pAsyncData)
|
|
|
+ // Call fetch()
|
|
|
+ Component.options.fetch = Component.options.fetch || noopFetch
|
|
|
+ let pFetch = Component.options.fetch(context)
|
|
|
+ if (!pFetch || (!(pFetch instanceof Promise) && (typeof pFetch.then !== 'function'))) { pFetch = Promise.resolve(pFetch) }
|
|
|
+ pFetch.then(() => this.$loading.increase && this.$loading.increase(30))
|
|
|
+ promises.push(pFetch)
|
|
|
+ return Promise.all(promises)
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ this.$loading.finish && this.$loading.finish()
|
|
|
+ _forceUpdate()
|
|
|
+ setTimeout(() => hotReloadAPI(this), 100)
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
async function mountApp(__app) {
|
|
|
// Set global variables
|
|
|
app = __app.app
|
|
|
@@ -507,6 +605,9 @@ async function mountApp(__app) {
|
|
|
Vue.nextTick(() => {
|
|
|
// Call window.{{globals.readyCallback}} callbacks
|
|
|
nuxtReady(_app)
|
|
|
+
|
|
|
+ // Enable hot reloading
|
|
|
+ hotReloadAPI(_app)
|
|
|
})
|
|
|
}
|
|
|
|