There is any options to set a custom route without change the folder structure?
module.exports = {
srcDir: resolve('./app'),
head: {
title: 'starter',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', content: 'Nuxt.js project' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: 'favicon.ico' }
]
},
css: ['~assets/css/main.css'],
loading: { color: '#3B8070' },
router: {
linkActiveClass: 'active',
**routes: [{
name: 'banana',
path: '/banana',
component: 'pages/index.vue'
}]**
}
};
Hi @danieloprado
This option has been removed since the 0.9.0
, the only way to create route is by the filesystem.
Why would you want to have another route pointing to the same page?
I want to write my code in english and make the routes in another language.
Maybe we can keep both and let the developer decide witch is better.
Hi,
I don't know about your routes structure but maybe a solution could be using dynamic routes for that and use the validate() method.
Unfortunately, we couldn't keep both methods for Nuxt.
This is my structure, I want the route to the product/_id.vue to be produtos/:id not product/:id without rename the folder
@danieloprado you should not worry about the names of your files in the pages
since they represent your routes of your applications, they don't have to be in english.
This application in particular is an international one, each client that uses it will use their own terms and custom routes, everything will be configurable and loaded when the application boots up.
I'll keep it open to look for a possible solution, but as I think it right now, the most flexible way would be with an extendRoutes
method in the router
property:
nuxt.config.js
module.exports = {
router: {
extendRoutes (routes) {
// Update
routes.find((r) => r.path.includes('pages/product/_id.vue')).path = '/produtos/:id'
}
}
}
This method would be used at your own risks, like build.extend
for extending webpack configuration.
You can now customise the routes with the latest release 0.9.7, see documentation.
@Atinux If I need to specify meta information for certain routes (for example, I need to do some blocking judgment on a particular routing page), I found that the router object can not be set successfully, Information, can not increase and modify, have better suggestions?
In addition, I also need to intercept the routing api, I was in default.vue used afterEach after using the routing method, but I think this is not a good solution, hope to give better suggestions, thank you.
like this:
router: {
linkActiveClass: 'active-link',
scrollBehavior(to, from, savedPosition) {
return { x: 0, y: 0 }
},
extendRoutes(routes) {
routes[0].meta = { needAuth: true }
// const fullPageNames = ['about', 'guestbook', 'music', 'project']
// 1:
// routes.map((route) => {
// const isFullPage = fullPageNames.includes(route.name) || route.path.includes('/project/')
// return isFullPage ? Object.assign(route, { meta: { fullPage: true }}) : route
// })
// 2:
// routes.forEach((value, index, array) => {
// const isFullPage = fullPageNames.includes(routes[index].name) || routes[index].path.includes('/project/')
// if(isFullPage) { Object.assign(routes[index], { meta: { fullPage: true }}) }
// })
console.log(routes)
}
}
It will be possible with the middleware feature (see examples/auth-routes/ and examples/middleware/)
This feature will be released next week.
ths:)
Hi @Atinux ,
I'm using extendRoutes
to define custom routes (login, logout, etc...).
extendRoutes (routes) {
routes.push({name: 'logout', path: '/logout', component: '~portal/pages/logout.vue'})
routes.push({name: 'login', path: '/login', component: '~portal/pages/login.vue', meta:{guest: true}})
}
According to the documentation "The schema of the route should respect the vue-router schema." but it looks like the meta
property is ignored. Is this a bug or a choice ?
Thanks.
The same problem was with alias
. It was ignored too when I last
checked.
On Fri, Mar 3, 2017 at 1:25 AM, Titus notifications@github.com wrote:
Hi @Atinux https://github.com/Atinux ,
I'm using extendRoutes to define custom routes (login, logout, etc...).
extendRoutes (routes) {
routes.push({name: 'logout', path: '/logout', component: '~portal/pages/logout.vue'})
routes.push({name: 'login', path: '/login', component: '~portal/pages/login.vue', meta:{guest: true}})
}According to the documentation "The schema of the route should respect the
vue-router schema." but it looks like the meta property is ignored. Is
this a bug or a choice ?Thanks.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/nuxt/nuxt.js/issues/112#issuecomment-283826836, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AB4d3VhJOeuH7bF4qEmBvbYE6cj_VeFsks5rh134gaJpZM4LfX28
.
It's a choice, use the middleware
instead of the meta
property (which is a king of hack from vue-router
).
Also, for the alias, it's an intended purpose since it's not good for SEO to have 2 routes which serves the same content. I you want to create an alias, you can do it by adding the route on the server-side (via express) and call nuxt.renderRoute()
Is there any way to disable the filesystem routing?
I really don't like that I need check the params in the validate() method.
This test has no place in component. Especially if we want to reuse component in several places.
@KleinMaximus Yes, via modules. Official module and examples coming soon :)
@pi0 any news on this? can you point me to where it is in the codebase?
@galvez While basic support is currently shipped with the latest alpha it is not stable yet. Enhancements will come with next release and we try providing enough documents for custom routes too :)
@pi0 can you point me to the source code? I'd be glad to help (and writing docs)
@galvez We have two options to provide and register custom routes:
1- Using module container extendRoutes() (see module.js#L76 method )
here and here are examples of extendRoutes
.
2- Using powerful tapable hooks for more advanced integrations. (see builder.js#L186 - coming in next release)
For disable file-system routing, this is an example of a completely customized router that can be set like this
btw PLEASE consider all of above pointers as UNOFFICIAL ones because better examples are coming soon :D
Hi @danieloprado,
Did you manage to solve the issue with the route aliases?
I'm in the same path and making hacks to make it work.
Thanks,
Cheers!.
My reason for wanting this is to have the same component available as a child component in different parts of the app without replicating the component's code. The SEO argument here doesn't even matter because one of the locations is a dashboard hidden to crawlers.
I should add that I have a fairly complex app already that I'm considering porting over to Nuxt but I see no benefit in rearranging everything and ditching the current router setup. I really like having all routes available at a glance in the same module.
If we have a large app using i18n as shown in the official example. I find it combersone and error prone to define the default route in pages without _lang only to import the _lang route. I wanted to write a function that auto maps the _lang routes to the default in this case and your example English. Is extended routes in config the best place for this? Would I not need the alias parameter for this as well?
@randyhoulahan I had a similar setup, where my site is set similar as as follows (via pages)
/:lang
|--> / (name 'lang')
|--> /user (name 'lang-user')
| |--> /account (name 'lang-user-account')
| |--> /settings (name 'lang-user-settings')
|--> /admin (name 'lang-admin')
|--> /login (name 'lang-login')
|--> /logout (name 'lang-logout')
|--> /signup (name 'lang-signup')
|--> etc, etc, etc
Where lang
could be en
, fr
, es
, etc, and I also wanted the path structure below /:lang
duplicated on /
(for default language of site)
Using the method shown in the example i18n
was cumbersome, and included importing all those page components in those new routes. Making hte user download the same page components again for these "duplicated" pages.
To get around this, I created the following function to take the existing routes and generate new routes without the /:lang
prefix:
function makeRoutes (routesIn) {
const routes = []
routesIn.forEach(r => {
let path = r.path
let name = r.name
let children = r.children
const component = r.component // re-use the same component/page
// Remove the /:lang prefix from the path
path = path.replace('/:lang', '')
// Adjust the route's name
if (name === 'lang') {
// Special case for /:lang index.vue page
name = 'index' // or you could make this an empty string name ""
// This becomes the new root index file
path = '/'
} else if (name) {
name = name.replace(/^lang-/, '')
}
// If the route has child routes, process them recursively
if (children) {
children = makeRoutes(children)
}
// Create the new route entry
const route = {
path: path,
name: name,
component: component,
}
// Add the child routes if needed
if (children) {
route.children = children
}
// Add the route to our routes array
routes.push(route)
})
// Return the new routes
return routes
}
Then in my nuxt.config.js
file, I did the following in the router section::
router: {
extendRoutes (routes) {
// Generate our non language routes
const newRoutes = makeRoutes(routes);
// Add our routes **in front** of the existing routes
routes.unshift(...newRoutes);
}
}
And voila, all my /:lang
routes are now available at /
, which re-use the same webpack chunked components. Say the default language was en
,, and user was at /user/account
, and then navigated on the browser to /fr/user/account
, the page updates immediately as nothing needs to be downloaded again, as this uses the exact same chunked page component.
I couldn't push the new routes onto the existing routes, as the /:lang
slug took precedence (on the server side in connect), so i had to unshift
them onto the front of the original page defined routes.
The new named routes are have the 'lang-' removed from the front (i.e. lang-user-account
is now also lang-user
), with the exception of named route lang
which is now called index
(although you could alter the code to name it "").
I have to alter my site navigation to handle the presence/absence of lang
, but it was minor adjustments (All links used named routes, and I jut strip of 'lang-' if the current route.name isn't prefixed with 'lang-', and a special case for 'lang' => 'index')
Here is what the final route structure becomes:
/ (name 'index')
/user (name 'user')
|--> /account (name 'user-account')
|--> /settings (name 'user-settings')
/admin (name 'admin')
/login (name 'login')
/logout (name 'logout')
/signup (name 'signup')
etc, etc, etc
/:lang
|--> / (name 'lang')
|--> /user (name 'lang-user')
| |--> /account (name 'lang-user-account')
| |--> /settings (name 'lang-user-settings')
|--> /admin (name 'lang-admin')
|--> /login (name 'lang-login')
|--> /logout (name 'lang-logout')
|--> /signup (name 'lang-signup')
|--> etc, etc, etc
The other option to above is to do the opposite. Create all your page without any /:lang
prefix, and then generate your new routes with a path-prefix of /:lang
and prepend the lang-
in front of the name (index
becomes lang-index
), and then push the new routes on the end of the existing routes. You just have to check if the route has a name or not (name will be undefined
for intermediate routes with children, and child routes usually wont have the /:lang
prefix, so you could just append the child routes as is)
Thank You @tmorehouse ! Nice work here. I think your code should be moved into the example for i18n as the default setup.
I've made some changes to my code.. I'll post new code here shortly. I switched it up and removed the /:lang
base path, and created the project without it, then add it in via a script. Gets rid of the special cases for index..
And I should say it works quite well. I use a middleware to detect the language, hav3 a defsult language set (which doesn't use the prefix), and do a bit of redirection depending on the locale. Created a make-link getter in the store that inspects the named route, the Lang param, etc, for making the navigation links (so they adjust based on the current locale selected)
any updates on this? much appreciated! @tmorehouse
I should be able to post something shortly...
I'd be very curious to see your work aswell @tmorehouse !
I recently pushed a sample project to show my current way of dealing with this: https://github.com/paulgv/nuxt-i18n-routing
Maybe we can share some ideas to improve all this i18n madness 😄
@iskanderbroere Here is my final setup:
Pages set up as follows (showing auto-generated route names):
/ (name 'index')
/user (name 'user')
|--> /account (name 'user-account')
|--> /settings (name 'user-settings')
/admin (name 'admin')
/login (name 'login')
/logout (name 'logout')
/signup (name 'signup')
/etc, etc, etc
Here is the function that takes the above routes and generates new routes with the /:lang
prefix:
function makeLangRoutes (routesIn, param = 'lang', isChild = false) {
if (typeof param !== 'string' && !param) {
// Bail if no parameter specified
return [];
}
const routes = []
routesIn.forEach(r => {
let path = r.path
let name = r.name
let children = r.children
const component = r.component
// Only change the path of top level (root) routes
if (!isChild && path) {
path = `/:${param}${path === '/' ? '' : path}`
}
// prefix named route with 'lang-'
name = name ? `${param}-${name}` : name
// Handle child routes (recursive)
children = children ? makeLangRoutes(children, param, true) : children
// Build a new route object
const route = { path, name, component }
if (children) {
route.children = children
}
// Append the new route
routes.push(route)
})
// Return the new array of routes
return routes
}
Then in my nuxt.config.js
file, I did the following in the router section::
router: {
extendRoutes (routes) {
// Generate our non language routes
const newRoutes = makeLanRoutes(routes, 'lang');
// Add our new language routes after existing routes:
routes.push(...newRoutes);
}
}
The new named routes are have the 'lang-' appended the front (i.e. user-account
is now also lang-user-account
, and index
is now also lang-index
),
Here is what the final route structure becomes:
/ (name 'index')
/user (name 'user')
|--> /account (name 'user-account')
|--> /settings (name 'user-settings')
/admin (name 'admin')
/login (name 'login')
/logout (name 'logout')
/signup (name 'signup')
etc, etc, etc
/:lang
|--> / (name 'lang-index')
|--> /user (name 'lang-user')
| |--> /account (name 'lang-user-account')
| |--> /settings (name 'lang-user-settings')
|--> /admin (name 'lang-admin')
|--> /login (name 'lang-login')
|--> /logout (name 'lang-logout')
|--> /signup (name 'lang-signup')
|--> etc, etc, etc
If the lang
param is not present, I assume the default language in my middleware (i.e. en
). If the lang
pram is provided,and it is equal to my default lang, I set my store.locale to the default, and then redirect to a named route without the lang-
prefix.
I have a function to generate my navigation links (which use named routes), and either prefix lang-
if needed.
my i18n
middleware does the following to handle redirecting back to the default language:
export default function ({ isHMR, isServer, isClient, req, app, store, route, params, query, error, redirect }) {
if (isHMR) return
let locale = params.lang | store.state.user.locale || null
const defLocale = store.state.default.locale
if (!locale) {
locale = defaultLocale || 'en'
}
if (store.state.locales.indexOf(locale) === -1) {
return error({
message: 'This specific language page could not be found.',
statusCode: 404
})
}
// Set locale
store.commit('SET_LANG', locale)
app.i18n.locale = store.state.locale
let name = route.name
if (locale === defaultLocale && /^lang-/.test(route.name)) {
name = name.replace(/^lang-?/, '')
params = Object.assign({}, params)
delete params.lang
let href = app.router.resolve({ name, params }).href
return redirect(href, query)
}
}
And in my store, I have the following getter to generate to
props for router-links:
makeLink: (state, getters) => {
const langRx = /^lang-/
// We use a function rather than arrow, so that "this" will be context of component
return function (name, params = {}, query = {}) {
const $route = this.$route
const $router = this.$router
// If we are on lang- route, add lang- prefex to route name
if (langRx.test($route.name) && !langRx.test(name)) {
name = `lang-${name}`
}
// New params object. We merge prams last, in case we want to overide the detected language
params = Object.assign($route.params.lang ? { lang: $route.params.lang } : {}, params)
const resolved = $router.resolve({ name, params, query })
return resolved.location
}
}
And when generating a router link, I just refer to the route by name (without the lang-
prefix. The above getter will add the lang-
prefix if needed, or if I want to switch to a particular language route, I call the getter with the lang-prefix
on the route name and pass the language I want as params object:
<!-- Use the current language specified by current URL -->
<router-link :to="makeLink('user-account')>Account</router-link>
<!-- Change language -->
<router-link :to="makeLink('lang-user-account', {lang: 'fr')>Compte</router-link>
@tmorehouse Do you know of a way to check if a locale file exists? require or import fails if the file is not there yet. Some components are fully translated while others are not. I have dummy files in place now but I was hoping to remove them. Thank You
@tmorehouse Sorry, also have you lazy loaded translations per component?
Just on vacation right now... will be back in a week.
To prepend locale to urls, I would use following code for nuxt.config.js
:
router: {
extendRoutes (routes) {
const locale = '/:locale(en|ku)?'
routes.forEach(r => {
r.path = locale + r.path
})
}
}
And a wrapper link
component:
const prependLocale = (locale, path) => {
if (!locale || /^/(en|ku)(/.+)?$/.test(path)) {
return path
}
return `/${locale}/${path.replace(/^\/+/, '')}`.replace(/\/+$/, '')
}
export default {
name: 'app-link',
functional: true,
render(h, { data, children, parent: { $route } }) {
let to = (data.attrs && data.attrs.to) || ''
if (typeof to === 'string') {
to = prependLocale($route.params.locale, to)
} else if (typeof to === 'object') {
to.params = to.params || {}
to.params.locale = to.params.locale || $route.params.locale
}
if (data.attrs) {
data.attrs.to = to
} else {
data.attrs = { to }
}
return h('nuxt-link', data, children)
},
}
And also don't forget to prepend locale for redirects.
@Atinux, the point about not good for SEO is only true when you are starting a new project but if you already have a project migrating to VueJS there will be many pages whose url structure could have changed but would be linking as alternate links and still preserve SEO, then you should you have the ability to add alias then? I believe this is a very valid case.
I'm facing this issue and don't know how to solve this
@1hakr I suggest to use directly the router-module to be able to respect the SEO you already have (it's easier for a migration).
@Atinux , i was able to achieve this with declaring another path in extendRoutes instead of using alias
by extending router module
extendRoutes (routes) {
routes.push({name: 'old-path', path: '/old-path', component: '~pages/index.vue'})
}
I hope this i will be useful to others.
@1hakr You can also simply replace all routes altogether.
https://vuejsdevelopers.com/2018/07/16/7-tips-large-nuxt-app-vue/
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
I'll keep it open to look for a possible solution, but as I think it right now, the most flexible way would be with an
extendRoutes
method in therouter
property:nuxt.config.js
This method would be used at your own risks, like
build.extend
for extending webpack configuration.