Add redirect in context

This commit is contained in:
Sébastien Chopin 2016-11-11 00:01:36 +01:00
parent b6ee7099a0
commit 5b0ff5617b
6 changed files with 59 additions and 8 deletions

View File

@ -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()
})
}

View File

@ -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

View File

@ -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, '/')
}

View File

@ -145,6 +145,7 @@ class Nuxt {
dev: self.dev, // Use to add the extracted CSS <link> 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
}
})
}

View File

@ -10,11 +10,19 @@
${title.toString()}
<% if (baseUrl) { %><base href="<%= baseUrl %>"><% } %>
<% if (!dev) { %><link rel="stylesheet" href="<%= files.css %>"><% } %>
<% if (redirected) { %>
<meta http-equiv="refresh" content="0; url=<%= redirected %>" />
<script type="text/javascript">
window.location.href = '<%= redirected %>'
</script>
<% } %>
</head>
<body>
<% if (!redirected) { %>
<%= APP %>
<script type="text/javascript" defer>window.__NUXT__=<%= serialize(context.nuxt) %></script>
<script src="<%= files.vendor %>" defer></script>
<script src="<%= files.app %>" defer></script>
<% } %>
</body>
</html>

View File

@ -1,6 +1,6 @@
{
"name": "nuxt",
"version": "0.3.5",
"version": "0.3.6",
"description": "A minimalistic framework for server-rendered Vue.js applications (inspired by Next.js)",
"main": "index.js",
"license": "MIT",