diff --git a/lib/app/client.js b/lib/app/client.js
index 246fe06431..4d1c3ef6bc 100644
--- a/lib/app/client.js
+++ b/lib/app/client.js
@@ -56,9 +56,15 @@ function render (to, from, next) {
}
})
this.error()
+ let nextCalled = false
Promise.all(Components.map((Component) => {
let promises = []
- const context = getContext({ to<%= (store ? ', store' : '') %>, isClient: true })
+ const _next = function (path) {
+ <%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
+ nextCalled = true
+ next(path)
+ }
+ const context = getContext({ to<%= (store ? ', store' : '') %>, isClient: true, next: _next.bind(this) })
if (Component._data && typeof Component._data === 'function') {
var promise = Component._data(context)
if (!(promise instanceof Promise)) promise = Promise.resolve(promise)
@@ -81,7 +87,10 @@ function render (to, from, next) {
}))
.then(() => {
<%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
- next()
+ // If not redirected
+ if (!nextCalled) {
+ next()
+ }
})
.catch((error) => {
this.error(error)
@@ -97,7 +106,11 @@ function hotReloadAPI (_app) {
if (!Component) return _forceUpdate()
<%= (loading ? 'this.$loading.start && this.$loading.start()' : '') %>
let promises = []
- const context = getContext({ route: router.currentRoute<%= (store ? ', store' : '') %>, isClient: true })
+ const next = function (path) {
+ <%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
+ router.push(path)
+ }
+ const context = getContext({ route: router.currentRoute<%= (store ? ', store' : '') %>, isClient: true, next: next.bind(this) })
// Check if data has been updated
const originalDataFn = (Component._data || noopData).toString().replace(/\s/g, '')
const newDataFn = (Component._Ctor.options.data || noopData).toString().replace(/\s/g, '')
@@ -124,7 +137,7 @@ function hotReloadAPI (_app) {
promises.push(p)
}
return Promise.all(promises).then(() => {
- <%= (loading ? 'this.$loading.finish && this.$loading.finish(30)' : '') %>
+ <%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
_forceUpdate()
})
}
diff --git a/lib/app/server.js b/lib/app/server.js
index 1198882244..65ea565c72 100644
--- a/lib/app/server.js
+++ b/lib/app/server.js
@@ -2,9 +2,10 @@
const debug = require('debug')('nuxt:render')
import Vue from 'vue'
+import { stringify } from 'querystring'
import { pick } from 'lodash'
import { app, router<%= (store ? ', store' : '') %> } from './index'
-import { getMatchedComponents, getContext } from './utils'
+import { getMatchedComponents, getContext, urlJoin } from './utils'
const isDev = <%= isDev %>
const _app = new Vue(app)
@@ -18,9 +19,25 @@ router.history.base = '<%= router.base %>'
// Since data fetching is async, this function is expected to
// return a Promise that resolves to the app instance.
export default context => {
+ // create context.next for simulate next() of beforeEach() when wanted to redirect
+ context.redirected = false
+ context.next = function (path) {
+ if (!path) return;
+ if (typeof path === 'string') path = { path }
+ path.query = stringify(path.query || {})
+ path.path = path.path + (path.query ? '?' + path.query : '')
+ path.path = urlJoin('<%= router.base %>', path.path)
+ if (!context.res) {
+ context.redirected = path.path
+ return
+ }
+ context.res.writeHead(302, {
+ 'Location': path.path
+ })
+ context.res.end()
+ }
// set router's location
router.push(context.url)
-
// Add route to the context
context.route = router.currentRoute
// Add meta infos
diff --git a/lib/app/utils.js b/lib/app/utils.js
index c58f0a3986..58aabee886 100644
--- a/lib/app/utils.js
+++ b/lib/app/utils.js
@@ -25,6 +25,10 @@ export function getContext (context) {
}
ctx.params = ctx.route.params || {}
ctx.query = ctx.route.query || {}
+ ctx.redirect = function (path) {
+ if (!path) return
+ context.next(path)
+ }
if (context.req) ctx.req = context.req
if (context.res) ctx.res = context.res
return ctx
@@ -38,3 +42,7 @@ export function getLocation (base) {
}
return (path || '/') + window.location.search + window.location.hash
}
+
+exports.urlJoin = function () {
+ return [].slice.call(arguments).join('/').replace(/\/+/g, '/')
+}
diff --git a/lib/nuxt.js b/lib/nuxt.js
index 0e0c243133..4418743335 100644
--- a/lib/nuxt.js
+++ b/lib/nuxt.js
@@ -145,6 +145,7 @@ class Nuxt {
dev: self.dev, // Use to add the extracted CSS in production
baseUrl: (self.options.router.base !== '/' ? self.options.router.base : null),
APP: app,
+ redirected: context.redirected,
context: context,
files: {
css: urlJoin(self.options.router.base, '/_nuxt/', self.options.build.filenames.css),
@@ -152,7 +153,11 @@ class Nuxt {
app: urlJoin(self.options.router.base, '/_nuxt/', self.options.build.filenames.app)
}
})
- return { html, error: context.nuxt.error }
+ return {
+ html,
+ error: context.nuxt.error,
+ redirected: context.redirected
+ }
})
}
diff --git a/lib/views/app.html b/lib/views/app.html
index ed052bcc17..d20fe936c8 100644
--- a/lib/views/app.html
+++ b/lib/views/app.html
@@ -10,11 +10,19 @@
${title.toString()}
<% if (baseUrl) { %>