Skip to content

Commit

Permalink
Add redirect in context
Browse files Browse the repository at this point in the history
  • Loading branch information
Atinux committed Nov 10, 2016
1 parent b6ee709 commit 5b0ff56
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 8 deletions.
21 changes: 17 additions & 4 deletions lib/app/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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, '')
Expand All @@ -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()
})
}
Expand Down
21 changes: 19 additions & 2 deletions lib/app/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
8 changes: 8 additions & 0 deletions lib/app/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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, '/')
}
7 changes: 6 additions & 1 deletion lib/nuxt.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,19 @@ 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),
vendor: urlJoin(self.options.router.base, '/_nuxt/', self.options.build.filenames.vendor),
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
}
})
}

Expand Down
8 changes: 8 additions & 0 deletions lib/views/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -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>
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down

0 comments on commit 5b0ff56

Please sign in to comment.