Routing
Nuxt.js automatically generates the vue-router configuration based on your file tree of Vue files inside the
pages
directory.
To navigate between pages, we recommend to use the <nuxt-link>
component.
For example:
<template>
<nuxt-link to="/">Home page</nuxt-link>
</template>
Basic Routes
This file tree:
pages/
--| user/
-----| index.vue
-----| one.vue
--| index.vue
will automatically generate:
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'user',
path: '/user',
component: 'pages/user/index.vue'
},
{
name: 'user-one',
path: '/user/one',
component: 'pages/user/one.vue'
}
]
}
Dynamic Routes
To define a dynamic route with a parameter, you need to define a .vue file OR a directory prefixed by an underscore.
Watch a free lesson about dynamic routes on Vue School
This file tree:
pages/
--| _slug/
-----| comments.vue
-----| index.vue
--| users/
-----| _id.vue
--| index.vue
will automatically generate:
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'users-id',
path: '/users/:id?',
component: 'pages/users/_id.vue'
},
{
name: 'slug',
path: '/:slug',
component: 'pages/_slug/index.vue'
},
{
name: 'slug-comments',
path: '/:slug/comments',
component: 'pages/_slug/comments.vue'
}
]
}
As you can see the route named users-id
has the path :id?
which makes it optional, if you want to make it required, create an index.vue
file in the users/_id
directory instead.
Warning: dynamic routes are ignored by the generate
command: API Configuration generate
Validate Route Params
Nuxt.js lets you define a validator method inside your dynamic route component.
In this example: pages/users/_id.vue
export default {
validate ({ params }) {
// Must be a number
return /^\d+$/.test(params.id)
}
}
If the validate method does not return true
or a Promise
that resolve to true
, or throws an Error, Nuxt.js will automatically load the 404 error page or 500 error page in case of an error.
More information about the validate method: API Pages validate
Nested Routes
Nuxt.js lets you create nested route by using the children routes of vue-router.
To define the parent component of a nested route, you need to create a Vue file with the same name as the directory which contain your children views.
Warning: don't forget to include <nuxt-child/>
inside the parent component (.vue
file).
This file tree:
pages/
--| users/
-----| _id.vue
-----| index.vue
--| users.vue
will automatically generate:
router: {
routes: [
{
path: '/users',
component: 'pages/users.vue',
children: [
{
path: '',
component: 'pages/users/index.vue',
name: 'users'
},
{
path: ':id',
component: 'pages/users/_id.vue',
name: 'users-id'
}
]
}
]
}
Dynamic Nested Routes
This scenario should not often happen, but it is possible with Nuxt.js: having dynamic children inside dynamic parents.
This file tree:
pages/
--| _category/
-----| _subCategory/
--------| _id.vue
--------| index.vue
-----| _subCategory.vue
-----| index.vue
--| _category.vue
--| index.vue
will automatically generate:
router: {
routes: [
{
path: '/',
component: 'pages/index.vue',
name: 'index'
},
{
path: '/:category',
component: 'pages/_category.vue',
children: [
{
path: '',
component: 'pages/_category/index.vue',
name: 'category'
},
{
path: ':subCategory',
component: 'pages/_category/_subCategory.vue',
children: [
{
path: '',
component: 'pages/_category/_subCategory/index.vue',
name: 'category-subCategory'
},
{
path: ':id',
component: 'pages/_category/_subCategory/_id.vue',
name: 'category-subCategory-id'
}
]
}
]
}
]
}
Unknown Dynamic Nested Routes
If you do not know the depth of your URL structure, you can use .vue
to dynamically match nested paths.This will handle requests that do not match a _more specific request.
This file tree:
pages/
--| people/
-----| _id.vue
-----| index.vue
--| _.vue
--| index.vue
Will handle requests like this:
Path | File |
---|---|
/ | index.vue |
/people | people/index.vue |
/people/123 | people/id.vue |
/about | .vue |
/about/careers | .vue |
/about/careers/chicago | .vue |
Note: Handling 404 pages is now up to the logic of the _.vue
page. More on 404 redirecting can be found here.
Named Views
To render named views you can use <nuxt name="top"/>
or <nuxt-child name="top"/>
components in your layout/page. To specify named view of page we need to extend router config in nuxt.config.js
file:
export default {
router: {
extendRoutes(routes, resolve) {
let index = routes.findIndex(route => route.name === 'main')
routes[index] = {
...routes[index],
components: {
default: routes[index].component,
top: resolve(__dirname, 'components/mainTop.vue')
},
chunkNames: {
top: 'components/mainTop'
}
}
}
}
}
It require to extend interested route with 2 properties components
and chunkNames
. Named view in this config example has name top
.
To see an example, take a look at the named-views example.
SPA fallback
You can enable SPA fallbacks for dynamic routes too. Nuxt.js will output an extra file that is the same as the index.html
that would be used in mode: 'spa'
. Most static hosting services can be configured to use the SPA template if no file matches. It won't include the head
info or any HTML, but it will still resolve and load the data from the API.
We enable this in our nuxt.config.js
file:
export default {
generate: {
fallback: true, // if you want to use '404.html' instead of the default '200.html'
fallback: 'my-fallback/file.html' // if your hosting needs a custom location
}
}
Implementation for Surge
Surge can handle both 200.html
and 404.html
. generate.fallback
is set to 200.html
by default, so no need to change it.
Implementation for GitHub Pages and Netlify
GitHub Pages and Netlify recognize the 404.html
file automatically, so setting generate.fallback
to true
is all we have to do!
Implementation for Firebase Hosting
Firebase Hosting can handle the 404.html
file automatically, so setting generate.fallback
to true
will render the error page with a default response code of 404.
Transitions
Nuxt.js uses the <transition>
component to let you create amazing transitions/animations between your routes.
Global Settings
Info: Nuxt.js default transition name is "page"
.
To add a fade transition to every page of your application, we need a CSS file that is shared across all our routes, so we start by creating a file in the assets
folder.
Our global css in assets/main.css
:
.page-enter-active, .page-leave-active {
transition: opacity .5s;
}
.page-enter, .page-leave-to {
opacity: 0;
}
Then we add its path to the css
array in our nuxt.config.js
file:
export default {
css: [
'~/assets/main.css'
]
}
More information about the transition key: API Configuration transition
Page Settings
You can also define a custom transition for a specific page with the transition
property.
We add a new class in our global css in assets/main.css
:
.test-enter-active, .test-leave-active {
transition: opacity .5s;
}
.test-enter, .test-leave-active {
opacity: 0;
}
Then we use the transition property to define the class name to use for this page transition:
export default {
transition: 'test'
}
More information about the transition property: API Pages transition
Middleware
Middleware lets you define custom functions that can be run before rendering either a page or a group of pages.
Every middleware should be placed in the middleware/
directory. The filename will be the name of the middleware (middleware/auth.js
will be the auth
middleware).
A middleware receives the context as first argument:
export default function (context) {
context.userAgent = process.server ? context.req.headers['user-agent'] : navigator.userAgent
}
In universal mode, middlewares will be called server-side once (on the first request to the Nuxt app or when page refreshes) and client-side when navigating to further routes. In SPA mode, middlewares will be called client-side on the first request and when navigating to further routes.
The middleware will be executed in series in this order:
nuxt.config.js
(in the order within the file)- Matched layouts
- Matched pagesA middleware can be asynchronous. To do this, simply return a
Promise
or use the 2ndcallback
argument:
middleware/stats.js
import axios from 'axios'
export default function ({ route }) {
return axios.post('http://my-stats-api.com', {
url: route.fullPath
})
}
Then, in your nuxt.config.js
, use the router.middleware
key:
nuxt.config.js
export default {
router: {
middleware: 'stats'
}
}
Now the stats
middleware will be called for every route change.
You can add your middleware to a specific layout or page as well:
pages/index.vue
or layouts/default.vue
export default {
middleware: 'stats'
}
To see a real-life example using the middleware, please see example-auth0 on GitHub.