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() this.error()
let nextCalled = false
Promise.all(Components.map((Component) => { Promise.all(Components.map((Component) => {
let promises = [] 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') { if (Component._data && typeof Component._data === 'function') {
var promise = Component._data(context) var promise = Component._data(context)
if (!(promise instanceof Promise)) promise = Promise.resolve(promise) if (!(promise instanceof Promise)) promise = Promise.resolve(promise)
@ -81,7 +87,10 @@ function render (to, from, next) {
})) }))
.then(() => { .then(() => {
<%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %> <%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
next() // If not redirected
if (!nextCalled) {
next()
}
}) })
.catch((error) => { .catch((error) => {
this.error(error) this.error(error)
@ -97,7 +106,11 @@ function hotReloadAPI (_app) {
if (!Component) return _forceUpdate() if (!Component) return _forceUpdate()
<%= (loading ? 'this.$loading.start && this.$loading.start()' : '') %> <%= (loading ? 'this.$loading.start && this.$loading.start()' : '') %>
let promises = [] 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 // Check if data has been updated
const originalDataFn = (Component._data || noopData).toString().replace(/\s/g, '') const originalDataFn = (Component._data || noopData).toString().replace(/\s/g, '')
const newDataFn = (Component._Ctor.options.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) promises.push(p)
} }
return Promise.all(promises).then(() => { return Promise.all(promises).then(() => {
<%= (loading ? 'this.$loading.finish && this.$loading.finish(30)' : '') %> <%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
_forceUpdate() _forceUpdate()
}) })
} }

View File

@ -2,9 +2,10 @@
const debug = require('debug')('nuxt:render') const debug = require('debug')('nuxt:render')
import Vue from 'vue' import Vue from 'vue'
import { stringify } from 'querystring'
import { pick } from 'lodash' import { pick } from 'lodash'
import { app, router<%= (store ? ', store' : '') %> } from './index' import { app, router<%= (store ? ', store' : '') %> } from './index'
import { getMatchedComponents, getContext } from './utils' import { getMatchedComponents, getContext, urlJoin } from './utils'
const isDev = <%= isDev %> const isDev = <%= isDev %>
const _app = new Vue(app) const _app = new Vue(app)
@ -18,9 +19,25 @@ router.history.base = '<%= router.base %>'
// Since data fetching is async, this function is expected to // Since data fetching is async, this function is expected to
// return a Promise that resolves to the app instance. // return a Promise that resolves to the app instance.
export default context => { 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 // set router's location
router.push(context.url) router.push(context.url)
// Add route to the context // Add route to the context
context.route = router.currentRoute context.route = router.currentRoute
// Add meta infos // Add meta infos

View File

@ -25,6 +25,10 @@ export function getContext (context) {
} }
ctx.params = ctx.route.params || {} ctx.params = ctx.route.params || {}
ctx.query = ctx.route.query || {} ctx.query = ctx.route.query || {}
ctx.redirect = function (path) {
if (!path) return
context.next(path)
}
if (context.req) ctx.req = context.req if (context.req) ctx.req = context.req
if (context.res) ctx.res = context.res if (context.res) ctx.res = context.res
return ctx return ctx
@ -38,3 +42,7 @@ export function getLocation (base) {
} }
return (path || '/') + window.location.search + window.location.hash 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 dev: self.dev, // Use to add the extracted CSS <link> in production
baseUrl: (self.options.router.base !== '/' ? self.options.router.base : null), baseUrl: (self.options.router.base !== '/' ? self.options.router.base : null),
APP: app, APP: app,
redirected: context.redirected,
context: context, context: context,
files: { files: {
css: urlJoin(self.options.router.base, '/_nuxt/', self.options.build.filenames.css), 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) 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()} ${title.toString()}
<% if (baseUrl) { %><base href="<%= baseUrl %>"><% } %> <% if (baseUrl) { %><base href="<%= baseUrl %>"><% } %>
<% if (!dev) { %><link rel="stylesheet" href="<%= files.css %>"><% } %> <% 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> </head>
<body> <body>
<% if (!redirected) { %>
<%= APP %> <%= APP %>
<script type="text/javascript" defer>window.__NUXT__=<%= serialize(context.nuxt) %></script> <script type="text/javascript" defer>window.__NUXT__=<%= serialize(context.nuxt) %></script>
<script src="<%= files.vendor %>" defer></script> <script src="<%= files.vendor %>" defer></script>
<script src="<%= files.app %>" defer></script> <script src="<%= files.app %>" defer></script>
<% } %>
</body> </body>
</html> </html>

View File

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