Nested dynamic routes

Build and Router
This commit is contained in:
Alexandre Chopin 2016-12-11 01:46:04 +01:00
parent bc1e9c00eb
commit 0b8b85128f
2 changed files with 66 additions and 36 deletions

View File

@ -5,8 +5,27 @@ import Router from 'vue-router'
Vue.use(Router)
<% uniqBy(router.routes, '_name').forEach((route) => { %>
const <%= route._name %> = process.BROWSER_BUILD ? () => System.import('<%= route._component %>') : require('<%= route._component %>')
<%
let components = []
function recursiveRoutes(routes, tab) {
let res = ''
routes.forEach((route, i) => {
components.push({ _name: route._name, component: route.component })
res += tab + '{\n'
res += tab + '\tpath: ' + JSON.stringify(route.path) + ',\n'
res += tab + '\tcomponent: ' + route._name
res += (route.name) ? ',\n\t' + tab + 'name: ' + JSON.stringify(route.name) : ''
res += (route.alias) ? ',\n\t' + tab + 'alias: ' + JSON.stringify(route.alias) : ''
res += (route.redirect) ? ',\n\t' + tab + 'redirect: ' + JSON.stringify(route.redirect) : ''
res += (route.meta) ? ',\n\t' + tab + 'meta: ' + JSON.stringify(route.meta) : ''
res += (route.children) ? ',\n\t' + tab + 'children: [\n' + recursiveRoutes(routes[i].children, tab + '\t\t') + '\n\t' + tab + ']' : ''
res += '\n' + tab + '}' + (i + 1 === routes.length ? '' : ',\n')
})
return res
}
let routes = recursiveRoutes(router.routes, '\t\t')
uniqBy(components, '_name').forEach((route) => { %>
const <%= route._name %> = process.BROWSER_BUILD ? () => System.import('<%= route.component %>') : require('<%= route.component %>')
<% }) %>
const scrollBehavior = (to, from, savedPosition) => {
@ -30,13 +49,6 @@ export default new Router({
linkActiveClass: '<%= router.linkActiveClass %>',
scrollBehavior,
routes: [
<% router.routes.forEach((route, i) => { %>
{
path: '<%= route.path %>',
component: <%= route._name %><% if (route.name) { %>,
name: '<%= route.name %>'<% } %><% if (route.meta) { %>,
meta: <%= JSON.stringify(route.meta) %><% } %>
}<%= (i + 1 === router.routes.length ? '' : ',') %>
<% }) %>
<%= routes %>
]
})

View File

@ -9,10 +9,9 @@ const hash = require('hash-sum')
const pify = require('pify')
const webpack = require('webpack')
const { createBundleRenderer } = require('vue-server-renderer')
const { join, resolve, sep, posix } = require('path')
const { join, resolve, sep } = require('path')
const clientWebpackConfig = require('./webpack/client.config.js')
const serverWebpackConfig = require('./webpack/server.config.js')
const basename = posix.basename
const remove = pify(fs.remove)
const readFile = pify(fs.readFile)
const writeFile = pify(fs.writeFile)
@ -111,13 +110,6 @@ exports.build = function * () {
if (!this.dev) {
yield mkdirp(r(this.dir, '.nuxt/dist'))
}
// Resolve custom routes component path
this.options.router.routes.forEach((route) => {
if (route.component.slice(-4) !== '.vue') {
route.component = route.component + '.vue'
}
route.component = r(this.srcDir, route.component)
})
// Generate routes and interpret the template files
yield generateRoutesAndFiles.call(this)
/*
@ -144,15 +136,6 @@ function * generateRoutesAndFiles () {
** Generate routes based on files
*/
const files = yield glob('pages/**/*.vue', { cwd: this.srcDir })
let routes = []
files.forEach((file) => {
let path = file.replace(/^pages/, '').replace(/index\.vue$/, '/').replace(/\.vue$/, '').replace(/\/{2,}/g, '/')
let name = file.replace(/^pages/, '').replace(/\.vue$/, '').replace(/\/{2,}/g, '/').split('/').slice(1).join('-')
if (basename(path)[0] === '_') return
routes.push({ path: path, component: r(this.srcDir, file), name: name })
})
// Concat pages routes and custom routes in this.routes
this.routes = routes.concat(this.options.router.routes)
/*
** Interpret and move template files to .nuxt/
*/
@ -192,14 +175,7 @@ function * generateRoutesAndFiles () {
templateVars.loading = templateVars.loading + '.vue'
}
// Format routes for the lib/app/router.js template
templateVars.router.routes = this.routes.map((route) => {
const r = Object.assign({}, route)
r._component = r.component
r._name = '_' + hash(r._component)
r.component = r._name
r.path = r.path.replace(/\\/g, '\\\\') // regex expression in route path escaping for lodash templating
return r
})
templateVars.router.routes = this.routes = createRoutes(files, this.srcDir, this.options.router.routes)
if (files.includes('pages/_app.vue')) {
templateVars.appPath = r(this.srcDir, 'pages/_app.vue')
}
@ -223,6 +199,48 @@ function * generateRoutesAndFiles () {
yield moveTemplates
}
function createRoutes (files, srcDir, options = {}) {
let routes = []
files.forEach((file) => {
let keys = file.replace(/^pages/, '').replace(/\.vue$/, '').replace(/\/{2,}/g, '/').split('/').slice(1)
let route = { name: '', path: '', component: r(srcDir, file), _name: null }
let parent = routes
keys.forEach((key, i) => {
route.name = route.name ? route.name + (key === 'index' ? '' : '-' + key.replace('_', '')) : key.replace('_', '')
let child = _.find(parent, { name: route.name })
if (child) {
if (!child.children) {
child.children = []
}
parent = child.children
} else {
route.path = route.path + (key === 'index' ? (i > 0 ? '' : '/') : '/' + key.replace('_', ':'))
}
})
route._name = '_' + hash(route.component)
// Update path with regexp in config
const path = _.result(options, keys.join('.'))
if (path && path.regexp) {
route.path = route.path.replace(_.last(keys).replace('_', ':'), path.regexp)
}
// regex expression in route path escaping for lodash templating
// route.path = route.path.replace(/\\/g, '\\\\')
parent.push(route)
})
return cleanChildrenRoutes(routes)
}
function cleanChildrenRoutes (routes, isChild = false) {
routes.forEach((route) => {
route.path = (isChild) ? route.path.replace('/', '') : route.path
if (route.children) {
delete route.name
route.children = cleanChildrenRoutes(route.children, true)
}
})
return routes
}
function getWebpackClientConfig () {
return clientWebpackConfig.call(this)
}