You are on page 1of 557

Creating a Nuxt module

Jamie Curnow Follow


Jul 19, 2019 · 17 min read
Photo by Daniel Chen on Unsplash

For our most recent project we are using a mono-repo setup with Lerna and
Yarn workspaces which gives us an excellent opportunity to create our own
local Node packages, writing more maintainable and useable code. All of
our front end apps run on Nuxt.js and I quite quickly found that I needed to
install Vue plugins, and add to the Vuex store from within a module, while
still keeping the context of the Nuxt app.

In this post, I will explain with code examples how to create a Nuxt module
as a local Node package. This could be easily extended to publish the
package on NPM if desired. I’ll cover the basic setup of a Nuxt module that
can be easily extended, including features such as passing options to the
module, creating a new Vuex store module, creating middleware, and
registering components.

TLDR;
Code repo here:
https://github.com/carepenny/nuxt-module

Let’s get started…


For the purposes of this tutorial, we’ll call our Nuxt module
`customCounter`. You can call it whatever you like.

The first thing to do is scaffold out your new package. In a new directory,
run
yarn init

In our case, we’re using Yarn workspaces and Lerna to manage local
packages, so for the name of the package, I’ll use `@carepenny/custom-
counter` you can use any name you want, following your repo standards or
NPM publishing standards.

The version and description are up to you.

Since we’re going to roughly follow Nuxt’s module naming standards, we’ll
use `module.js` as our entry point.

Repo URL, author, license and private options are up to you.

You should end up with a lonely `package.json` in your directory, which is


where you would add all of your dependencies for the module. In this case,
to keep things simple, we won’t need any other external packages for our
module to work, but you could `yarn add` any external or internal package
in your module.

In the Nuxt examples for modules, they recommend having `lib` folder in
your module directory including a `module.js` and `plugin.js file`. We’re
going to take it a step further and create the following directories and files:

./module.js (our entry point)

./debug.js (used for debugging)

./components/index.js (component registerring plugin)

./components/lib/index.js (exposing all components in a single place)

./components/lib/counterAdjuster.vue (a custom component)

./middleware/index.js (some custom middleware)

./plugins/index.js (injecting a custom function object into Nuxt)

./plugins/helpers/index.js (exposing all plugin functions)

./plugins/helpers/message.js (a function to console log a message)

./plugins/helpers/counter.js (a function to adjust the counter in the


store)

./store/index.js (store registering plugin)

./store/modules/counter.js (the vuex store holding the counter data,


mutations and getters)

Create all of those files in your package:


mkdir -p {components/lib,middleware,plugins/helpers,store/modules} \
&& touch module.js debug.js \
{components,components/lib,middleware,plugins,plugins/helpers,store}/
index.js \
components/lib/counterAdjuster.vue \
plugins/helpers/{message,counter}.js \
store/modules/counter.js

This file structure is a little over-the-top for a simple module such as this,
but we’ll use it to demonstrate how a Nuxt module could be extensive and
still easily managed.

Setting up the entry point


The entry point of the module `module.js` is where we’ll scaffold out the
module, tell Nuxt what files to create and where to create them, manage
module options and set off all of the plugins for the module.

There are two things a Nuxt module must do. The first is to export a default
function where all of our code will be held. This function has access to a
`moduleOptions` object that contains the options passed through to the
module directly when declaring it in an array format in your
`nuxt.config.js` (more on that in a minute).
// module.js
export default function(moduleOptions) {}

The second thing we must do is add our modules `package.json` to a meta


key on the module export… Sounds confusing but it’s a one-liner-and-
forget that Nuxt uses under the hood to avoid registering the same module
twice.

// module.js
module.exports.meta = require('./package.json')

Our `module.js` should currently look like this:

// module.js
export default function(moduleOptions) {}

module.exports.meta = require('./package.json')

Let’s get the options for the module and spread them into a single options
object. The options for the module can come from two places depending on
how you define the module in your `nuxt.config.js`. If you define the
module options like this:

// nuxt.config.js
export default {
// ...
// register modules:
modules: [
// ...
[@carepenny/custom-counter, { option1: 'something' }]
]
}

Then the `moduleOptions` variable in `module.js` will be:

{ option1: 'something' }

However, you can also define the module options independently in your
Nuxt config like this:

// nuxt.config.js
export default {
// ...
// register modules:
modules: [
// ...
'@carepenny/custom-counter'
],
// custom-counter options:
customCounter: { option1: 'something' }
}

In this case, the `moduleOptions` variable in `module.js` will be empty,


however, we can access any of the `nuxt.config.js` through `this.options`
(which is a little confusing). eg:

// module.js
export default function(moduleOptions) {
console.log(this.options.customCounter) // { option1: 'something' }
}

module.exports.meta = require('./package.json')

It’s obviously important here to document what the object in the nuxt
config should be called and to make it unique enough so that it doesn’t
clash with other modules or Nuxt options.

You can combine these methods of passing options and of course if this is a
public package, the end users have the options to use either of these
methods to pass options to your module. So we need to handle both of these
scenarios and for our sanity, we’ll create a new `options` object that we will
use everywhere else in the module side of our code.

// module.js
export default function(moduleOptions) {
// get all options for the module
const options = {
...moduleOptions,
...this.options.customCounter
}
}

module.exports.meta = require('./package.json')

The options that we’re going to pass through for our `customCounter`
example module are:

namespace
Providing an example of customising the naming of the store/plugin etc
and allowing the user to avoid conflicts with their own code.

initialValue
Providing an example of setting up state for our store module and
allowing the user to set an initial value for the counter.
debug
Provides an easy way to debug the module and see what’s going on. For
now, this will be simply console logging the options that we pass
through to the module.

Let’s update the nuxt config to pass through these options using both
methods:

// nuxt.config.js
export default {
// ...
// register modules:
modules: [
// ...
['@carepenny/custom-counter', { namespace: 'counter' }]
],
// custom-counter options:
customCounter: { initialValue: 6, debug: true }
}

That’s all we need to do in the nuxt config. From here on, we’ll be building
out the module.

Building out the module


In Nuxt modules, there are a few methods available on the `this` object.
One of those is the `addPlugin()` method which takes an object for its
params. This method allows the module to add new plugins to Nuxt.

(Docs: https://nuxtjs.org/api/internals-module-container/#addplugin-
template-)

The `addPlugin` method is used like this:

// module.js
const { resolve, join } = require('path')

export default function(moduleOptions) {


// get all options for the module
const options = {
...moduleOptions,
...this.options.customCounter
}

// add the debug plugin


this.addPlugin({
src: resolve(__dirname, 'debug.js'),
fileName: join('customCounter', 'debug.js'),
options: {
...options,
somethingElse: false
}
})
}

module.exports.meta = require('./package.json')
The params for the `addplugin` method are:

src
The path to the file containing plugin logic. We use the path module
here and its resolve function to resolve the path when the module is
being built by Nuxt.

filename
This string is the name of the file that Nuxt will end up building. It can,
however, include a path and Nuxt will create the directories and file at
build time. We use the path module’s join function to create the path
string.

options
This object is used to pass variables through to the plugin file. Under the
hood, Nuxt uses Lodash templates to pass these through. We use a little
snippet to just get the options back out into a javascript object in the
plugin file. More on that in a minute…

One other thing we need to do right from the start is to handle the
`namespace` variable. We’re going to use this to:
name the global nuxt methods that we will inject through a plugin,

name the directory that nuxt builds our plugin in,

add a prefix to our store module,

add a prefix to the custom middleware.

Doing this will negate the risk of naming conflicts in our Nuxt app and it’s a
great example of how powerful nuxt modules are. Remember that we set
the `namespace` variable for the module in our `nuxt.config.js` to
`counter`. We’ll expose the namespace variable right after we create the
options object in our module and set a default for it in case it is undefined.

// module.js
const { resolve, join } = require('path')

export default function(moduleOptions) {


// get all options for the module
const options = {
...moduleOptions,
...this.options.customCounter
}

// expose the namespace / set a default


if (!options.namespace) options.namespace = 'customCounter'
const { namespace } = options

// add the debug plugin


this.addPlugin({
src: resolve(__dirname, 'debug.js'),
// ** NOTE: we now use namespace here: **
fileName: join(namespace, 'debug.js'),
options // just pass through the options object
})
}
module.exports.meta = require('./package.json')

Creating the plugin files


Let’s open up the `debug.js` plugin file and demonstrate how to retrieve
the options passed through from the `addPlugin` method in the module
file.

// debug.js
const options = JSON.parse(`<%= JSON.stringify(options) %>`)
const { debug, namespace } = options
if (debug) {
console.log(`${namespace} options: `, options)
}

Here we pluck out all the options using Lodash templates and
JSON.stringify().

If you run `nuxt dev` or `yarn run dev` back in your Nuxt project, you
should see the options passed all the way through from `nuxt.config.js` to
the `debug.js` file.

{
namespace: 'counter',
initialValue: 6,
debug: true
}

We can use this pattern for all plugins that we need to register through our
module.

Other than the Lodash templates, the plugin files in the module is a normal
Nuxt plugin file and you can write it exactly the same as a normal nuxt
plugin. It has access to Vue for registering components etc. and if you export
a default function from the plugin file, you have access to the nuxt context
and the `inject` method.

The rest of our plugins will live under the `plugins/helpers` directory that
we created. The next thing that we’ll do is write the functions for
`plugins/helpers/message.js` and `plugins/helpers/counter.js`. These
functions are pretty self-explanatory and the comments on them should
give you enough info to see what they are doing.
// plugins/helpers/message.js
// funtion to allow a user to console.log() a value,
// prefixing that value with the namespace option of our module.
export const message = ({ namespace, string }) => {
return console.log(namespace, string)
}

// plugins/helpers/counter.js
// functions to get, adjust and log the counter in the store
// the store module in question will be created with the namespace
// module option as it's name

// mini function to handle if no store, or no store module


// with our namespace exists
const storeModuleExists = ({ state, namespace }) => {
if (!state || !state[namespace]) {
console.error(`${namespace} nuxt module error: store not
initialized`)
return false
} else {
return true
}
}

// function to return the current value of the count


export const value = ({ state, namespace }) => {
// handle no store:
if (!storeModuleExists({ state, namespace })) return undefined
// return the counter vale from the store
return state[namespace].count
}

// functions to adjust the counter


export const adjust = ({ state, store, namespace, adjustment }) => {
// handle no store:
if (!storeModuleExists({ state, namespace })) return undefined
// the adjustment shoud be of type number, err if not
if (typeof adjustment !== 'number') {
return console.error(`${namespace} nuxt module error: adjustment
should be of type 'number'.`)
}
// adjust the value of the counter using a store mutation
return store.commit(`${namespace}/adjust`, adjustment)
}

// function to console log the current value of the count


export const log = ({ state, namespace }) => {
// handle no store:
if (!storeModuleExists({ state, namespace })) return undefined
// get the current count from the store
const { count } = state[namespace]
// console log it
return console.log(count)
}

We will then export these methods from the `plugins/helpers/index.js`


file, which is not really necessary with such a small module, but will set us
up for easily extending in the future.

// plugins/helpers/index.js
export * from './counter'
export * from './message'

This simply allows us to import all the helpers at once in the


`plugins/index.js` file which we will now build out…
The `plugins/index.js` file will apply a new global set of methods to the
Vue instance of our Nuxt app using Nuxt’s `inject()` function which is
available along with the context of the app in Nuxt plugin files when you
export a default function. (Nuxt inject docs). Inject is used like this:

// some/nuxt/plugin/file.js
export default (context, inject) => {
inject('myFunction', (string) => console.log('Hello', string))
}

Which adds `$myFunction` to the Vue prototype so you can use it in any
Vue instance like this:

// some/vue/file.vue
export default {
// ...
mounted () {
this.$myFunction('World')
}
}

You also have access to it in the Vuex store modules:


// some/vuex/store/module.js
// ...
export const actions = {
someAction () {
this.$myFunction('Store')
}
}

And it is also attached to the Nuxt context on the `app` object so you can
use it in other plugin files:

// some/other/nuxt/plugin/file.js
export default ({ app }) => {
app.$myFunction('This is awesome')
}

As you can see, Nuxt’s inject function is very powerful and easily makes
code reusable throughout the app.

Our plugin will be using the functions that we exported in


`plugins/helpers/index.js` and injecting them into the app under an object
with the name that was provided as the `namespace` variable. It will look
like this:
// plugins/index.js
import * as helpers from './helpers/index.js'
// get the options out using lodash templates
const options = JSON.parse(`<%= JSON.stringify(options) %>`)
// extract the namespace from the options
const { namespace } = options
// create the plugin
export default ({ store }, inject) => {
// get a reference to the vuex store's state
const { state } = store
// inject an object of functions into the app
inject(namespace, {
value() {
return helpers.value({ state, namespace })
},
adjust(adjustment) {
return helpers.adjust({ state, store, namespace, adjustment })
},
log() {
return helpers.log({ state, namespace })
},
message(string) {
return helpers.message({ namespace, string })
}
})
}

Now we need to create the Vuex store module through our plugin so that
the functions inside `plugins/helpers` can do their thing.

Creating Vuex store modules


We will structure our code for registering the Vuex store module by putting
all of the module logic in the `store/modules` directory and we’ll register
the store modules in `store/index.js`. This may be a little over-the-top for
this instance, but it provides a good example of easily extendable code.
We’ll start with `store/modules/counter.js` which will hold our
state/mutation/getters for the counter. We will pass through the plugin
options when calling this function so that we can set an initial value and
expose the options in the Vuex state for use in components etc. If you’re
familiar with Vuex, this should be pretty straight forward (If not, you have
some further reading to do):

// store/modules/counter.js
export default options => ({
namespaced: true,
state: () => ({
options,
count: options.initialValue
}),
mutations: {
adjust(state, data) {
state.count += data
}
},
getters: {
count: state => state.count
}
})
Then we’ll add that module to Vuex in `store/index.js`. This is done using
the Vuex store’s `registerModule()` function (Vuex Docs). The important
thing to note here is the use of the `preserveState` option which will
preserve the previous state when registering a new module. We set this to
`true` if a store module with the same name already exists. This saves
conflicts with the apps store modules and doesn’t override the state if it’s
mutated server-side.

// store/index.js
import counterModule from './modules/counter'
// get the options out using lodash templates
const options = JSON.parse(`<%= JSON.stringify(options) %>`)
// extract the namespace var
const { namespace } = options
// create the plugin
export default ({ store }, inject) => {
// register the module using namespace as the name.
// counter module takes the options object and returns an object
that is a
// vuex store defenition
store.registerModule(namespace, counterModule(options), {
preserveState: Boolean(store.state[namespace]) // if the store
module already exists, preserve it
})
}

That’s all we need to do to register store modules!


Defining and registering components
We can define components in our module that will be registered globally
and available for use throughout the app. The component templates will be
defined in `components/lib/*` and can be any flavour of component that
you like (SFC/Render function) as Nuxt will compile and build them like
any other component. We will expose all of our component files in
`components/lib/index.js` and then import and register them all in
`components/index.js`.

Lets start with a really simple component in


`components/lib/counterAdjuster.vue`:

<template lang="html">
<div class="custom-counter">
<!-- Basic html to render the current count and provide
adjustment buttons -->
<h1>Count is: {{ count }}</h1>
<button class="custom-counter--button"
@click="adjust(-1)">Minus</button>
<button class="custom-counter--button"
@click="adjust(+1)">Add</button>
</div>
</template>

<script>
// components/lib/counterAdjuster.vue
export default {
computed: {
pluginOptions() {
// _customCounterOptions will be added as a prop on component
registration.
// it will be the plugin's options object
return this._customCounterOptions || {}
},
// helper to get the name of our injected plugin using the
namespace option
injectedPluginName() {
const { pluginOptions } = this
return pluginOptions.namespace ? '$' + pluginOptions.namespace
: undefined
},
// helper to return the current value of the counter using our
injected plugin function
count() {
const { injectedPluginName } = this
return injectedPluginName
? this[injectedPluginName].value() // same as
this.$count.value()
: undefined
}
},
methods: {
// method to adjust the counter using our injected plugin
function
adjust(adjustment) {
const { injectedPluginName } = this
this[injectedPluginName].adjust(adjustment)
}
}
}
</script>

<style lang="scss" scoped></style>


This component is very straight forward, but one thing to note is the
`_customCounterOptions` variable in the `pluginOptions()` computed
prop. This var is actually a prop passed into the component on registration
which allows us to access the options of the module from within the
component — importantly the `namespace` option. We’ll set this up in a
minute, but next, we’ll quickly create the `components/lib/index.js` which
simply exposes any components from the `components/lib` folder for easy
registration:

// components/lib/index.js
import counterAdjuster from './counterAdjuster.vue'
export default {
counterAdjuster
}

Now let’s register our component globally using `Vue.component()` (Vue


docs). We will use the `extends` option to extend our imported
components, adding the `_customCounterOptions` prop that is needed to
access our module options from within the component files.

// components/index.js
import Vue from 'vue'
import components from './lib'
// get options passed from module.js
const options = JSON.parse(`<%= JSON.stringify(options) %>`)
// loop through components and register them
for (const name in components) {
Vue.component(name, {
// extend the original component
extends: components[name],
// add a _customCounterOptions prop to gain access to the options
in the component
props: {
_customCounterOptions: {
type: Object,
default: () => ({ ...options })
}
}
})
}

The for loop there simply loops over every component exported from
`components/lib/index.js` and registers them using their export name as
the component name. We can then use the component in any
layout/page/component by it’s name eg.:

// some/random/page.vue
<template lang="html">
<counterAdjuster></counterAdjuster>
</template>

<script>
export default {}
</script>
That’s it for components, now onto the final type of registration —
middleware.

Adding Nuxt Middleware


Adding middleware to Nuxt through a module is not very well documented
(as far as I could find), but it is very simple indeed. All you need to do is
import Nuxt’s middleware object from the nuxt build folder. Remember
that all of our files will be put into the nuxt build folder at build time, so we
should import the middleware object as if we were in our build destination.
For example, the nuxt middleware can be imported from
`.nuxt/middleware.js` (assuming your build folder is `.nuxt`). We will be
replicating our module directory structure in the build folder under a
directory with the same name as the `namespace` option passed to the
module (more on this in the next step). So the relative path from our
`middleware/index.js` file to the nuxt `middleware.js` file is
`../../middleware.js`. After we have access to the nuxt middleware object,
we can simply add a new function to the object, giving us access to the
context of the app, just like adding a default export from a nuxt middleware
file. From there, you can do anything that is achievable in a standard
middleware file. (Nuxt middleware docs):
// middleware/index.js
import Middleware from '../../middleware'
const options = JSON.parse(`<%= JSON.stringify(options) %>`)
const { namespace } = options
Middleware[namespace] = context => {
const { route, store, app } = context
// simply console logging here to demonstrate access to app
context.
console.log('Counter middleware route', route.path)
console.log('Counter middleware store',
store.state[namespace].count)
console.log('Counter middleware app', app[`$${namespace}`].value())
}

It’s important to note that you still need to register the middleware by name
in the `nuxt.config.js`

The middleware will not be registered and used by Nuxt automatically —


just like any other middleware you’ll need to register it on a page-by-page
basis, or globally in the `nuxt.config.js`. As you can see above we used the
`namespace` variable from the module options to add the middleware
function to the Nuxt middleware object, so the name of the middleware in a
page or `nuxt.config.js` will be the same as the module’s
`options.namespace` var, which in our case defaults to `customCounter`
but was set as `counter` when we registered the module.
// nuxt.config.js
{
// ...
router: {
middleware: ['counter']
},
// ...
modules: [
['@carepenny/custom-counter', { namespace: 'counter' }]
]
}

Registering all of our plugins and adding files to


the nuxt build folder
The final step for our module is to make sure all of the work in all of the files
above gets built into our nuxt build folder and all of the plugins get
registered. This will all happen in the `module.js file`. We’ve already
partially set up `module.js` and talked about nuxt’s `addPlugin()` function
that is available in the default export function. Our `module.js` currently
looks like this:

// module.js
const { resolve, join } = require('path')

export default function(moduleOptions) {


// get all options for the module
const options = {
...moduleOptions,
...this.options.customCounter
}

// expose the namespace / set a default


if (!options.namespace) options.namespace = 'customCounter'
const { namespace } = options

// add the debug plugin


this.addPlugin({
src: resolve(__dirname, 'debug.js'),
// ** NOTE: we now use namespace here: **
fileName: join(namespace, 'debug.js'),
options // just pass through the options object
})
}
module.exports.meta = require('./package.json')

We’ll ditch the single `addPlugin()` function that registers the debug
plugin, and instead define an array of file-path strings to loop over and
register all of the plugins dynamically:

// module.js
const { resolve, join } = require('path')

export default function(moduleOptions) {


// get all options for the module
const options = {
...moduleOptions,
...this.options.customCounter
}
// expose the namespace / set a default
if (!options.namespace) options.namespace = 'customCounter'
const { namespace } = options

// add all of the initial plugins


const pluginsToSync = [
'components/index.js',
'store/index.js',
'plugins/index.js',
'debug.js',
'middleware/index.js'
]
for (const pathString of pluginsToSync) {
this.addPlugin({
src: resolve(__dirname, pathString),
fileName: join(namespace, pathString),
options
})
}
}
module.exports.meta = require('./package.json')

That was easy!

We’ll do the same kind of thing to get all of our plugin dependencies into
the build folder in the right location, but this time we’ll use another method
that nuxt makes available in the module’s default export function —
`addTemplate()`. This function takes an object where we can define a few
options:
src
A path to a source file

fileName
The name of the file once built in the nuxt build folder. This is a strange
name for this option because it can also be a path string like
`/some/folder/file.js`.

optoins
The options to be passed through using lodash templates, just like in
plugins.

The function by it’s self would look a little like this:

this.addTemplate({
src: resolve(__dirname, 'something.js'),
fileName: 'customCounter/something.js',
options
})

But we’re going to loop over another array of paths to directories and use
the `readdirSync` function availble in the fs module to read each file in the
directories, loop over them, and call the `addTemplate` function for each of
them. Our complete `module.js` looks a little like this:
// module.js
const { resolve, join } = require('path')
const { readdirSync } = require('fs')

export default function(moduleOptions) {


// get all options for the module
const options = {
...moduleOptions,
...this.options.customCounter
}

// expose the namespace / set a default


if (!options.namespace) options.namespace = 'customCounter'
const { namespace } = options
// add all of the initial plugins
const pluginsToSync = [
'components/index.js',
'store/index.js',
'plugins/index.js',
'debug.js',
'middleware/index.js'
]
for (const pathString of pluginsToSync) {
this.addPlugin({
src: resolve(__dirname, pathString),
fileName: join(namespace, pathString),
options
})
}
// sync all of the files and folders to revelant places in the nuxt
build dir (.nuxt/)
const foldersToSync = ['plugins/helpers', 'store/modules',
'components/lib']
for (const pathString of foldersToSync) {
const path = resolve(__dirname, pathString)
for (const file of readdirSync(path)) {
this.addTemplate({
src: resolve(path, file),
fileName: join(namespace, pathString, file),
options
})
}
}
}
module.exports.meta = require('./package.json')

To conclude
Nuxt modules are a great way to share code and separate concerns in your
applications. They provide a comprehensive way to extend Nuxt
functionality and are highly customizable. Hopefully, this tutorial clears up
some questions around modules and illuminates some undocumented parts
of module building.

Let me know if you have any suggestions on how to make this better, or if
you have any questions or issues following the tutorial, so let me know

JavaScript Nuxtjs Nodejs Development Vuejs

Learn more. Make Medium yours. Share your thinking.


Medium is an open platform where 170 Follow the writers, publications, and topics If you have a story to tell, knowledge to
million readers come to find insightful and that matter to you, and you’ll see them on share, or a perspective to offer — welcome
dynamic thinking. Here, expert and your homepage and in your inbox. Explore home. It’s easy and free to post your thinking
undiscovered voices alike dive into the heart on any topic. Write on Medium
of any topic and bring new ideas to the
surface. Learn more

About Help Legal


Sign in to your account (ti__@g__.com) for your personalized experience.

Sign in with Google Not you? Sign in or create an account


Vue.js (and Vuex) bug squasher
cheatsheet
Maximilian Øystå Lloyd Follow
Sep 2, 2018 · 3 min read

Recently I have been writing a lot of Vue, and it happens every so often that i
make the same mistakes, then it takes me 10–15 minutes to find out why it
isn’t working, so I made this cheatsheet for us. I hope this helps you in some
way. If you have any suggestions for more common bugs, please leave a
comment so I can make this article better.

1. v-show on template
When you are using v-show, Vue is changing the CSS display property. the
template tag in Vue does not actually create an element, so if you try to use
v-show, nothing will happen since Vue does not have an element to target.
solution
use v-if on the template tag or change the template tag into an element (div,
section, etc).

example
2. Why is the ref element undefined?
Most likely you are trying to access an element that is not being rendered
due to being nested somewhere within an ancestor element that has v-if
directive that evaluates to false.

solution

1. Change the v-if to v-show

2. Wait until the v-if evaluates to true, then access and start using the ref
element.
example
3. Are you targeting the correct property: Updating a property in Vuex
state
When your Vue application starts to become more complex, and you have
things that are named similarly, and perhaps more nesting than is healthy
in your data structures, it can be easy to target the incorrect property when
you are mutating the state.

solution

1. Better naming

2. Try to avoid nesting unless it is necessary or suits the situation and


double

3. check if the path to the property is correct.

example
In my app the Vuex store module was named user, then there were
properties like loggedIn, token and so on. and then also a property called
user containing the actual data. When I was importing the module into
other modules and i wanted to access the name, it would be
user.state.user.name, many times i simply just ended up typing
user.name. The two property names were essentially fighting for the same
mental ram in my head.

Vuejs JavaScript Web Development Cheatsheet ES6

Learn more. Make Medium yours. Share your thinking.


Medium is an open platform where 170 Follow the writers, publications, and topics If you have a story to tell, knowledge to
million readers come to find insightful and that matter to you, and you’ll see them on share, or a perspective to offer — welcome
dynamic thinking. Here, expert and your homepage and in your inbox. Explore home. It’s easy and free to post your thinking
undiscovered voices alike dive into the heart on any topic. Write on Medium
of any topic and bring new ideas to the
surface. Learn more

About Help Legal


Installation

Prerequisites
node - at least v10.13 We recommend you have the latest LTS version installed.

A text editor, we recommend VS Code with the Vetur extension or WebStorm

A terminal, we recommend using VS Code's integrated terminal or WebStorm terminal.

Using create-nuxt-app
To get started quickly you can use the create-nuxt-app.

Make sure you have npx installed (npx is shipped by default since npm 5.2.0) or npm v6.1 or yarn.

Yarn npx npm

yarn create nuxt-app <project-name>

It will ask you some questions (name, Nuxt options, UI framework, TypeScript, linter, testing framework, etc. To find out more about
all the options see the Create Nuxt app.

Once all questions are answered, it will install all the dependencies. The next step is to navigate to the project folder and launch it:

Yarn npm
cd <project-name>
yarn dev

The application is now running on http://localhost:3000. Well done!

Another way to get started with Nuxt.js is to use CodeSandbox which is a great way for quickly playing around with Nuxt.js and/or sharing your
code with other people.

Manual Installation
Creating a Nuxt.js project from scratch only requires one file and one directory.

We will use the terminal to create the directories and files, feel free to create them using your editor of choice.

Set up your project


Create an empty directory with the name of your project and navigate into it:

mkdir <project-name>
cd <project-name>

Replace  <project-name>  with the name of your project.

Create the  package.json  file:

touch package.json
Fill the content of your  package.json  with:

package.json
{
"name": "my-app",
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"generate": "nuxt generate",
"start": "nuxt start"
}
}

scripts  define Nuxt.js commands that will be launched with the command  npm run <command>  or  yarn <command> .

What is a package.json file?

The  package.json  is like the ID card of your project. It contains all the project dependencies and much more. If you don't know what
the  package.json  file is, we highly recommend you to have a quick read on the npm documentation.

Install Nuxt
Once the  package.json  has been created, add  nuxt  to your project via  npm  or  yarn  like so below:

Yarn npm

yarn add nuxt


This command will add  nuxt  as a dependency to your project and add it to your  package.json . The  node_modules  directory will also
be created which is where all your installed packages and dependencies are stored.

A  yarn.lock  or  package-lock.json  is also created which ensures a consistent install and compatible dependencies of your packages
installed in your project.

Create your first page


Nuxt.js transforms every  *.vue  file inside the  pages  directory as a route for the application.

Create the  pages  directory in your project:

mkdir pages

Then, create an  index.vue  file in the  pages  directory:

touch pages/index.vue

It is important that this page is called  index.vue  as this will be the default home page Nuxt shows when the application opens.

Open the  index.vue  file in your editor and add the following content:

pages/index.vue
<template>
<h1>Hello world!</h1>
</template>
Start the project
Run your project by typing one of the following commands below in your terminal:

Yarn npm

yarn dev

We use the dev command when running our application in development mode.

The application is now running on http://localhost:3000.

Open it in your browser by clicking the link in your terminal and you should see the text "Hello World" we copied in the previous
step.

When launching Nuxt.js in development mode, it will listen for file changes in most directories, so there is no need to restart the application
when e.g. adding new pages

When you run the dev command it will create .nuxt folder. This folder should be ignored from version control. You can ignore files by creating a
.gitignore file at the root level and adding .nuxt.

Bonus step
Create a page named  fun.vue  in the  pages  directory.

Add a  <template></template>  and include a heading with a funny sentence inside.


Then, go to your browser and see your new page on localhost:3000/fun.

Create a directory named  more-fun  and put an  index.vue  file inside. This will give the same result as creating a  more-fun.vue  file

  Routing

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the 
Routing

Automatic Routes
Most websites will have more than one page (i.e. a home page, about page, contact page etc.). In order to show these pages, we
need a Router. That's where  vue-router  comes in. When working with the Vue application, you have to set up a configuration file
(i.e.  router.js ) and add all your routes manually to it. Nuxt.js automatically generates the  vue-router  configuration for you, based
on your provided Vue files inside the  pages  directory. That means you never have to write a router config again! Nuxt.js also gives
you automatic code-splitting for all your routes.

In other words, all you have to do to have routing in your application is to create  .vue  files in the  pages  folder.

Learn more about Routing

Navigation
To navigate between pages of your app, you should use the NuxtLinkcomponent. This component is included with Nuxt.js and
therefore you don't have to import it as you do with other components. It is similar to the HTML  <a> tag, except that instead of
using a  href="/about"  we use  to="/about" . If you have used  vue-router  before, you can think of the  <NuxtLink>  as a replacement
for  <RouterLink>

A simple link to the  index.vue  page in your  pages  folder:

pages/index.vue
<template>
<NuxtLink to="/">Home page</NuxtLink>
</template>

For all links to pages within your site, use  <NuxtLink> . If you have links to other websites you should use the  <a>  tag. See below for
an example:

pages/index.vue
<template>
<main>
<h1>Home page</h1>
<NuxtLink to="/about">
About (internal link that belongs to the Nuxt App)
</NuxtLink>
<a href="https://nuxtjs.org">External Link to another page</a>
</main>
</template>

Learn more about the NuxtLink component.


Directory Structure
The default Nuxt.js application structure is intended to provide a great starting point for both small and large applications. You are
free to organize your application however you like and can create other directories as and when you need them.

Let's create the directories and files that do not exist in our project yet.

mkdir components assets static


touch nuxt.config.js

These are the main directories and files that we use when building a Nuxt.js application. You will find an explanation of each of them
below.

Creating directories with these names enables features in your Nuxt.js project.

Directories

The pages directory


The  pages  directory contains your application's views and routes. As you've learned in the last chapter, Nuxt.js reads all
the  .vue  files inside this directory and uses them to create the application router.

Learn more about the pages directory


The components directory
The  components  directory is where you put all your Vue.js components which are then imported into your pages.

With Nuxt.js you can create your components and auto import them into your .vue files meaning there is no need to manually
import them in the script section. Nuxt.js will scan and auto import these for you once you have components set to true.

Learn more about the components directory

The assets directory


The  assets  directory contains your uncompiled assets such as your styles, images, or fonts.

Learn more about the assets directory

The static directory


The  static  directory is directly mapped to the server root and contains files that have to keep their names
(e.g.  robots.txt ) or likely won't change (e.g. the favicon)

Learn more about the static directory

The nuxt.config.js file


The  nuxt.config.js  file is the single point of configuration for Nuxt.js. If you want to add modules or override default settings, this
is the place to apply the changes.

Learn more about the nuxt.config.js file

The package.json file


The  package.json  file contains all the dependencies and scripts for your application.

More about the project structures


There are more helpful directories and files, including content, layouts, middleware, modules, plugins and store . As they aren't
necessary for small applications, they are not covered here.

To learn about all directories in detail, feel free to read the the Directory Structure book.
Commands and Deployment
Nuxt.js comes with a set of useful commands, both for development and production purpose.

Using in package.json
You should have these commands in your  package.json :

"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
}

You can launch your commands via  yarn <command>  or  npm run <command> (example:  yarn dev  /  npm run dev ).

Development Environment
To launch Nuxt in development mode with hot module replacement on  http://localhost:3000 :

Yarn npm

yarn dev
List of Commands
You can run different commands depending on the target:

target:  server  (default value)

nuxt dev - Launch the development server.

nuxt build - Build and optimize your application with webpack for production.

nuxt start - Start the production server (after running  nuxt build ). Use it for Node.js hosting like Heroku, Digital Ocean, etc.

target:  static

nuxt dev - Launch the development server.

nuxt generate - Build the application (if needed), generate every route as a HTML file and statically export to  dist/  directory
(used for static hosting).

nuxt start - serve the  dist/  directory like your static hosting would do (Netlify, Vercel, Surge, etc), great for testing before
deploying.

Webpack Config Inspection


You can inspect the webpack config used by nuxt to build project similar to vue inspect).

nuxt webpack [query...]

Arguments:
--name : Bundle name to inspect. (client, server, modern)

--dev : Inspect webpack config for dev mode

--depth : Inspection depth. Defaults to 2 to prevent verbose output.

--no-colors : Disable ANSI colors (disabled by default when TTY is not available or when piping to a file)

Examples:

nuxt webpack

nuxt webpack devtool

nuxt webpack resolve alias

nuxt webpack module rules

nuxt webpack module rules test=.jsx

nuxt webpack module rules test=.pug oneOf use.0=raw

nuxt webpack plugins constructor.name=WebpackBar options reporter

nuxt webpack module rules loader=vue-

nuxt webpack module rules "loader=.*-loader"

Production Deployment
Nuxt.js lets you choose between Server or Static deployments.

Server Deployment
To deploy a SSR application we use  target: 'server' , where server is the default value.

Yarn npm

yarn build

Nuxt.js will create a  .nuxt  directory with everything inside ready to be deployed on your server hosting.

we recommend putting  .nuxt  in  .npmignore  or  .gitignore .

Once your application is built you can use the  start  command to see a production version of your application.

Yarn npm

yarn start

Static Deployment (Pre-rendered)


Nuxt.js gives you the ability to host your web application on any static hosting.

To deploy a static generated site make sure you have  target: 'static'  in your  nuxt.config.js  (for Nuxt >= 2.13):

nuxt.config.js
export default {
target: 'static'
}
Yarn npm

yarn generate

Nuxt.js will create a  dist/  directory with everything inside ready to be deployed on a static hosting service.

As of Nuxt v2.13 there is a crawler installed that will now crawl your link tags and generate your routes when using the
command  nuxt generate  based on those links.

Warning: dynamic routes are ignored by the  generate  command when using Nuxt <= v2.12: API Configuration generate

When generating your web application with  nuxt generate , the context given to asyncData and fetch will not have  req  and  res .

Fail on Error

To return a non-zero status code when a page error is encountered and let the CI/CD fail the deployment or build, you can use the  -
-fail-on-error  argument.

Yarn npm

yarn generate --fail-on-error

What's next?
Read our Deployment Guides to find examples for deployments to popular hosts.

Directory Structure Conclusion


Conclusion
Congratulations! You have now created your first Nuxt.js app and you may now consider yourself a Nuxter, but there is so much
more to learn and so much more you can do with Nuxt.js. Here are a few recommendations:

Check out the Concepts book

Working with asyncData

Choosing between different Rendering modes

Did you like Nuxt.js so far? Don't forget to star our project on GitHub

Commands and Deployment Upgrading


Upgrading
Upgrading Nuxt.js is quick, but more involved than updating your package.json

If you are upgrading to Nuxt v2.14 and want to use static hosting then you will need to add target:static to your nuxt.config.js file in
order for the generate command to work properly.

nuxt.config.js
export default {
target: 'static'
}

Getting Started
. Check the release notes for the version you wish to upgrade to see if there are any additional instructions for that particular
release.

. Update the version specified for the  nuxt  package in your  package.json  file.

After this step instructions vary depending upon whether you are using Yarn or npm. Yarn is the preferred package manager for
working with Nuxt as it is the development tool which tests have been written against.

Yarn
. remove  yarn.lock  file

. remove  node_modules  directory

. Run the  yarn  command


. After installation has completed and you have run your tests consider upgrading other dependencies as well. The  yarn
outdated  command can be used.

npm
. remove  package-lock.json  file

. remove  node_modules  directory

. Run the  npm install  command

. After installation has completed and you have run your tests consider upgrading other dependencies as well. The  npm
outdated  command can be used.

Conclusion  

Caught a mistake or want to contribute to the documentation? Edit this pag


Views
The Views section describes all you need to know to configure data and views for a specific route in your Nuxt.js Application. Views
consist of an app template, a layout, and the actual page. In addition, you can define custom meta tags for the head section of each
page which are important for SEO (Search Engine Optimization).

Composition of a View in Nuxt.js

Pages
Every Page component is a Vue component but Nuxt.js adds special attributes and functions to make the development of your
application as easy as possible.

pages/index.vue
<template>
<h1 class="red">Hello World</h1>
</template>

<script>
export default {
head() {
// Set Meta Tags for this Page
}
// ...
}
</script>

<style>
.red {
color: red;
}
</style>

Properties of a page component


There are many properties of the page component such as the head property in the example above.

See the Directory Structure book to learn more about all the properties can use on your page
Layouts
Layouts are a great help when you want to change the look and feel of your Nuxt.js app. For example you want to include a sidebar
or have distinct layouts for mobile and desktop.

Default Layout
You can define a default layout by adding a  default.vue  file inside the layouts directory. This will be used for all pages that don't
have a layout specified. The only thing you need to include in the layout is the  <Nuxt />  component which renders the page
component.

layouts/default.vue
<template>
<Nuxt />
</template>

Learn more about the Nuxt component in the components chapter

Custom Layout
You can create custom layouts by adding a  .vue  file to the layouts directory. In order to use the custom layout you need to set
the  layout  property in the page component where you want to use that layout. The value will be the name of the custom layout
that you have created.

To create a blog layout add a  blog.vue  file to your layouts directory  layouts/blog.vue :
layouts/blog.vue
<template>
<div>
<div>My blog navigation bar here</div>
<Nuxt />
</div>
</template>

Make sure to add the  <Nuxt/>  component when creating a layout to actually include the page component.

We then use the layout property with the value of 'blog' in the page where we want that layout to be used.

pages/posts.vue
<template>
<!-- Your template -->
</template>
<script>
export default {
layout: 'blog'
// page component definitions
}
</script>

If you don't add a layout property to your page, e.g.  layout: 'blog' , then the  default.vue  layout will be used.

Error Page
The error page is a page component which is always displayed when an error occurs (that does not happen while server-side
rendering).

Although this file is placed in the  layouts  folder, it should be treated as a page.

As mentioned above, this layout is special, since you should not include the  <Nuxt/>   component inside its template. You must see
this layout as a component displayed when an error occurs ( 404 ,  500 , etc.). Similar to other page components, you can set a custom
layout for the error page as well in the usual way.

You can customize the error page by adding a  layouts/error.vue  file:

layouts/error.vue
<template>
<div>
<h1 v-if="error.statusCode === 404">Page not found</h1>
<h1 v-else>An error occurred</h1>
<NuxtLink to="/">Home page</NuxtLink>
</div>
</template>

<script>
export default {
props: ['error'],
layout: 'error' // you can set a custom layout for the error page
}
</script>

Document: App.html
The app template is used to create the actual HTML frame of your document for your Nuxt.js application which injects the content as
well as variables for the head and body. This file is created automatically for you and in general rarely needs to be modified. You can
customize the HTML app template used by Nuxt.js to include scripts or conditional CSS classes by creating an  app.html  file in the
source directory of your project which by default is the root directory.

The default template used by Nuxt.js is:

app.html
<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
<head {{ HEAD_ATTRS }}>
{{ HEAD }}
</head>
<body {{ BODY_ATTRS }}>
{{ APP }}
</body>
</html>

One use case of using a custom app template is to add conditional CSS classes for IE:

app.html
<!DOCTYPE html>
<!--[if IE 9]><html class="lt-ie9 ie9" {{ HTML_ATTRS }}><![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--><html {{ HTML_ATTRS }}><!--<![endif]-->
<head {{ HEAD_ATTRS }}>
{{ HEAD }}
</head>
<body {{ BODY_ATTRS }}>
{{ APP }}
</body>
</html>
While you can add JavaScript and CSS files in the  app.html , it is recommended to use the  nuxt.config.js  for these tasks instead!
Context and Helpers
The  context  object is available in specific Nuxt functions like asyncData, plugins, middleware and nuxtServerInit. It
provides additional and often optional information about the current request to the application.
First and foremost, the context is used to provide access to other parts of the Nuxt.js application, e.g. the Vuex store or the
underlying  connect  instance. Thus, we have the  req  and  res  objects in the context available on the server side and  store  always
available. But with time, the context was extended with many other helpful variables and shortcuts. Now we have access to HMR
functionalities in  development  mode, the current  route , page  params  and  query , as well as the option to access environment
variables through the context. Furthermore, module functions and helpers can be exposed through the context to be available on
both - the client and the server side.

All context keys that are present by default

function (context) { // Could be asyncData, nuxtServerInit, ...


// Always available
const {
app,
store,
route,
params,
query,
env,
isDev,
isHMR,
redirect,
error,
$config
} = context

// Only available on the Server-side


if (process.server) {
const { req, res, beforeNuxtRender } = context
}
// Only available on the Client-side
if (process.client) {
const { from, nuxtState } = context
}
}

The context we refer to here is not to be confused with the  context  object available in Vuex Actions or the one available in
the  build.extend  function in your  nuxt.config.js . These are all not related to each other!

Learn more about the different context keys in our Internals Glossary

Using page parameters for your API query


The context directly exposes possible dynamic parameters of the route via  context.params . In the following example, we call an API
via the  nuxt/http module using a dynamic page parameter as part of the URL. Modules, like the nuxt/http module, can expose own
functions which are then available through the context.app object.

Also, we wrap the API call in a  try/catch  statement to handle potential errors. With the  context.error  function, we can directly
show Nuxt's error page and pass in the occurred error.

pages/posts/_id.vue
export default {
async asyncData(context) {
const id = context.params.id
try {
// Using the nuxtjs/http module here exposed via context.app
const post = await context.app.$http.$get(
`https://api.nuxtjs.dev/posts/${id}`
)
return { post }
} catch (e) {
context.error(e) // Show the nuxt error page with the thrown error
}
}
}

With ES6 you can use this syntax to destructure your context object. You can pass in the objects you want to have access to and then
you can use them in the code without using the word context.

pages/posts/_id.vue
export default {
async asyncData({ params, $http, error }) {
const id = params.id

try {
// Using the nuxtjs/http module here exposed via context.app
const post = await $http.$get(`https://api.nuxtjs.dev/posts/${id}`)
return { post }
} catch (e) {
error(e) // Show the nuxt error page with the thrown error
}
}
}

Want to use query parameters instead? You then use context.query.id then.

Redirecting users & accessing the store


Accessing the Vuex store (when you have it set up through the  store  directory) is also possible through the context. It provides
a  store  object which can be treated as  this.$store  in Vue components. In addition, we use the  redirect method, an exposed
helper through the context, to redirect the user in case the  authenticated  state is falsy.

export default {
middleware({ store, redirect }) {
// retrieving keys via object destructuring
const isAuthenticated = store.state.authenticated
if (!isAuthenticated) {
return redirect('/login')
}
}
}

Check out the Internals Glossary book for more examples of the redirect method

Helpers
Besides the shortcuts in the context, there are also other tiny helpers present in your Nuxt.js application.

$nuxt : The Nuxt.js helper


$nuxt  is a helper designed to improve the user experience and to be an escape hatch in some situations. It is accessible
via  this.$nuxt  in Vue components and via  window.$nuxt  otherwise on the client side.
Connection checker
The  $nuxt  helper provides a quick way to find out whether the internet connection of a user is present or not: It exposes the
boolean values  isOffline and  isOnline . We can use these to show a message as soon as the user is offline (for example).

layouts/default.vue
<template>
<div>
<div v-if="$nuxt.isOffline">You are offline</div>
<Nuxt />
</div>
</template>

Accessing the root instance


Besides providing DX/UX features, the  $nuxt  helper also provides a shortcut to the root instance of your application from every
other component. But that's not everything — you can also access the  $nuxt  helper through  window.$nuxt  which can be used as an
escape hatch to gain access to module methods like  $axios from outside your Vue components. This should be used wisely and only
as last resort.

Refreshing page data


When you want to refresh the current page for the user, you don't want to fully reload the page because you might hit the server
again and at least re-initialize the whole Nuxt.js application. Instead, you often only want to refresh the data, provided
by  asyncData  or  fetch .

You can do so, by using  this.$nuxt.refresh() !


<template>
<div>
<div>{{ content }}</div>
<button @click="refresh">Refresh</button>
</div>
</template>

<script>
export default {
asyncData() {
return { content: 'Created at: ' + new Date() }
},
methods: {
refresh() {
this.$nuxt.refresh()
}
}
}
</script>

Controlling the loading bar

With  $nuxt , you can also control Nuxt's loading bar programmatically via  this.$nuxt.$loading .

export default {
mounted() {
this.$nextTick(() => {
this.$nuxt.$loading.start()
setTimeout(() => this.$nuxt.$loading.finish(), 500)
})
}
}

Read more in the corresponding loading feature chapter

onNuxtReady helper
If you want to run some scripts after your Nuxt.js application has been loaded and is ready, you can use
the  window.onNuxtReady  function. This can be useful when you want to execute a function on the client-side without increasing the
time to interactive of your site.

window.onNuxtReady(() => {
console.log('Nuxt.js is ready and mounted')
})

Process helpers
Nuxt.js injects three boolean values ( client ,  server , and  static ) into the global  process  object which will help you to determine
whether your app was rendered on the server or fully on the client, as well as checking for static site generation. These helpers are
available across your application and are commonly used in  asyncData  userland code.

pages/about.vue
<template>
<h1>I am rendered on the {{ renderedOn }} side</h1>
</template>
<script>
export default {
asyncData() {
return { renderedOn: process.client ? 'client' : 'server' }
}
}
</script>

In the example,  renderedOn  will evaluate to  'server'  when using server-side rendering and a user accesses the page directly. When
the user would navigate to the page from another part of the application, e.g. by click on a  <NuxtLink> , it will evaluate to client.

Views Server Side Rendering


Server Side Rendering
Server-side rendering (SSR), is the ability of an application to contribute by displaying the web-page on the server instead of
rendering it in the browser. Server-side sends a fully rendered page to the client; the client's JavaScript bundle takes over which then
allows the Vue.js app to hydrate.

Node.js server required


A JavaScript environment is required to render your web page.

A Node.js server needs to be configured to execute your Vue.js application.

Extend and control the server


You can extend the server with serverMiddleware and control routes with middleware.

server-middleware/logger.js
export default function (req, res, next) {
console.log(req.url)
next()
}

nuxt.config.js
export default {
serverMiddleware: ['~/server-middleware/logger']

}
If your server middleware consists of a list of functions mapped to paths:

Server vs Browser environments


Because you are in a Node.js environment you have access to Node.js objects such as  req  and  res . You do not have access to
the  window  or  document  objects as they belong to the browser environment. You can however use  window  or  document  by using
the  beforeMount  or  mounted  hooks.

beforeMount () {
window.alert('hello');
}
mounted () {
window.alert('hello');
}

Server-side rendering steps with Nuxt.js

Step 1: Browser to Server


When a browser sends the initial request, it will hit the Node.js internal server. Nuxt.js will generate the HTML and send it back to the
browser with results from executed functions, e.g.  asyncData ,  nuxtServerInit  or  fetch . Hooks functions are executed as well.

Step 2: Server to Browser


The browser receives the rendered page from the server with the generated HTML. The content is displayed and the Vue.js hydration
kicks in, making it reactive. After this process, the page is interactive.

Step 3: Browser to Browser


Navigating between pages with  <NuxtLink>  is done on the client side so you don't hit the server again unless you hard refresh the
browser.

Caveats

window or document undefined


This is due to the server-side rendering. If you need to specify that you want to import a resource only on the client-side, you need
to use the  process.client variable.

For example, in your  .vue  file:

if (process.client) {
require('external_library')
}

iOS and phone numbers


Some mobile Safari versions will automatically transform phone numbers into links. This will trigger a  NodeMismatch  warning as the
SSR content doesn't match the website content anymore. This can make your app unusable on these Safari versions.
If you include telephone numbers in your Nuxt page, you have two options.

Use a meta tag to stop the transformation


<meta name="format-detection" content="telephone=no" />

Wrap your phone numbers in links


<!-- Example phone number: +7 (982) 536-50-77 -->

<template>
<a href="tel: +7 (982) 536-50-77">+7 (982) 536-50-77</a>
</template>

Context and Helpers Static Site Generation

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


Static Site Generation
With static site generation you can render your application during the build phase and deploy it to any static hosting services such
as Netlify, GitHub pages, Vercel etc. This means that no server is needed in order to deploy your application.

Generating your site


When deploying your site in with target:static all your  .vue  pages will be generated into HTML and JavaScript files. All calls to APIs
will be made and cached in a folder called static inside your generated content so that no calls to your API need to be made on
client side navigation.

Step 1: Browser to CDN


When a browser sends the initial request, it will hit the CDN.

Step 2: CDN to Browser


The CDN will send the already generated HTML, JavaScript and static assets back to the browser. The content is displayed and the
Vue.js hydration kicks in, making it reactive. After this process, the page is interactive.

Step 3: Browser to Browser


Navigating between pages with  <NuxtLink>  is done on the client side so you don't hit the CDN again and all API calls will be loaded
from the already cached static folder even if you hard refresh the browser.
SPA Fallback
Pages that have been excluded from generation, by using the  generate.exclude property will fallback to being a single page
application. These pages will therefore not exist in the CDN and will be rendered on client side in the browser once the user
navigates to that page.

To learn more about the generate property

Updating your content


In order to get new content to your site from your API you will need to regenerate your site again. With most static sites hosting
providers you can do this by pushing your changes to your master branch via the git command or via a pull request.

Preview Mode
The Preview mode will call your API or your CMS so you can see the changes live before deploying. See the preview mode on how to
enable this feature.
Nuxt Lifecycle
No matter which tool you use, you will always feel more confident when you understand how the tool works under the hood. The
same applies to Nuxt.js. The goal of this chapter is to give you a high-level overview of the different parts of the framework, their
order of execution and how they work together.
The Nuxt.js lifecycle describes what happens after the build phase, where your application is bundled, chunked and minified. What
happens after this phase depends on whether you have server-side rendering enabled or not. If you have, it furthermore depends on
the type of server-side rendering you have chosen:

Dynamic SSR ( nuxt start )

or Static Site Generation ( nuxt generate ).

Lifecycle

Server
For SSR, these steps will be executed for every initial request to your app

The server starts ( nuxt start )

When using static site generation, the server steps are only executed on build time, but once for every page that will be generated

The generation process starts ( nuxt generate )

Nuxt hooks

serverMiddleware

Server-side Nuxt plugins

in order as defined in nuxt.config.js


nuxtServerInit

Vuex action that is called only on server-side to pre-populate the store

First argument is the Vuex context, second argument is the Nuxt.js context

Dispatch other actions from here → only "entry point" for subsequent store actions on server-side

can only be defined in  store/index.js

Middleware

Global middleware

Layout middleware

Route middleware

asyncData

beforeCreate (Vue lifecycle method)

created (Vue lifecycle method)

The new fetch (top to bottom, siblings = parallel)

Serialization of state ( render:routeContext  Nuxt.js hook)

the HTML rendering happens ( render:route  Nuxt.js hook)


render:routeDone  hook when HTML has been sent to the browser

generate:before  Nuxt.js hook

HTML files are generated

Full static generation

e.g. static payloads are extracted

generate:page  (HTML editable)

generate:routeCreated  (Route generated)

generate:done  when all HTML files have been generated

Client
This part of the lifecycle is fully executed in the browser, no matter which Nuxt.js mode you've chosen.

Receives the HTML

Loading assets (e.g. JavaScript)

Vue Hydration

Middleware

Global middleware
Layout middleware

Route middleware

client-side Nuxt.js plugin

in order as defined in nuxt.config.js

asyncData (blocking)

beforeCreate (Vue lifecycle method)

created (Vue lifecycle method)

The new fetch (top to bottom, siblings = parallel) (non-blocking)

beforeMount (Vue lifecycle method)

mounted (Vue lifecycle method)

Navigate using the NuxtLink component


Same as for the client part, everything is happening in the browser but only when navigating via  <NuxtLink> . Furthermore, no page
content is displayed until all blocking tasks are fulfilled.

Check out the component chapter to see more info on  <NuxtLink>

middleware (blocking)

Global middleware

Layout middleware
Route middleware

asyncData (blocking)

asyncData (blocking) [or full static payload loading]

beforeCreate & created (Vue lifecycle methods)

fetch (non-blocking)

beforeMount & mounted


Rendering

Server Side Rendered Sites and Static Sites


Server-side rendered sites are rendered on the server each time the user requests a page, therefore a server is needed to be able to
serve the page on each request.

Static sites are very similar to server-side rendered applications with the main difference being that static sites are rendered at build
time, therefore no server is needed. Navigating from one page to another is then on the client-side.

See deployment targets for more info on static and server hosting.

nuxt.config.js
export default {
ssr: true // default value
}

You do not need to add  ssr: true  to your nuxt config in order to enable server-side-rendering as it is enabled by default.

Client Side Rendering Only


With client side rendering only there is no server-side rendering. Client side rendering means rendering the content in the browser
using JavaScript. Instead of getting all of the content from the HTML we just get a basic HTML document with a JavaScript file that
will then render the rest of the site using the browser. For client side rendering set ssr to  false .
nuxt.config.js
export default {
ssr: false
}
Deployment Targets

Static Hosting
Nuxt.js also works as a static site generator. Statically render your Nuxt.js application and get all of the benefits of a universal app
without a server. The  nuxt generate  command will generate a static version of your website. It will generate HTML for every one of
your routes and put it inside of its own file in the  dist/  directory. This improves performance as well as SEO and better offline
support.

Dynamic routes are also generated thanks to the Nuxt Crawler

For static sites the target of  static  needs to be added to your  nuxt.config  file.

nuxt.config.js
export default {
target: 'static' // default is 'server'
}

Running nuxt dev with the static target will improve the developer experience:

Remove  req  &  res  from  context

Fallback to client-side rendering on 404, errors and redirects see SPA fallback

$route.query  will always be equal to  {}  on server-side rendering

process.static  is true


We are also exposing  process.target  for module authors to add logic depending on the user target.

Server Hosting
Server Hosting is hosting that requires a server and is intended for SSR applications or applications that are using serverMiddleware.
Server-side rendering otherwise known as SSR means that your page is rendered on the server when it is requested by the user.
When the user opens your page in a browser the browser sends a request to the server requesting that page. The page is rendered
on the server and sent back to the browser with all its content.

For server hosting the target of server is used, which is the default value. With SSR you use the  build  command to build your
application.

nuxt.config.js
export default {
target: 'server'
}

Rendering File System Routing


File System Routing
Nuxt.js automatically generates the vue-router configuration based on your file tree of Vue files inside the pages directory. When
you create a .vue file in your pages directory you will have basic routing working with no extra configuration needed.

Sometimes you might need to create dynamic routes or nested routes or you might need to further configure the router property.
This chapter will go through everything you need to know in order to get the best out of your router.

Nuxt.js gives you automatic code splitting for your routes, no configuration is needed

Use the NuxtLink component to navigate between pages

<template>
<NuxtLink to="/">Home page</NuxtLink>
</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
Sometimes it is not possible to know the name of the route such as when we make a call to an API to get a list of users or blog posts.
We call these dynamic routes. To create a dynamic route you need to add an underscore ( _ ) before the  .vue  file name or before the
name of the directory. You can name the file or directory anything you want but you must prefix it with an underscore.

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.

As of Nuxt >= v2.13 there is a crawler installed that will now crawl your link tags and generate your dynamic routes based on those links.
However if you have pages that are not linked to such as a secret page, then you will need to manually generate those dynamic routes.

Generate dynamic routes for static sites

Locally Accessing Route Params


You can access the current route parameters within your local page or component by referencing  this.$route.params.
{parameterName} . For example, if you had a dynamic users page ( users/_id.vue ) and wanted to access the  id  parameter to load the
user or process information, you could access the variable like this:  this.$route.params.id .
Nested Routes
Nuxt.js lets you create nested routes 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 contains your children views.

Don't forget to include the NuxtChild component 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 is not a common scenario, but it is possible with Nuxt.js to have 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 route.

This file tree:

pages/
--| people/
-----| _id.vue
-----| index.vue
--| _.vue
--| index.vue

Will handle requests like this:

/ -> index.vue
/people -> people/index.vue
/people/123 -> people/_id.vue
/about -> _.vue
/about/careers -> _.vue
/about/careers/chicago -> _.vue

Handling 404 pages is now up to the logic of the  _.vue  page.

Extending the router


There are multiple ways to extend the routing with Nuxt:

router-extras-module to customize the route parameters in the page

component@nuxtjs/router to overwrite the Nuxt router and write your own  router.js  file

Use the router.extendRoutes property in your  nuxt.config.js

The router Property


The router property lets you customize the Nuxt.js router (vue-router).

nuxt.config.js
export default {
router: {
// customize the Nuxt.js router
}
}

Base:
The base URL of the app. For example, if the entire single page application is served under  /app/ , then base should use the
value  '/app/' .

Router Base Property

extendRoutes
You may want to extend the routes created by Nuxt.js. You can do so via the  extendRoutes  option.

Example of adding a custom route:

nuxt.config.js
export default {
router: {
extendRoutes(routes, resolve) {
routes.push({
name: 'custom',
path: '*',
component: resolve(__dirname, 'pages/404.vue')
})
}
}
}

If you want to sort your routes, you can use the   sortRoutes(routes)   function from  @nuxt/utils :

nuxt.config.js
import { sortRoutes } from '@nuxt/utils'
export default {
router: {
extendRoutes(routes, resolve) {
// Add some routes here ...

// and then sort them


sortRoutes(routes)
}
}
}

The schema of the route should respect the vue-router schema.

When adding routes that use Named Views, don't forget to add the corresponding  chunkNames  of named  components .

nuxt.config.js
export default {
router: {
extendRoutes(routes, resolve) {
routes.push({
path: '/users/:id',
components: {
default: resolve(__dirname, 'pages/users'), // or routes[index].component
modal: resolve(__dirname, 'components/modal.vue')
},
chunkNames: {
modal: 'components/modal'
}
})
}
}
}

extendRoutes Property

fallback
Controls whether the router should fallback to hash mode when the browser does not support history.pushState but mode is set to
history.

fallback Property

mode
Configure the router mode, it is not recommended to change it due to server-side rendering.

mode Property

parseQuery / stringifyQuery
Provide custom query string parse / stringify functions.

parseQuery / stringifyQuery Property


routeNameSplitter
You may want to change the separator between route names that Nuxt.js uses. You can do so via the  routeNameSplitter  option in
your configuration file. Imagine we have the page file  pages/posts/_id.vue . Nuxt.js will generate the route name programmatically,
in this case  posts-id . Changing the  routeNameSplitter  config to  /  the name will therefore change to  posts/id .

nuxt.config.js
export default {
router: {
routeNameSplitter: '/'
}
}

scrollBehavior
The  scrollBehavior  option lets you define a custom behavior for the scroll position between the routes. This method is called every
time a page is rendered.

To learn more about it, see vue-router scrollBehavior documentation.

Available since:v2.9.0:

In Nuxt.js you can use a file to overwrite the router scrollBehavior. This file should be placed in a folder called app.

~/app/router.scrollBehavior.js .

Example of forcing the scroll position to the top for every route:
app/router.scrollBehavior.js
export default function (to, from, savedPosition) {
return { x: 0, y: 0 }
}

Nuxt.js default  router.scrollBehavior.js  file.

scrollBehavior Property

trailingSlash
Available since: v2.10

If this option is set to true, trailing slashes will be appended to every route. If set to false, they'll be removed.

nuxt.config.js
export default {
router: {
trailingSlash: true
}
}

This option should not be set without preparation and has to be tested thoroughly. When setting  router.trailingSlash  to something else
other than  undefined (which is the default value), the opposite route will stop working. Thus 301 redirects should be in place and your internal
linking has to be adapted correctly. If you set  trailingSlash  to  true , then only  example.com/abc/  will work but not  example.com/abc .
On false, it's vice-versa.
trailingSlash Property

Deployment Targets Data Fetching


Data Fetching
Nuxt.js supports traditional Vue patterns for loading data in your client-side app, such as fetching data in a
component's  mounted()  hook. Universal apps, however, need to use Nuxt.js-specific hooks to be able to render data during server-
side rendering. This allows your page to render with all of its required data present.

Nuxt has two hooks for asynchronous data loading:

The  fetch  hook (Nuxt 2.12+). This hook can be placed on any component, and provides shortcuts for rendering loading states
(during client-side rendering) and errors.

The  asyncData  hook. This hook can only be placed on page components. Unlike  fetch , this hook does not display a loading
placeholder during client-side rendering: instead, this hook blocks route navigation until it is resolved, displaying a page error if it
fails.

In versions of Nuxt before 2.12, the  fetch  hook worked much like  asyncData does today. This functionality is still supported today for
backwards-compatibility: if a  context  argument is accepted in your  fetch() , it will be considered a "legacy" fetch hook. This functionality is
deprecated, and should be replaced with either  asyncData(context)  or an anonymous middleware using  middleware(context) .

These hooks can be used with any data fetching library you choose. We recommend using @nuxt/http or @nuxt/axios for making
requests to HTTP APIs. More information about these libraries, such as guides for configuring authentication headers, can be found
in their respective documentation.

If you define  fetch  or  asyncData  inside a mixin and also have it defined in a component/page, the mixin function will be overwritten instead
of called.

The fetch hook


This hook is only available for Nuxt 2.12 and later.

fetch  is a hook called during server-side rendering after the component instance is created, and on the client when navigating. The
fetch hook should return a promise (whether explicitly, or implicitly using  async/await ) that will be resolved:

On the server before the initial page is rendered

On the client some time after the component is mounted

It exposes  $fetchState  at the component level with the following properties:

pending  is a  Boolean  that allows you to display a placeholder when  fetch  is being called on client-side.

error  is either  null  or an  Error  thrown by the fetch hook

timestamp  is a timestamp of the last fetch, useful for caching with  keep-alive

For static hosting, the fetch hook is only called during page generation, and the result is then cached for use on the client. To avoid cache
conflicts, it may be necessary to specify a name for your component, or alternatively provide a unique fetchKey implementation.

In addition to fetch being called by Nuxt, you can manually call fetch in your component (to e.g. reload its async data) by
calling  this.$fetch() .

components/NuxtMountains.vue
<template>
<p v-if="$fetchState.pending">Fetching mountains...</p>
<p v-else-if="$fetchState.error">An error occurred :(</p>
<div v-else>
<h1>Nuxt Mountains</h1>
<ul>
<li v-for="mountain of mountains">{{ mountain.title }}</li>
</ul>
<button @click="$fetch">Refresh</button>
</div>
</template>

<script>
export default {
data() {
return {
mountains: []
}
},
async fetch() {
this.mountains = await fetch(
'https://api.nuxtjs.dev/mountains'
).then(res => res.json())
}
}
</script>

You can access the Nuxt context within the fetch hook using  this.$nuxt.context .

Options
fetchOnServer :  Boolean  or  Function  (default:  true ), call  fetch()  when server-rendering the page

fetchDelay :  Integer  (default:  200 ), set the minimum executing time in milliseconds (to avoid quick flashes)
When  fetchOnServer  is falsy ( false  or returns  false ),  fetch  will be called only on client-side and  $fetchState.pending  will
return  true  when server-rendering the component.

export default {
data() {
return {
posts: []
}
},
async fetch() {
this.posts = await fetch('https://api.nuxtjs.dev/posts').then(res =>
res.json()
)
},
// call fetch only on client-side
fetchOnServer: false
}

Listening to query string changes


The  fetch  hook is not called on query string changes by default. To watch for query changes you can add a watcher
on  $route.query  and call  $fetch :

export default {
watch: {
'$route.query': '$fetch'
},
async fetch() {
// Called also on query changes
}
}

Caching
You can use  keep-alive  directive in  <nuxt/>  and  <nuxt-child/>  component to save  fetch  calls on pages you already visited:

layouts/default.vue
<template>
<nuxt keep-alive />
</template>

You can also specify the props passed to  <keep-alive>  by passing a prop  keep-alive-props  to the  <nuxt>   component.

layouts/default.vue
<nuxt keep-alive :keep-alive-props="{ max: 10 }" />

Keeps only 10 page components in memory.

Using  activated  hook


Nuxt will directly fill   this.$fetchState.timestamp   (timestamp) of the last  fetch  call (ssr included). You can use this property
combined with  activated  hook to add a 30 seconds cache to  fetch :

pages/posts/_id.vue
<template> ... </template>

<script>
export default {
data() {
return {
posts: []
}
},
activated() {
// Call fetch again if last fetch more than 30 sec ago
if (this.$fetchState.timestamp <= Date.now() - 30000) {
this.$fetch()
}
},
async fetch() {
this.posts = await fetch('https://api.nuxtjs.dev/posts').then(res =>
res.json()
)
}
}
</script>

The navigation to the same page will not call  fetch  if last  fetch  call was before 30 sec ago.

Async Data
asyncData  is only available for pages and you don't have access to  this  inside the hook.

asyncData  is another hook for universal data fetching. Unlike  fetch , which requires you to set properties on the component
instance (or dispatch Vuex actions) to save your async state,  asyncData  simply merges its return value into your component's local
state. Here's an example using the @nuxt/http library:

pages/posts/_id.vue
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.description }}</p>
</div>
</template>

<script>
export default {
async asyncData({ params, $http }) {
const post = await $http.$get(`https://api.nuxtjs.dev/posts/${params.id}`)
return { post }
}
}
</script>

Unlike  fetch , the promise returned by the  asyncData  hook is resolved during route transition. This means that no "loading
placeholder" is visible during client-side transitions (although the loading bar can be used to indicate a loading state to the user).
Nuxt will instead wait for the  asyncData  hook to be finished before navigating to the next page or display the error page).

This hook can only be used for page-level components. Unlike  fetch ,  asyncData cannot access the component instance ( this ).
Instead, it receives the context as its argument. You can use it to fetch some data and Nuxt.js will automatically shallow merge the
returned object with the component data.

In the upcoming examples, we are using @nuxt/http which we recommend for fetching data from an API.

Async data in components?


Because components do not have an  asyncData  method, you cannot directly fetch async data server side within a component. In
order to get around this limitation you have three basic options:

. Use the new  fetch  hook that is available in Nuxt 2.12 and later versions.

. Make the API call in the  mounted  hook and set data properties when loaded. Downside: Won't work for server side rendering.

. Make the API call in the  asyncData  method of the page component and pass the data as props to the sub components. Server
rendering will work fine. Downside: the  asyncData  of the page might be less readable because it's loading the data for other
components.

Listening to query changes


The  asyncData  method is not called on query string changes by default. If you want to change this behavior, for example when
building a pagination component, you can set up parameters that should be listened to with the  watchQuery  property of your page
component.

Learn more about the watchQuery property and see the list of available keys in context.

File System Routing Meta Tags and SEO


Meta Tags and SEO
Nuxt.js gives you 3 different ways to add meta data to your application:

. Globally using the nuxt.config.js

. Locally using the head as an object

. Locally using the head as a function so that you have access to data and computed properties.

Global Settings
Nuxt.js lets you define all default  <meta>  tags for your application inside the nuxt.config.js file using the head property. This is very
useful for adding a default title and description tag for SEO purposes or for setting the viewport or adding the favicon.

nuxt.config.js
export default {
head: {
title: 'my website title',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{
hid: 'description',
name: 'description',
content: 'my website description'
}
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
}
}

This will give you the same title and description on every page

Local Settings
You can also add titles and meta for each page using the  head  method inside your script tag on every page.

pages/index.vue
<script>
export default {
head: {
title: 'Home page',
meta: [
{
hid: 'description',
name: 'description',
content: 'Home page description'
}
],
}
}
</script>

Use  head  as an object to set a title and description only for the home page
pages/index.vue
<template>
<h1>{{ title }}</h1>
</template>
<script>
export default {
data() {
return {
title: 'Home page'
}
},
head() {
return {
title: this.title,
meta: [
{
hid: 'description',
name: 'description',
content: 'Home page description'
}
]
}
}
}
</script>

Use  head  as a function to set a title and description only for the home page. By using a function you have access to data and computed
properties
Nuxt.js uses vue-meta to update the document head and meta attributes of your application.

To avoid any duplication when used in child components, please give a unique identifier with the  hid  key to the meta description. This
way  vue-meta  will know that it has to overwrite the default tag.

Learn more about the options available for  head , in the vue-meta documentation.

External Resources
You can include external resources such as scripts and fonts by adding them globally to the  nuxt.config.js  or locally in
the  head  object or function.

You can also pass each resource an optional  body: true  to include the resource before the closing  </body>  tag.

Global Settings
nuxt.config.js
export default {
head: {
script: [
{
src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'
}
],
link: [
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css?family=Roboto&display=swap'
}
]
}
}

Local Settings

pages/index.vue
<template>
<h1>About page with jQuery and Roboto font</h1>
</template>

<script>
export default {
head() {
return {
script: [
{
src:
'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'
}
],
link: [
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css?family=Roboto&display=swap'
}
]
}
}
}
</script>

<style scoped>
h1 {
font-family: Roboto, sans-serif;
}
</style>

Resource Hints
Adds prefetch and preload links for faster initial page load time.

You may want to only disable this option if you have many pages and routes.

Resource Hints

Data Fetching Configuration


Configuration
By default, Nuxt.js is configured to cover most use cases. This default configuration can be overwritten with the nuxt.config.js file.

The css Property


Nuxt.js lets you define the CSS files/modules/libraries you want to set globally (included in every page).

In case you want to use  sass  make sure that you have installed the  sass  and  sass-loader  packages.

In  nuxt.config.js , add the CSS resources:

nuxt.config.js
export default {
css: [
// Load a Node.js module directly (here it's a Sass file)
'bulma',
// CSS file in the project
'~/assets/css/main.css',
// SCSS file in the project
'~/assets/css/main.scss'
]
}

Nuxt.js will automatically guess the file type by its extension and use the appropriate pre-processor loader for webpack. You will still need to
install the required loader if you need to use them.
Style Extensions
You can omit the file extension for CSS/SCSS/Postcss/Less/Stylus/... files listed in the css array in your nuxt config file.

nuxt.config.js
export default {
css: ['~/assets/css/main', '~/assets/css/animations']
}

If you have two files with the same name, e.g.  main.scss  and  main.css , and don't specify an extension in the css array entry, e.g.  css:
['~/assets/css/main'] , then only one file will be loaded depending on the order of  styleExtensions . In this case only the  css  file will be
loaded and the  scss file will be ignored because  css  comes first in the default  styleExtension  array.

Default order:  ['css', 'pcss', 'postcss', 'styl', 'stylus', 'scss', 'sass', 'less']

Pre-processors
Thanks to Vue Loader, you can use any kind of pre-processor for your   <template>  or  <style> : use the  lang  attribute.

Example of our  pages/index.vue  using Pug and Sass:

pages/index.vue
<template lang="pug"> h1.red Hello {{ name }}! </template>

<style lang="scss">
.red {
color: red;
}
</style>
To use these pre-processors, we need to install their webpack loaders:

yarn add -D pug pug-plain-loader


yarn add -D sass sass-loader@10 fibers

Synchronous compilation with  sass  (2x speed increase) is enabled automaticallywhen  fibers  is installed.

External Resources

Global Settings
You can include your external resources in the head object or function. As described in the head API docs, the following examples
shows the use of  head  as an object and as a function. If you want to use values from your Vue component like computed properties
or data, you can use the  head()  function, returning the final head object. You can also pass each resource an optional  body: true  to
include the resource before the closing  </body>  tag.

Include your resources in  nuxt.config.js  (here in the head object):

export default {
head: {
script: [
{
src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'
}
],
link: [
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css?family=Roboto&display=swap'
}
]
}
}

Local Settings
Include your resources in your  .vue  file inside the  pages/  directory (here in the head function):

<template>
<h1>About page with jQuery and Roboto font</h1>
</template>

<script>
export default {
head() {
return {
script: [
{
src:
'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'
}
],
link: [
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css?family=Roboto&display=swap'
}
]
}
}
}
</script>

<style scoped>
h1 {
font-family: Roboto, sans-serif;
}
</style>

PostCSS plugins
If present, rename or delete the  postcss.config.js  in your project directory. Then, in your  nuxt.config.js  file add the following:

export default {
build: {
postcss: {
// Add plugin names as key and arguments as value
// Install them before as dependencies with npm or yarn
plugins: {
// Disable a plugin by passing false as value
'postcss-url': false,
'postcss-nested': {},
'postcss-responsive-type': {},
'postcss-hexrgba': {}
},
preset: {
// Change the postcss-preset-env settings
autoprefixer: {
grid: true
}
}
}
}
}

JSX
Nuxt.js uses @nuxt/babel-preset-app, which is based on the official @vue/babel-preset-app for babel default configuration, so you
can use JSX in your components.

You can also use JSX in the  render  method of your components:

<script>
export default {
data () {
return { name: 'World' }
},
render (h) {
return <h1 class="red">{this.name}</h1>
}
}
</script>
Aliasing  createElement  to  h  is a common convention you’ll see in the Vue ecosystem but is actually optional for JSX since
it automatically injects  const h = this.$createElement  in any method and getter (not functions or arrow functions) declared in
ES2015 syntax that has JSX so you can drop the (h) parameter.

You can learn more about how to use it in the JSX section of the Vue.js documentation.

Ignoring files

.nuxtignore
You can use a  .nuxtignore  file to let Nuxt.js ignore   layout ,  page ,  store  and  middleware   files in your project’s root directory
( rootDir ) during the build phase. The  .nuxtignore  file is subject to the same specification as   .gitignore   and   .eslintignore  files,
in which each line is a glob pattern indicating which files should be ignored.

.nuxtignore
# ignore layout foo.vue

layouts/foo.vue

# ignore layout files whose name ends with -ignore.vue

layouts/\*-ignore.vue

# ignore page bar.vue

pages/bar.vue

# ignore page inside ignore folder


pages/ignore/\*.vue

# ignore store baz.js

store/baz.js

# ignore store files match _.test._

store/ignore/_.test._

# ignore middleware files under foo folder except foo/bar.js

middleware/foo/\*.js !middleware/foo/bar.js

The ignorePrefix Property


Any file in pages/, layout/, middleware/ or store/ will be ignored during the build if its filename starts with the prefix specified
by ignorePrefix.

By default all files which start with  -  will be ignored, such as  store/-foo.js  and  pages/-bar.vue . This allows for co-locating tests,
utilities, and components with their callers without themselves being converted into routes, stores, etc.

The ignore Property


More customizable than ignorePrefix: all files matching glob patterns specified inside ignore will be ignored in building.
nuxt.config.js
export default {
ignore: 'pages/bar.vue'
}

ignoreOptions
nuxtignore  is using  node-ignore  under the hood,  ignoreOptions  can be configured as  options  of  node-ignore .

nuxt.config.js
export default {
ignoreOptions: {
ignorecase: false
}
}

Extend webpack config


You can extend nuxt's webpack configuration via the  extend  option in your  nuxt.config.js . The  extend  option of
the  build  property is a method that accepts two arguments. The first argument is the webpack  config  object exported from nuxt's
webpack config. The second parameter is a context object with the following boolean properties:  { isDev, isClient, isServer,
loaders } .

nuxt.config.js
export default {
build: {
extend(config, { isDev, isClient }) {
// ..
config.module.rules.push({
test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
loader: 'file-loader'
})
// Sets webpack's mode to development if `isDev` is true.
if (isDev) {
config.mode = 'development'
}
}
}
}

The  extend  method gets called twice - Once for the client bundle and the other for the server bundle.

Customize chunks configuration


You may want to tweak the optimization configuration a bit, avoiding a rewrite of the default object.

nuxt.config.js
export default {
build: {
extend(config, { isClient }) {
if (isClient) {
config.optimization.splitChunks.maxSize = 200000
}
}
}
}
Inspect webpack configuration
For complex projects and debugging it's sometimes useful to check what the final webpack configuration will look like. Luckily you
can run  nuxt webpack command from withing your project to output the configuration. Checkout this PR #7029 for more details.

Add webpack plugins


In your  nuxt.config.js  file, under the  build  option, you can pass webpack  plugins , the same way you would do it
in a  webpack.config.js  file.

In this example we add the webpack built-in ProvidePlugin for automatically loading JavaScript modules (lodash and jQuery) instead
of having to  import  or  require  them everywhere.

import webpack from 'webpack'

export default {
build: {
plugins: [
new webpack.ProvidePlugin({
// global modules
$: 'jquery',
_: 'lodash'
})
]
}
}

Note: You might not need jQuery in a Vue-based app.


With Nuxt, you can also control plugins execution context: if they are meant to be run on the  client  or in the  server  builds (or
differentiating  dev  and  prod builds) within  build.extend , where you can manually pass webpack plugins too.

Extend Webpack to load audio files


Audio files should be processed by  file-loader . This loader is already included in the default Webpack configuration, but it is not
set up to handle audio files. You need to extend its default configuration in  nuxt.config.js :

export default {
build: {
extend(config, ctx) {
config.module.rules.push({
test: /\.(ogg|mp3|wav|mpe?g)$/i,
loader: 'file-loader',
options: {
name: '[path][name].[ext]'
}
})
}
}
}

You can now import audio files like this  <audio :src="require('@/assets/water.mp3')" controls></audio> .

If you only want to write:  <audio src="@/assets/water.mp3" controls></audio> , you need to tell  vue-loader  to automatically require
your audio files when you reference them with the  src  attribute:
export default {
build: {
loaders: {
vue: {
transformAssetUrls: {
audio: 'src'
}
}
},

extend(config, ctx) {
config.module.rules.push({
test: /\.(ogg|mp3|wav|mpe?g)$/i,
loader: 'file-loader',
options: {
name: '[path][name].[ext]'
}
})
}
}
}

Edit host and port


By default, the Nuxt.js development server host is  localhost   which is only accessible from within the host machine. In order to view
your app on another device you need to modify the host. You can modify the host in your nuxt.config.js file.
Host  '0.0.0.0'   is designated to tell Nuxt.js to resolve a host address, which is accessible to connections outside of the host
machine (e.g. LAN). If the host is assigned the string value of  '0'  (not 0, which is falsy), or  '0.0.0.0'  your local IP address will be
assigned to your Nuxt.js application.

nuxt.config.js
export default {
server: {
host: '0' // default: localhost
}
}

You can also change the port number from the default port of 3000.

nuxt.config.js
export default {
server: {
port: 8000 // default: 3000
}
}

If the port is assigned the string value of  '0'  (not 0, which is falsy) a random port number will be assigned to your Nuxt.js application.

Although you can modify this in the nuxt.config.js file it is not advised to as it might cause you issues when hosting your site. It is
much better to modify the host and port direct in the dev command.

HOST=0 PORT=8000 npm run dev

or create a script in your package.json


"scripts": {
"dev:host": "nuxt --hostname '0' --port 8000"
}

Asynchronous Configuration
Although it is better to use the normal configuration  export default {}  you can have an async configuration by exporting an async
function that return the config object.

nuxt.config.js
import axios from 'axios'

export default async () => {


const data = await axios.get('https://api.nuxtjs.dev/posts')
return {
head: {
title: data.title
//... rest of config
}
}
}

The axios-module cannot be used in  nuxt.config.js . You will need to import axios and configure it again.

Further configuration
The  nuxt.config.js  has way more customization and configuration options! Check out all its keys in the configuration glossary.

Meta Tags and SEO Loading


Loading
Out of the box, Nuxt.js gives you its own loading progress bar component that's shown between routes. You can customize it,
disable it or even create your own loading component.

Customizing the Progress Bar


Among other properties, the color, size, duration and direction of the progress bar can be customized to suit your application's
needs. This is done by updating the  loading  property of the  nuxt.config.js  with the corresponding properties.

For example, to set a blue progress bar with a height of 5px, we update the  nuxt.config.js  to the following:

export default {
loading: {
color: 'blue',
height: '5px'
}
}

List of properties to customize the progress bar.

Key Type Default Description


color String 'black' CSS color of the progress bar
CSS color of the progress bar when an error appended while rendering the route (if data or fetch sent back
failedColor String 'red'
an error for example).
height String '2px' Height of the progress bar (used in the style property of the progress bar)
In ms, wait for the specified time before displaying the progress bar. Useful for preventing the bar from
throttle Number 200
flashing.
Key Type Default Description
In ms, the maximum duration of the progress bar, Nuxt.js assumes that the route will be rendered before 5
duration Number 5000
seconds.
continuous Boolean false Keep animating progress bar when loading takes longer than duration.
css Boolean true Set to false to remove default progress bar styles (and add your own).
rtl Boolean false Set the direction of the progress bar from right to left.

Disable the Progress Bar


If you don't want to display the progress bar between the routes add  loading: false  in your  nuxt.config.js  file:

nuxt.config.js
export default {
loading: false
}

The loading property gives you the option to disable the default loading progress bar on a specific page.

pages/index.vue
<template>
<h1>My page</h1>
</template>

<script>
export default {
loading: false
}
</script>
Programmatically starting the loading bar
The loading bar can also be programmatically started in your components by calling  this.$nuxt.$loading.start()  to start the
loading bar and  this.$nuxt.$loading.finish()  to finish it.

During your page component's mounting process, the  $loading  property may not be immediately available to access. To work
around this, if you want to start the loader in the  mounted  method, make sure to wrap your  $loading  method calls
inside  this.$nextTick  as shown below.

export default {
mounted() {
this.$nextTick(() => {
this.$nuxt.$loading.start()
setTimeout(() => this.$nuxt.$loading.finish(), 500)
})
}
}

Internals of the Progress Bar


Unfortunately, it is not possible for the Loading component to know in advance how long loading a new page will take. Therefore, it
is not possible to accurately animate the progress bar to 100% of the loading time.

Nuxt's loading component partially solves this by letting you set the  duration , this should be set to an estimate of how long the
loading process will take. Unless you use a custom loading component, the progress bar will always move from 0% to 100%
in  duration  time (regardless of actual progression). When the loading takes longer than  duration  time, the progress bar will stay at
100% until the loading finishes.
You can change the default behavior by setting  continuous  to true, then after reaching 100% the progress bar will start shrinking
back to 0% again in  duration  time. When the loading is still not finished after reaching 0% it will start growing from 0% to 100%
again, this repeats until the loading finishes.

export default {
loading: {
continuous: true
}
}

Example of a continuous progress bar:

Using a Custom Loading Component


You can also create your own component that Nuxt.js will call instead of the default loading progress bar component. To do so, you
need to give a path to your component in the  loading  option. Then, your component will be called directly by Nuxt.js.

Your component has to expose some of these methods:

Method Required Description


start() Required Called when a route changes, this is where you display your component.
finish() Required Called when a route is loaded (and data fetched), this is where you hide your component.
fail(error) Optional Called when a route couldn't be loaded (failed to fetch data for example).
Method Required Description
increase(num) Optional Called during loading the route component, num is an Integer < 100.
You can create your custom component in  components/LoadingBar.vue :

components/LoadingBar.vue
<template>
<div v-if="loading" class="loading-page">
<p>Loading...</p>
</div>
</template>

<script>
export default {
data: () => ({
loading: false
}),
methods: {
start() {
this.loading = true
},
finish() {
this.loading = false
}
}
}
</script>

<style scoped>
.loading-page {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.8);
text-align: center;
padding-top: 200px;
font-size: 30px;
font-family: sans-serif;
}
</style>

Then, you update your  nuxt.config.js  to tell Nuxt.js to use your component:

nuxt.config.js
export default {
loading: '~/components/LoadingBar.vue'
}

The loading indicator Property


When running Nuxt.js in SPA mode, there is no content from the server side on the first page load. So, instead of showing a blank
page while the page loads, Nuxt.js gives you a spinner which you can customize to add your own colors or background and even
change the the indicator.

nuxt.config.js
export default {
loadingIndicator: {
name: 'circle',
color: '#3B8070',
background: 'white'
}
}

Built-in indicators
These indicators are imported from the awesome SpinKit project. You can check out its demo page to preview the spinners. In order
to use one of these spinners all you have to do is add its name to the name property. No need to import or install anything. Here is a
list of built in indicators you can use.

circle

cube-grid

fading-circle

folding-cube

chasing-dots

nuxt

pulse

rectangle-bounce

rotating-plane

three-bounce

wandering-cubes

Built-in indicators support  color  and  background  options.


Custom indicators
If you need your own special indicator, a String value or Name key can also be a path to an HTML template of indicator source code!
All of the options are passed to the template, too.

Nuxt's built-in source code is also available if you need a base!

Configuration Nuxt Components


Nuxt Components
Nuxt.js comes with a few important components included out of the box, which will be helpful when building your application. The
components are globally available, which means that you don't need to import them in order to use them.

In the following paragraphs, each of the included components is explained.

The Nuxt Component


The  <Nuxt>  component is the component you use to display your page components. Basically, this component gets replaced by
what is inside your page components depending on the page that is being shown. Therefore it is important that you add
the  <Nuxt>  component to your layouts.

layouts/default.vue
<template>
<div>
<div>My nav bar</div>
<Nuxt />
<div>My footer</div>
</div>
</template>

The  <Nuxt>  component can only be used inside layouts.

The  <Nuxt>  component can take the prop of  nuxt-child-key . This prop will be passed to  <RouterView>  so that your transitions will
work correctly inside dynamic pages.
There are 2 ways to handle the internal  key  prop of  <RouterView> .

. Use a  nuxtChildKey  prop on your  <Nuxt>  component

layouts/default.vue
<template>
<div>
<Nuxt :nuxt-child-key="someKey" />
</div>
</template>

. Add the  key  option in page components as  string  or  function

export default {
key(route) {
return route.fullPath
}
}

The NuxtChild Component


This component is used for displaying the children components in a nested route.

Example:

-| pages/
---| parent/
------| child.vue
---| parent.vue

This file tree will generate these routes:

;[
{
path: '/parent',
component: '~/pages/parent.vue',
name: 'parent',
children: [
{
path: 'child',
component: '~/pages/parent/child.vue',
name: 'parent-child'
}
]
}
]

To display the  child.vue  component, you have to insert the  <NuxtChild> component inside  pages/parent.vue :

pages/parent.vue
<template>
<div>
<h1>I am the parent view</h1>
<NuxtChild :foobar="123" />
</div>
</template>
keep-alive
Both, the  <Nuxt>  component and the  <NuxtChild/>  component, accept  keep-alive  and  keep-alive-props.

To learn more about keep-alive and keep-alive-props see the vue docs

layouts/default.vue
<template>
<div>
<Nuxt keep-alive :keep-alive-props="{ exclude: ['modal'] }" />
</div>
</template>

<!-- will be converted into something like this -->


<div>
<KeepAlive :exclude="['modal']">
<RouterView />
</KeepAlive>
</div>

pages/parent.vue
<template>
<div>
<NuxtChild keep-alive :keep-alive-props="{ exclude: ['modal'] }" />
</div>
</template>

<!-- will be converted into something like this -->


<div>
<KeepAlive :exclude="['modal']">
<RouterView />
</KeepAlive>
</div>

<NuxtChild>  components can also receive properties like a regular Vue component.

<template>
<div>
<NuxtChild :key="$route.params.id" />
</div>
</template>

The NuxtLink Component


To navigate between pages of your app, you should use the   <NuxtLink>  component. This component is included with Nuxt.js and
therefore you don't have to import it like you do with other components. It is similar to the HTML  <a>  tag except that instead of
using a  href="/about"  you use  to="/about" . If you've used  vue-router  before, you can think of  <NuxtLink>  as a replacement
of  <RouterLink>

A simple link to the  index.vue  page in your  pages  folder:

<template>
<NuxtLink to="/">Home page</NuxtLink>
</template>

The  <NuxtLink>  component should be used for all internal links. That means for all links to the pages within your site you should
use  <NuxtLink> . The  <a>  tag should be used for all external links. That means if you have links to other websites you should use
the  <a>  tag for those.

<template>
<div>
<h1>Home page</h1>
<NuxtLink to="/about"
>About (internal link that belongs to the Nuxt App)</NuxtLink
>
<a href="https://nuxtjs.org">External Link to another page</a>
</div>
</template>

If you want to know more about  <RouterLink> , feel free to read the Vue Router documentation for more information.

prefetchLinks
Nuxt.js automatically includes smart prefetching. That means it detects when a link is visible, either in the viewport or when scrolling
and prefetches the JavaScript for those pages so that they are ready when the user clicks the link. Nuxt.js only loads the resources
when the browser isn't busy and skips prefetching if your connection is offline or if you only have 2G connection.

Check out this article to learn more about smart prefetching.

Disable prefetching for specific links

However sometimes you may want to disable prefetching on some links if your page has a lot of JavaScript or you have a lot of
different pages that would be prefetched or you have a lot of third party scripts that need to be loaded. To disable the prefetching
on a specific link, you can use the  no-prefetch  prop. Since Nuxt.js v2.10.0, you can also use the  prefetch  prop set to  false

<NuxtLink to="/about" no-prefetch>About page not prefetched</NuxtLink>


<NuxtLink to="/about" :prefetch="false">About page not prefetched</NuxtLink>

Disable prefetching globally

To disable the prefetching on all links, set the  prefetchLinks  to  false :

nuxt.config.js
export default {
router: {
prefetchLinks: false
}
}

Since Nuxt.js v2.10.0, if you have to set  prefetchLinks  to  false  but you want to prefetch a specific link, you can use
the  prefetch  prop:

<NuxtLink to="/about" prefetch>About page prefetched</NuxtLink>

Link Classes

linkActiveClass
The  linkActiveClass  works the same as the  vue-router  class for active links. If we want to show which links are active all you have
to do is create some css for the class  nuxt-link-active  .

.nuxt-link-active {
color: red;
}

This css can be added to the navigation component or for a specific page or layout or in your main.css file.

If you want to you can also configure the class name to be something else. You can do this by modifying the  linkActiveClass  in the
router property in your  nuxt.config.js  file.

export default {
router: {
linkActiveClass: 'my-custom-active-link'
}
}

This option is given directly to the  vue-router  linkActiveClass. See the vue-router docs for more info.

linkExactActiveClass

The  linkExactActiveClass  works the same as the  vue-router  class for exact active links. If we want to show which links are active
with an exact match all you have to do is create some css for the class  nuxt-link-exact-active  .
.nuxt-link-exact-active {
color: green;
}

This css can be added to the navigation component or for a specific page or layout or in your main.css file.

If you want to you can also configure the class name to be something else. You con do this by modifying
the  linkExactActiveClass  in the router property in your  nuxt.config.js  file.

nuxt.config.js
export default {
router: {
linkExactActiveClass: 'my-custom-exact-active-link'
}
}

This option is given directly to the  vue-router  linkExactActiveClass. See the vue-router docs for more info

linkPrefetchedClass

The linkPrefetchedClass will allow you to add styles for all links that have been prefetched. This is great for testing which links are
being prefetched after modifying the default behavior. The linkPrefetchedClass is disabled by default. If you want to enable it you
need to add it to the router property in your  nuxt-config.js  file.
nuxt.config.js
export default {
router: {
linkPrefetchedClass: 'nuxt-link-prefetched'
}
}

Then you can add the styles for that class.

.nuxt-link-prefetched {
color: orangered;
}

The client-only Component


This component is used to purposely render a component only on client-side. To import a component only on the client, register the
component in a client-side only plugin.

pages/example.vue
<template>
<div>
<sidebar />
<client-only placeholder="Loading...">
<!-- this component will only be rendered on client-side -->
<comments />
</client-only>
</div>
</template>
Use a slot as placeholder until  <client-only />  is mounted on client-side.

pages/example.vue
<template>
<div>
<sidebar />
<client-only>
<!-- this component will only be rendered on client-side -->
<comments />

<!-- loading indicator, rendered on server-side -->


<comments-placeholder slot="placeholder" />
</client-only>
</div>
</template>

Sometimes in server rendered pages  $refs  inside  <client-only>  might not be ready even with  $nextTick , the trick might be to
call  $nextTick  couple of times:

page.vue
mounted(){
this.initClientOnlyComp()
},
methods: {
initClientOnlyComp(count = 10) {
this.$nextTick(() => {
if (this.$refs.myComp) {
//...
} else if (count > 0) {
this.initClientOnlyComp(count - 1);
}
});
},
}

If you are using a version of Nuxt < v2.9.0, use  <no-ssr>  instead of  <client-only>

Loading Transitions
Transitions
Nuxt.js uses the transition component to let you create amazing transitions/animations between your routes.

To define a custom transition for a specific route add the  transition  key to the page component.

pages/index.vue
export default {
// Can be a String
transition: ''
// Or an Object
transition: {}
// or a Function
transition (to, from) {}
}

String
If the  transition  key is set as a string, it will be used as the  transition.name .

pages/index.vue
export default {
transition: 'home'
}

Nuxt.js will use these settings to set the component as follows:

pages/index.vue
<transition name="home"></transition>
This is automatically done for you and you do not need to add the  <transition> component to your pages or layouts.

Now all you have to do is create the new class for your transitions.

pages/index.vue
<style>
.home-enter-active, .home-leave-active { transition: opacity .5s; }
.home-enter, .home-leave-active { opacity: 0; }
</style>

Object
If the  transition  key is set as an object:

pages/index.vue
export default {
transition: {
name: 'home',
mode: 'out-in'
}
}

Nuxt.js will use these settings to set the component as follows:

pages/index.vue
<transition name="home" mode="out-in"></transition>
The  transition  object can have many properties such as name, mode, css, duration and many more. Please see the vue docs for
more info.

You can also define methods in the page  transition  property, for more information on the JavaScript hooks see the vue docs.

export default {
transition: {
afterLeave(el) {
console.log('afterLeave', el)
}
}
}

Transition Mode

The default transition mode for pages differs from the default mode in Vue.js. The  transition  mode is by default set to  out-in . If you want
to run leaving and entering transitions simultaneously, you have to set the mode to the empty string  mode: '' .

pages/index.vue
export default {
transition: {
name: 'home',
mode: ''
}
}
Function
If the  transition  key is set as a function:

pages/index.vue
export default {
transition(to, from) {
if (!from) {
return 'slide-left'
}
return +to.query.page < +from.query.page ? 'slide-right' : 'slide-left'
}
}

Transitions applied on navigation:

/  to  /posts  =>  slide-left , /posts  to  /posts?page=3  =>  slide-left , /posts?page=3  to  /posts?page=2  =>  slide-right .

Global Settings
The Nuxt.js default transition name is  "page" . To add a fade transition to every page of your application, all you need is a CSS file
that is shared across all your routes.

Our global css in  assets/main.css :

assets/main.css
.page-enter-active,
.page-leave-active {
transition: opacity 0.5s;
}
.page-enter,
.page-leave-to {
opacity: 0;
}

Then we add its path to the  css  array in our  nuxt.config.js  file:

nuxt.config.js
export default {
css: ['~/assets/main.css']
}

Configuration Settings

The layoutTransition Property


The layout transition is used to set the default properties of the layout transitions.

The default settings for layout transitions are:

{
name: 'layout',
mode: 'out-in'
}

assets/main.css
.layout-enter-active,
.layout-leave-active {
transition: opacity 0.5s;
}
.layout-enter,
.layout-leave-active {
opacity: 0;
}

If you want to change the default settings for your layout transitions you can do so in the nuxt.config.js file.

nuxt.config.js
export default {
layoutTransition: 'my-layouts'
// or
layoutTransition: {
name: 'my-layouts',
mode: 'out-in'
}
}

assets/main.css
.my-layouts-enter-active,
.my-layouts-leave-active {
transition: opacity 0.5s;
}
.my-layouts-enter,
.my-layouts-leave-active {
opacity: 0;
}
The pageTransition Property
The default settings for page transitions are:

{
name: 'page',
mode: 'out-in'
}

Should you wish to modify the default settings you can do so in the nuxt.config.js

nuxt.config.js
export default {
pageTransition: 'my-page'
// or
pageTransition: {
name: 'my-page',
mode: 'out-in',
beforeEnter (el) {
console.log('Before enter...');
}
}
}

If you do modify the page Transition name you will also have to rename the css class.

assets/main.css
.my-page-enter-active,
.my-page-leave-active {
transition: opacity 0.5s;
}
.my-page-enter,
.my-page-leave-to {
opacity: 0;
}

Nuxt Components Preview Mode


Preview Mode
With Nuxt.js and full static you can now use live preview out of the box which will call your API or your CMS so you can see the
changes live before deploying.

Only available when using target:static

The preview mode will automatically refresh the page data as it uses  $nuxt.refresh  under the hood and therefore calls
nuxtServerInit, asyncData and fetch on the client side.

In order to activate live preview you will need to add the following plugin:

plugins/preview.client.js
export default function ({ query, enablePreview }) {
if (query.preview) {
enablePreview()
}
}

`enablePreview` is only available in the context object of plugins. Previews are handled client-side and thus the plugin should be run on the
client: preview.client.js

nuxt.config.js
export default {
plugins: ['~/plugins/preview.client.js']
}

Once you have added the plugin you can now generate your site and serve it.
npx Yarn

npx nuxt generate


npx nuxt start

Then you can see your preview page by adding the query param to the end of the page you want to see once:

?preview=true

enablePreview should be tested locally with yarn start and not yarn dev

Previewing pages that are not yet generated


For pages that are not yet generated, SPA fallback will still call the API before showing the 404 page as these pages exist on the API
but are not generated yet.

If you have set a validate hook, you will probably need to modify it so that it doesn't redirect to the 404 page in preview mode.

validate({ params, query }) {


if (query.preview) {
return true
}

Passing data to enablePreview


You can pass data to the  enablePreview  function. That data will then be available on the  $preview  context helper and
on  this.$preview .

What's next

Check out the Directory Structure book

Transitions  
.nuxt
The  .nuxt  directory is the so-called build directory. It is dynamically generated and hidden by default. Inside the directory you can
find automatically generated files when using  nuxt dev  or your build artifacts when using  nuxt build . Modifying these files is great
for debugging but remember that they are generated files and once you run the  dev  or  build  command again, anything that was
saved here will be regenerated.

The  .nuxt  directory should not be committed to your version control system and should be ignored through your  .gitignore  as it will be
generated automatically when executing  nuxt dev  or  nuxt build .

The buildDir Property


By default, many tools assume that  .nuxt  is a hidden directory, because its name starts with a dot. You can use the buildDir option
to prevent that. If you do change the name remember to add the new name to your  .gitignore  file.

nuxt.config.js
export default {
buildDir: 'nuxt-dist'
}

Inside the .nuxt folder:

The router.js file is the generated router file that Nuxt.js generates for you when you put  .vue  files inside the pages folder. You
can use this file for debugging for when you want to look up which routes are generated for vue-router and find out the names of a
specific route.

The router.scrollBehavior.js which is your Router ScrollBehavior


The Components folder has all your Nuxt components such as NuxtChild and NuxtLink. It also contains the nuxt-build-indicator
which is the page we see when your application is building and nuxt-loading which is your loading component that gets seen when
we are waiting for your page to load. You will also find the nuxt-error page in here which contains the Nuxt default error page.

The mixins folder has the files needed for the Nuxt  $fetch  method.

The views folder contains your app template and your server error page.

The app.js is your main application file.

The client.js file is your client file needed for everything that happens client side.

The empty file is intentionally left empty for no-op aliases

The index.js file bootstraps your application.

The loading.html is the file that is used when the page is loading.

The middleware file is where your middleware is kept

The server.js file is all the code that is ran on the server

the utilities contains the utilities that Nuxt needs for it to work.

Deploying
The  .nuxt  folder is part of the files needed to deploy your SSR application. It is not needed for deploying your static Nuxt.js app
though because we use the  dist  folder for that.

  assets
assets
The  assets  directory contains your uncompiled assets such as Stylus or Sass files, images, or fonts.

Images
Inside your  vue  templates, if you need to link to your  assets  directory use  ~/assets/your_image.png  with a slash before assets.

<template>
<img src="~/assets/your_image.png" />
</template>

Inside your  css  files, if you need to reference your   assets   directory, use  ~assets/your_image.png (without a slash)

background: url('~assets/banner.svg');

When working with dynamic images you will need to use require

<img :src="require(`~/assets/img/${image}.jpg`)" />

Learn more about webpack Assets

Styles
Nuxt.js lets you define the CSS files/modules/libraries you want to set globally (included in every page). In the nuxt.config you can
easily add your styles using the CSS Property.

nuxt.config.js
export default {
css: [
// Load a Node.js module directly (here it's a Sass file)
'bulma',
// CSS file in the project
'~/assets/css/main.css',
// SCSS file in the project
'~/assets/css/main.scss'
]
}

Sass
In case you want to use  sass  make sure that you have installed  sass  and  sass-loader  packages.

Yarn npm

yarn add -D sass sass-loader@10 fibers

Synchronous compilation with  sass  (2x speed increase) is enabled automaticallywhen  fibers  is installed.

Nuxt.js will automatically guess the file type by its extension and use the appropriate pre-processor loader for webpack. You will still
need to install the required loader if you need to use them.
Fonts
You can use local fonts by adding them to your assets folder. Once they have been added you can then access them through your css
using the @font-face.

-| assets
----| fonts
------| DMSans-Regular.ttf
------| DMSans-Bold.ttf

assets/main.css
@font-face {
font-family: 'DM Sans';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('~assets/fonts/DMSans-Regular.ttf') format('truetype');
}

@font-face {
font-family: 'DM Sans';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url('~assets/fonts/DMSans-Bold.ttf') format('truetype');
}

CSS files are not automatically loaded. Add them using the CSS config property .
To add external fonts such as google fonts check out the Meta Tags and SEO chapter

Webpack Assets
By default, Nuxt uses webpack's vue-loader, file-loader and url-loader to serve your assets. You can also use the static directory for
assets that should not run through webpack

Webpack
vue-loader automatically processes your style and template files with  css-loader  and the Vue template compiler out of the box. In
this compilation process, all asset URLs such as  <img src="..."> ,  background: url(...)  and CSS  @import  are resolved as module
dependencies.

For example, we have this file tree:

-| assets/
----| image.png
-| pages/
----| index.vue

If you use  url('~assets/image.png')  in your CSS, it will be translated  into   require('~/assets/image.png') .

The  ~/  alias won't be resolved correctly in your CSS files. You must use  ~assets  (without a slash) in  url  CSS references, i.e.  background:
url("~assets/banner.svg")
If you reference that image in your  pages/index.vue :

pages/index.vue
<template>
<img src="~/assets/image.png" />
</template>

It will be compiled into:

createElement('img', { attrs: { src: require('~/assets/image.png') } })

Because  .png  is not a JavaScript file, Nuxt.js configures webpack to use file-loader and url-loader to handle them for you.

The benefits of these loaders are:

file-loader  lets you designate where to copy and place the asset file, and how to name it using version hashes for better caching.
In production, you will benefit from long-term caching by default!

url-loader  allows you to conditionally inline files as base64 data URLs if they are smaller than a given threshold. This can reduce the
number of HTTP requests for trivial files. If a file is larger than the threshold, it automatically falls back to file-loader.

For these two loaders, the default configuration is:

// https://github.com/nuxt/nuxt.js/blob/dev/packages/webpack/src/config/base.js#L382-L411
{
test: /\.(png|jpe?g|gif|svg|webp|avif)$/i,
use: [{
loader: 'url-loader',
options: {
esModule: false,
limit: 1000, // 1kB
name: 'img/[name].[contenthash:7].[ext]'
}
}]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
use: [{
loader: 'url-loader',
options: {
esModule: false,
limit: 1000, // 1kB
name: 'fonts/[name].[contenthash:7].[ext]'
}
}]
},
{
test: /\.(webm|mp4|ogv)$/i,
use: [{
loader: 'file-loader',
options: {
esModule: false,
name: 'videos/[name].[contenthash:7].[ext]'
}
}]
}

Which means that every file below 1 kB will be inlined as base64 data URL. Otherwise, the image/font will be copied in its
corresponding folder (inside the  .nuxt  directory) with a name containing a version hash for better caching.
When launching your application with  nuxt , your template in  pages/index.vue :

pages/index.vue
<template>
<img src="~/assets/your_image.png" />
</template>

Will be transformed into:

<img src="/_nuxt/img/your_image.0c61159.png" />

If you want to change the loader configurations, please use build.extend.

Aliases
By default the source directory (srcDir) and the root directory (rootDir) are the same. You can use the alias of  ~  for the source
directory. Instead of writing relative paths like  ../assets/your_image.png  you can use  ~/assets/your_image.png .

Both will achieve the same results.

components/Avatar.vue
<template>
<div>
<img src="../assets/your_image.png" />
<img src="~/assets/your_image.png" />
</div>
</template>
We recommend using the  ~  as an alias.  @  is still supported but will not work in all cases such as with background images in your
css.

You can use the alias of  ~~  or  @@  for the root directory.

Tip: On Spanish keyboard you can access  ~  with ( Option  +  ñ ) on Mac OS, or ( Alt gr  +  4 ) on Windows

.nuxt components
components
The components directory contains your Vue.js components. Components are what makes up the different parts of your page and
can be reused and imported into your pages, layouts and even other components.

Fetching Data
To access asynchronous data from an API in your components you can use Nuxt  fetch()  hook.

By checking  $fetchState.pending , we can show a message when data is waiting to be loaded. We can also
check  $fetchState.error  and show an error message if there is an error fetching the data. When using  fetch() , we must declare
the appropriate properties in  data() . The data that comes from the fetch can then be assigned to these properties.

components/MountainsList.vue
<template>
<div>
<p v-if="$fetchState.pending">Loading....</p>
<p v-else-if="$fetchState.error">Error while fetching mountains</p>
<ul v-else>
<li v-for="(mountain, index) in mountains" :key="index">
{{ mountain.title }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
mountains: []
}
},
async fetch() {
this.mountains = await fetch(
'https://api.nuxtjs.dev/mountains'
).then(res => res.json())
}
}
</script>

See the chapter on fetch() for more details on how fetch works.

Components Discovery
Starting from  v2.13 , Nuxt can auto import your components when used in your templates. To activate this feature, set  components:
true  in your configuration:
nuxt.config.js
export default {
components: true
}

Once you create your components in the components directory they will then be available to be auto imported.

components/
TheHeader.vue
TheFooter.vue

layouts/default.vue
<template>
<div>
<TheHeader />
<Nuxt />
<TheFooter />
</div>
</template>

Dynamic Imports
To dynamically import a component, also known as lazy loading a component, all you need to do is add the  Lazy  prefix in your
templates.

layouts/default.vue
<template>
<div>
<TheHeader />
<Nuxt />
<LazyTheFooter />
</div>
</template>

Using the lazy prefix you can also dynamically import a component when an event is triggered.

pages/index.vue
<template>
<div>
<h1>Mountains</h1>
<LazyMountainsList v-if="show" />
<button v-if="!show" @click="showList">Show List</button>
</div>
</template>

<script>
export default {
data() {
return {
show: false
}
},
methods: {
showList() {
this.show = true
}
}
}
</script>
Nested Directories
If you have components in nested directories such as:

components/
base/
foo/
Button.vue

The component name will be based on its own path directory and filename. Therefore, the component will be:

<BaseFooButton />

However, if you want to use custom directory strcture that should not be part of component name, can explicitly specify these
directories:

components/
base/
foo/
Button.vue

nuxt.config.js
components: {
dirs: [
'~/components',
'~/components/base'
]
}
And now in your template you can use  FooButton  instead of  BaseFooButton .

pages/index.vue
<FooButton />

Learn more about the components module .

assets content
content
Empower your Nuxt.js application with  @nuxtjs/content  module where you can write in a  content/  directory and fetch your
Markdown, JSON, YAML and CSV files through a MongoDB like API, acting as a Git-based Headless CMS.
Hot reload in development
The content module is blazing fast when it comes to hot reloading in development due to not having to go through webpack when
you make changes to your markdown files. You can also listen to the  content:update  event and create a plugin so that every time
you update a file in your content directory it will dispatch a fetchCategories method for example.

See the content module docs for more details

Displaying content
You can use  <nuxt-content>  component directly in your template to display the page body.

pages/blog/_slug.vue
<template>
<article>
<nuxt-content :document="article" />
</article>
</template>

See the content module docs for more details

Styling your content


Depending on what you're using to design your app, you may need to write some style to properly display the markdown.

<nuxt-content>  component will automatically add a  .nuxt-content  class, you can use it to customize your styles.

<style>
.nuxt-content h2 {
font-weight: bold;
font-size: 28px;
}
.nuxt-content p {
margin-bottom: 20px;
}
</style>

See the content module docs for more details

Handles Markdown, CSV, YAML, JSON(5)


This module converts your .md files into a JSON AST tree structure, stored in a body variable. You can also add a YAML front matter
block to your markdown files or a .yaml file which will be injected into the document. You can also add a json/json5 file which can
also be injected into the document. And you can use a .csv file where rows will be assigned to the body variable.

---
title: My first Blog Post
description: Learning how to use @nuxt/content to create a blog
---

See the content module docs for more details

Vue components in Markdown


You can use Vue components directly in your markdown files. You will however need to use your components as kebab case and
cannot use self-closing tags.
components/global/InfoBox.vue
<template>
<div class="bg-blue-500 text-white p-4 mb-4">
<p><slot name="info-box">default</slot></p>
</div>
</template>

content/articles/my-first-blog-post.md
<info-box>
<template #info-box>
This is a vue component inside markdown using slots
</template>
</info-box>

See the content module docs for more details

Fully Searchable API


You can use  $content()  to list, filter and search your content easily.

pages/blog/index.vue
<script>
export default {
async asyncData({ $content, params }) {
const articles = await $content('articles', params.slug)
.only(['title', 'description', 'img', 'slug', 'author'])
.sortBy('createdAt', 'asc')
.fetch()
return {
articles
}
}
}
</script>

See the content module docs for more details

Previous and Next articles


The content module includes a  .surround(slug)  so that you get previous and next articles easily.

async asyncData({ $content, params }) {


const article = await $content('articles', params.slug).fetch()

const [prev, next] = await $content('articles')


.only(['title', 'slug'])
.sortBy('createdAt', 'asc')
.surround(params.slug)
.fetch()

return {
article,
prev,
next
}
},
<prev-next :prev="prev" :next="next" />

See the content module docs for more details

Full-text search
The content module comes with a full text search so you can easily search across your markdown files without having to install
anything.

components/AppSearchInput.vue
<script>
export default {
data() {
return {
searchQuery: '',
articles: []
}
},
watch: {
async searchQuery(searchQuery) {
if (!searchQuery) {
this.articles = []
return
}
this.articles = await this.$content('articles')
.limit(6)
.search(searchQuery)
.fetch()
}
}
}
</script>

See the content module docs for more details

Syntax highlighting
This module automatically wraps codeblocks and applies Prism classes. You can also add a different Prism theme or disable it
altogether.

Yarn npm

yarn add prism-themes

nuxt.config.js
content: {
markdown: {
prism: {
theme: 'prism-themes/themes/prism-material-oceanic.css'
}
}
}

See the content module docs for more details


Extend Markdown Parsing
Originally markdown does not support highlighting lines inside codeblock nor filenames. The content module allows it with its own
custom syntax. Line numbers are added to the  pre  tag in data-line attributes and the filename will be converted to a  span  with
a  filename  class, so you can style it.

See the content module docs for more details

Table of contents generation


A toc(Table of Contents) array property will be injected into your document, listing all the headings with their titles and ids, so you
can link to them.

pages/blog/_slug.vue
<nav>
<ul>
<li v-for="link of article.toc" :key="link.id">
<NuxtLink :to="`#${link.id}`">{{ link.text }}</NuxtLink>
</li>
</ul>
</nav>

See the content module docs for more details

Powerful query builder API (MongoDB-like)


The content module comes with a powerful query builder API similar to MongoDB which allows you to easily see the JSON of each
directory at  http://localhost:3000/_content/ . The endpoint is accessible on GET and POST request, so you can use query params.

http://localhost:3000/_content/articles?only=title&only=description&limit=10

See the content module docs for more details

Extend with hooks


You can use hooks to extend the module so you can add data to a document before it is stored.

See the content module docs for more details

Integration with @nuxtjs/feed


In the case of articles, the content can be used to generate news feeds using @nuxtjs/feed module.

See the content module docs for more details

Support static site generation


The content module works with static site generation using the  nuxt generate . All routes will be automatically generated thanks to
the nuxt crawler feature.

If using Nuxt <2.13 and you need to specify the dynamic routes you can do so using the generate property and using @nuxt/content
programmatically.

See the content module docs for more details on programmatic usage

What's next

Check out our tutorial on How to Create a Blog with Nuxt Content

Check out the content module docs for more advanced usage and examples

components dist
dist
The  dist  folder, short for distribution folder. It is dynamically generated when using the  nuxt generate  command and includes the
generated production ready HTML files and assets that are necessary to deploy and run your statically generated Nuxt.js application.

Deploying
This is the folder you need to upload for static hosting as it contains your generated production ready HTML files and assets

The  dist  directory should not be committed to your version control system and should be ignored through your  .gitignore  as it will be
generated automatically every time you run  nuxt generate .

The dir property


The dist folder is named dist by default but can be configured in your nuxt.config file.

nuxt.config.js
generate: {
dir: 'my-site'
}

If you do change your dist folder then you will need to add that to your version control so that git will ignore it.

The subFolders Property


Nuxt.js puts all your generated pages inside a folder by default, however you can change this if you want by modifying the
nuxt.config and changing the subFolders to be false.

nuxt.config.js
generate: {
subFolders: false
}

The fallback Property


When deploying your site you will need to make sure the fallback HTML path is set correctly. It should be set as the error page so
that unknown routes are rendered via Nuxt. If it is unset Nuxt.js will use the default value which is 200.html.

When running a single page application it makes more sense to use 200.html as it is the only file necessary as no other routes are
generated.

When working with statically generated pages it is recommended to use a 404.html for error pages.

Depending on where you are hosting your site, you may have to use 200.html or 404.html. Please check with your hosting provider. Netlify, for
example uses 404.html.

nuxt.config.js
export default {
generate: {
fallback: '404.html'
}
}
The excludes property
You can exclude pages from being generated by using the generate excludes property. Instead of being generated as a static page it
will fallback to be a single page application page and will only be rendered on the client side.

nuxt.config.js
generate: {
exclude: [/admin/]
}

You can also use a regex expression here to exclude pages starting or ending with a particular word

content layouts
layouts
Layouts are a great help when you want to change the look and feel of your Nuxt.js app. Whether you want to include a sidebar or
have distinct layouts for mobile and desktop.

This directory cannot be renamed without extra configuration.

Default Layout
You can extend the main layout by adding a  layouts/default.vue  file. It will be used for all pages that don't have a layout specified.
Make sure to add the  <Nuxt>  component when creating a layout to actually include the page component.

All you need in your layout is three lines of code which will render the page component.

layouts/default.vue
<template>
<Nuxt />
</template>

You can add more components here such as Navigation, Header, Footer etc.

layouts/default.vue
<template>
<div>
<TheHeader />
<Nuxt />
<TheFooter />
</div>
</template>

If you have components set to true then there is no need to add any import statements for your components.

Custom Layout
Every file (top-level) in the  layouts  directory will create a custom layout accessible with the  layout  property in the page
components.

Let's say we want to create a blog layout and save it to  layouts/blog.vue :

layouts/blog.vue
<template>
<div>
<div>My blog navigation bar here</div>
<Nuxt />
</div>
</template>

Then you have to tell the pages to use your custom layout

pages/posts.vue
<script>
export default {
layout: 'blog',
// OR
layout (context) {
return 'blog'
}
}
</script>

Error Page
The error page is a page component which is always displayed when an error occurs (that is not thrown on the server-side).

Though this file is placed in the  layouts  folder, it should be treated as a page.

As mentioned above, this layout is special and you should not include  <Nuxt>  inside its template. You must see this layout as a
component displayed when an error occurs ( 404 ,  500 , etc.). Similar to other page components, you can set a custom layout for the
error page as well in the usual way.

You can customize the error page by adding a  layouts/error.vue  file:

layouts/error.vue
<template>
<div class="container">
<h1 v-if="error.statusCode === 404">Page not found</h1>
<h1 v-else>An error occurred</h1>
<NuxtLink to="/">Home page</NuxtLink>
</div>
</template>

<script>
export default {
props: ['error'],
layout: 'blog' // you can set a custom layout for the error page
}
</script>

The default error page source code is available on GitHub.

dist middleware
middleware
The  middleware  directory contains your application middleware. Middleware lets you define custom functions that can be run
before rendering either a page or a group of pages (layout).

Shared 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). You can also define page-specific middleware by using a function directly,
see anonymous middleware.

A middleware receives the context as the first argument.

middleware/user-agent.js
export default function (context) {
// Add the userAgent property to the context
context.userAgent = process.server
? context.req.headers['user-agent']
: navigator.userAgent
}

In universal mode, middlewares will be called once on server-side (on the first request to the Nuxt app, e.g. when directly accessing
the app or refreshing the page) and on the client-side when navigating to further routes. With  ssr: false , middlewares will be
called on the client-side in both situations.

The middleware will be executed in series in this order:

. nuxt.config.js  (in the order within the file)

. Matched layouts

. Matched pages
Router Middleware
A middleware can be asynchronous. To do this return a   Promise  or use async/await.

middleware/stats.js
import http from 'http'

export default function ({ route }) {


return http.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 (even multiple) to a specific layout or page as well.

pages/index.vue / layouts/default.vue
export default {
middleware: ['auth', 'stats']
}
Named middleware
You can create named middleware by creating a file inside the   middleware/  directory, the file name will be the middleware name.

middleware/authenticated.js
export default function ({ store, redirect }) {
// If the user is not authenticated
if (!store.state.authenticated) {
return redirect('/login')
}
}

pages/secret.vue
<template>
<h1>Secret page</h1>
</template>

<script>
export default {
middleware: 'authenticated'
}
</script>

Anonymous middleware
If you need to use a middleware only for a specific page, you can directly use a function for it (or an array of functions):

pages/secret.vue
<template>
<h1>Secret page</h1>
</template>

<script>
export default {
middleware({ store, redirect }) {
// If the user is not authenticated
if (!store.state.authenticated) {
return redirect('/login')
}
}
}
</script>

layouts modules
modules

Exploring Nuxt Modules


Discover our list of modules to supercharge your Nuxt project, created by the Nuxt team and community.

165+ Modules

105+ Maintainers

Check out modules.nuxtjs.org
Nuxt Modules Nuxt v2.14
September 2020
modules are Nuxt.js extensions that extend Nuxt's
core functionalities

// nuxt.config.js
export default {
modules: [
// Using package name
'@nuxtjs/axios',

// Relative to project srcDir


property type: modules '~/modules/simple',
array
// Providing options
['~/modules/simple', { token: '123' }]

Called once, in sequence, // Inline definition array item can be


while booting Nuxt app function () {} string, array with
]
i.e. npm run dev options or function
}

Write your own module


// nuxt.config.js
export default {
Combine multiple options modules: [
Top-level options [ '@nuxtjs/axios', { anotherOption: true }] ],
sources //axios module is aware of this by using`this.options.axios`
axios: { option1, option2 }
}

// modules/module.js
export default function (moduleOptions) {
Access Nuxt.js options, // `options` will contain option1,option2 & anotherOption
const options = Object.assign({},
including module's options this.options this.options.axios,
i.e. add a CSS library or moduleOptions
emit assets )
}
// modules/module.js
Refers to the current Nuxt.js export default function (moduleOptions) { this refers to the 
instance, allowing us this.nuxt.hook('ready', async nuxt => {}) moduleContainer
to register hooks on certain this.nuxt this.nuxt.hook('error', async error => {}) instance
this.nuxt.hook('close', async nuxt => {})
life-cycle events this.nuxt.hook('listen', async(server, {host, port})) => {})
i.e. provide plugins or }
register custom webpack loaders

// modules/mymodule.js
// Use async/await
export default async function asyncModule() {
create async modules that const pages = await ...
return a promise or async module }
// Return a promise
call a callback export default function asyncModule() {
return fetch().then(response => {...})
}

Use modules Use buildModules


If module: If module is imported during dev and build time.
- provides serverMiddleware
- registers Node.js runtime hook simply, add dependency in devDependencies and
use buildModules:
- affects vue-renderer behaviour
- or anything that's outside of webpack scope // nuxt.config.js
export default {
// nuxt.config.js buildModules: ['@nuxtjs/eslint-module']
export default { }
modules: ['@nuxtjs/sitemap']
✅ Decrease node_module size
} Benefits:
✅ Make production startup faster

While developing production-grade applications with Nuxt.js you might find that the framework's core functionality is not enough.
Nuxt.js can be extended with configuration options and plugins, but maintaining these customizations across multiple projects is
tedious, repetitive and time-consuming. On the other hand, supporting every project's needs out of the box would make Nuxt.js
very complex and hard to use.
This is one of the reasons why Nuxt.js provides a higher-order module system that makes it possible to extend the core. Modules are
functions that are called sequentially when booting Nuxt.js. The framework waits for each module to finish before continuing. In this
way, modules can customize almost any aspect of your project. Thanks to Nuxt.js' modular design (based on webpack's Tapable),
modules can easily register hooks for certain entry points like the builder initialization. Modules can also override templates,
configure webpack loaders, add CSS libraries, and perform many other useful tasks.

Best of all, Nuxt.js modules can be incorporated into npm packages. This makes it possible to reuse across projects and to share with
the community, helping create an ecosystem of high-quality add-ons.

The modules Property


Modules are Nuxt.js extensions which can extend the framework's core functionality and add endless integrations. Once you have
installed the modules you can then add them to your nuxt.config.js file under the modules property.

nuxt.config.js
export default {
modules: [
// Using package name
'@nuxtjs/axios',

// Relative to your project srcDir


'~/modules/awesome.js',

// Providing options
['@nuxtjs/google-analytics', { ua: 'X1234567' }],

// Inline definition
function () {}
]
}
Module developers usually provide additionally needed steps and details for usage.

Nuxt.js tries to resolve each item in the modules array using node require path (in the  node_modules ) and then will resolve from the
project  srcDir  if  @  alias is used.

Modules are executed sequentially so the order is important.

Modules should export a function to enhance build/runtime and optionally return a promise until their job is finished. Note that
they are imported at runtime so they should be already transpiled if using modern ES6 features.

Write your own Module


Modules are functions. They can be packaged as npm modules or directly included in your project source code.

nuxt.config.js
export default {
exampleMsg: 'hello',
modules: [
// Simple usage
'~/modules/example',
// Passing options directly
['~/modules/example', { token: '123' }]
]
}
modules/example.js
export default function ExampleModule(moduleOptions) {
console.log(moduleOptions.token) // '123'
console.log(this.options.exampleMsg) // 'hello'

this.nuxt.hook('ready', async nuxt => {


console.log('Nuxt is ready')
})
}

// REQUIRED if publishing the module as npm package


module.exports.meta = require('./package.json')

1) ModuleOptions
moduleOptions : This is the object passed using the  modules  array by the user. We can use it to customize its behavior.

Top level options


Sometimes it is more convenient if we can use top level options while registering modules in  nuxt.config.js . This allows us to
combine multiple option sources.

nuxt.config.js
export default {
modules: [['@nuxtjs/axios', { anotherOption: true }]],

// axios module is aware of this by using `this.options.axios`


axios: {
option1,
option2
}
}

2) this.options
this.options : You can directly access the Nuxt.js options using this reference. This is the content of the user's  nuxt.config.js  with
all default options assigned to it. It can be used for shared options between modules.

module.js
export default function (moduleOptions) {
// `options` will contain option1, option2 and anotherOption
const options = Object.assign({}, this.options.axios, moduleOptions)

// ...
}

Add a CSS Library


If your module will provide a CSS library, make sure to perform a check if the user already included the library to avoid duplicates,
and add an option to disable the CSS library in the module.

module.js
export default function (moduleOptions) {
if (moduleOptions.fontAwesome !== false) {
// Add Font Awesome
this.options.css.push('font-awesome/css/font-awesome.css')
}
}
Emit assets
We can register webpack plugins to emit assets during build.

module.js
export default function (moduleOptions) {
const info = 'Built by awesome module - 1.3 alpha on ' + Date.now()

this.options.build.plugins.push({
apply(compiler) {
compiler.plugin('emit', (compilation, cb) => {
// This will generate `.nuxt/dist/info.txt' with contents of info variable.
// Source can be buffer too
compilation.assets['info.txt'] = {
source: () => info,
size: () => info.length
}

cb()
})
}
})
}

3) this.nuxt
this.nuxt : This is a reference to the current Nuxt.js instance. We can register hooks on certain life cycle events.
Ready : Nuxt is ready to work (ModuleContainer and Renderer ready).

nuxt.hook('ready', async nuxt => {


// Your custom code here
})

Error: An unhandled error when calling hooks.

nuxt.hook('error', async error => {


// Your custom code here
})

Close: Nuxt instance is gracefully closing.

nuxt.hook('close', async nuxt => {


// Your custom code here
})

Listen: Nuxt internal server starts listening. (Using nuxt start or nuxt dev)

nuxt.hook('listen', async (server, { host, port }) => {


// Your custom code here
})

this : Context of modules. All modules will be called within context of the ModuleContainer instance.
Please look into the ModuleContainer class docs for available methods.

Run Tasks on Specific hooks


Your module may need to do things only on specific conditions and not just during Nuxt.js initialization. We can use the powerful
Nuxt.js hooks to do tasks on specific events (based on Hookable). Nuxt.js will wait for your function if it returns a Promise or is
defined as  async .

Here are some basic examples:

modules/myModule.js
export default function myModule() {
this.nuxt.hook('modules:done', moduleContainer => {
// This will be called when all modules finished loading
})

this.nuxt.hook('render:before', renderer => {


// Called after the renderer was created
})

this.nuxt.hook('build:compile', async ({ name, compiler }) => {


// Called before the compiler (default: webpack) starts
})

this.nuxt.hook('generate:before', async generator => {


// This will be called before Nuxt generates your pages
})
}
Provide plugins
It is common that modules provide one or more plugins when added. For example bootstrap-vue module would require to register
itself into Vue. In such situations we can use the  this.addPlugin  helper.

plugin.js
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue/dist/bootstrap-vue.esm'

Vue.use(BootstrapVue)

module.js
import path from 'path'

export default function nuxtBootstrapVue(moduleOptions) {


// Register `plugin.js` template
this.addPlugin(path.resolve(__dirname, 'plugin.js'))
}

Template plugins
Registered templates and plugins can leverage lodash templates to conditionally change registered plugins output.

plugin.js
// Set Google Analytics UA
ga('create', '<%= options.ua %>', 'auto')

<% if (options.debug) { %>


// Dev only code
<% } %>
module.js
import path from 'path'

export default function nuxtBootstrapVue(moduleOptions) {


// Register `plugin.js` template
this.addPlugin({
src: path.resolve(__dirname, 'plugin.js'),
options: {
// Nuxt will replace `options.ua` with `123` when copying plugin to project
ua: 123,

// conditional parts with dev will be stripped from plugin code on production builds
debug: this.options.dev
}
})
}

Register custom webpack loaders


We can do the same as   build.extend   in   nuxt.config.js   using   this.extendBuild .

module.js
export default function (moduleOptions) {
this.extendBuild((config, { isClient, isServer }) => {
// `.foo` Loader
config.module.rules.push({
test: /\.foo$/,
use: [...]
})
// Customize existing loaders
// Refer to source code for Nuxt internals:
// https://github.com/nuxt/nuxt.js/blob/dev/packages/webpack/src/config/base.js
const barLoader = config.module.rules.find(rule => rule.loader === 'bar-loader')
})
}

Async Modules
Not all modules will do everything synchronous. For example you may want to develop a module which needs fetching some API or
doing asynchronous Operation. For this, Nuxt.js supports async modules which can return a Promise or call a callback.

Use async/await

import fse from 'fs-extra'

export default async function asyncModule() {


// You can do async work here using `async`/`await`
const pages = await fse.readJson('./pages.json')
}

Return a Promise
export default function asyncModule($http) {
return $http
.get('https://jsonplaceholder.typicode.com/users')
.then(res => res.data.map(user => '/users/' + user.username))
.then(routes => {
// Do something by extending Nuxt routes
})
}

There are way more hooks and possibilities for modules. Please read the Nuxt Internals to find out more about the nuxt-internal API.

Publishing your module


module.exports.meta : This line is required if you are publishing the module as an npm package. Nuxt internally uses meta to work
better with your package.

modules/myModule.js
module.exports.meta = require('./package.json')

buildModules
Some modules are only imported during development and build time. Using  buildModules  helps to make production startup faster
and also significantly decrease the size of your  node_modules  for production deployments. Please refer to the docs for each module
to see if it is recommended to use  modules  or  buildModules .

The usage difference is:


Instead of adding to  modules  inside  nuxt.config.js , use  buildModules

nuxt.config.js
export default {
buildModules: ['@nuxtjs/eslint-module']
}

Instead of adding to  dependencies  inside  package.json , use  devDependencies

Yarn npm

yarn add -D @nuxtjs/eslint-module

If you are a module author, It is highly recommended to suggest to users to install your package as a  devDependency  and use
  buildModules  instead of  modules  for  nuxt.config.js .

Your module is a  buildModule  unless:

It is providing a serverMiddleware

It has to register a Node.js runtime hook (Like sentry)

It is affecting vue-renderer behavior or using a hook from  server:  or  vue-renderer:  namespace

Anything else that is outside of webpack scope (Hint: plugins and templates are compiled and are in webpack scope)

 
If you are going to offer using  buildModules  please mention that this feature is only available since Nuxt v2.9. Older users should upgrade
Nuxt or use the  modules  section.
middleware pages
pages
The  pages  directory contains your application views and routes. Nuxt.js reads all the  .vue  files inside this directory and
automatically creates the router configuration for you.

You can also create routes with .js files and .ts files

Every Page component is a Vue component but Nuxt.js adds special attributes and functions to make the development of your
universal application as easy as possible.

<template>
<h1 class="red">Hello {{ name }}!</h1>
</template>

<script>
export default {
// page properties go here
}
</script>

<style>
.red {
color: red;
}
</style>
Dynamic Pages
Dynamic pages can be created when you don't know the name of the page due to it coming from an API or you don't want to have
to create the same page over and over again. To create a dynamic page you need to add an underscore before the .vue file name or
before the the name of the directory, if you want the directory to be dynamic. You can name the file or directory anything you want
but you must prefix it with an underscore.

If you've defined a file named  _slug.vue  in your pages folder, you can access the value using the context with params.slug

pages/_slug.vue
<template>
<h1>{{ this.slug }}</h1>
</template>

<script>
export default {
async asyncData({ params }) {
const slug = params.slug // When calling /abc the slug will be "abc"
return { slug }
}
}
</script>

If you've defined a file named _slug.vue inside a folder called _book you can access the value using the context with params.slug and
params.book

pages/_book/_slug.vue
<template>
<h1>{{ this.book }} / {{ this.slug }}</h1>
</template>
<script>
export default {
async asyncData({ params }) {
const book = params.book
const slug = params.slug
return { book, slug }
}
}
</script>

Properties

asyncData
asyncData is called every time before loading the component. It can be asynchronous and receives the context as an argument. The
returned object will be merged with your data object.

pages/index.vue
export default {
asyncData(context) {
return { name: 'World' }
}
}

See more on how asyncData works in our Data Fetching chapter


fetch
Every time you need to get asynchronous data you can use fetch. Fetch is called on server-side when rendering the route, and on
client-side when navigating.

<script>
export default {
data() {
return {
posts: []
}
},
async fetch() {
this.posts = await fetch('https://api.nuxtjs.dev/posts').then(res =>
res.json()
)
}
}
</script>

See more on how fetch works in our Data Fetching chapter

head
Set specific  tags for the current page. Nuxt.js uses  vue-meta  to update the document head and meta attributes of your application.
pages/index.vue
export default {
head() {
// Set Meta Tags for this Page
}
}

See more in our Meta Tags and SEO chapter

layout
Specify a layout defined in the layouts directory.

pages/index.vue
export default {
layout: 'blog'
}

See more on layouts in our Views chapter.

loading
If set to false, prevents a page from automatically calling  this.$nuxt.$loading.finish()  as you enter it
and  this.$nuxt.$loading.start()  as you leave it, allowing you to manually control the behavior, as this example shows.
pages/index.vue
export default {
loading: false
}

Only applies if loading is also set in nuxt.config.js.

See more in our Loading chapter.

transition
Defines a specific transition for the page.

pages/index.vue
export default {
transition: 'fade'
}

See more on transitions in our Transitions chapter

scrollToTop
The  scrollToTop  property lets you tell Nuxt.js to scroll to the top before rendering the page. By default, Nuxt.js scrolls to the top
when you go to another page, but with child routes, Nuxt.js keeps the scroll position. If you want to tell Nuxt.js to scroll to the top
when rendering your child route, set  scrollToTop  to  true
pages/index.vue
export default {
scrollToTop: true
}

Conversely, you can manually set  scrollToTop  to  false  on parent routes as well.

If you want to overwrite the default scroll behavior of Nuxt.js, take a look at the scrollBehavior option.

middleware
Defines middleware for this page. The middleware will be called before rendering the page.

pages/index.vue
export default {
middleware: 'auth'
}

See more on middleware in our Middleware chapter

The watchQuery Property


Use the  watchQuery  key to set up a watcher for query strings. If the defined strings change, all component methods (asyncData,
fetch, validate, layout, ...) will be called. Watching is disabled by default to improve performance.

pages/index.vue
export default {
watchQuery: ['page']
}
If you want to set up a watcher for all query strings, set  watchQuery  to  true .

pages/index.vue
export default {
watchQuery: true
}

You can also use the function  watchQuery(newQuery, oldQuery)  to have more refined watchers.

pages/index.vue
export default {
watchQuery(newQuery, oldQuery) {
// Only execute component methods if the old query string contained `bar`
// and the new query string contains `foo`
return newQuery.foo && oldQuery.bar
}
}

See more on the watch query property in our Data Fetching chapter

Ignoring pages
If you want to ignore pages so that they are not included in the generated  router.js  file then you can ignore them by prefixing
them with a  - .

For example,  pages/-about.vue  will be ignored.


Checkout the ignore option to learn more about it.

Configuration
You can rename the  pages/  directory to something different by setting  dir.pages  option:

nuxt.config.js
export default {
dir: {
// Rename `pages` directory to `routes`
pages: 'routes'
}
}

Checkout the dir option to learn more about it.

modules plugins
plugins
Nuxt Plugins Nuxt v2.14.1
August 2020
3 ways to extend functionalities of
$root refers
Nuxt app using plugins
to root
Vue instance.

1 //plugins/hello.js
make functions or export default (context, inject) =>
values available injected in {
on client-side and $root & context inject('hello', msg => console.log(msg))
}
server-side
access hello on:
client-side: this.$hello('mounted')
server-side: $hello('asyncData') context refers to
2 Nuxt context. You can
use Vue plugins //plugins/vue-tooltip.js access keys like
in your import Vue from 'vue' app, store, etc. And 
Vue plugin
Nuxt application import VTooltip from 'v-tooltip' inject is a method:
Vue.use(VTooltip) inject(key, value)

3 // plugins/axios.js
use external
External export default function ({ $axios, redirect }) {
packages/modules packages or $axios.onError(error => {
in your Nuxt modules if(error.response.status === 404) {
application redirect('/sorry')
}
})
}

Include Nuxt plugin using plugins property Only in client-side


Only in server-side
type: array Both client & server
// nuxt.config.js
export default {
plugins: [
Array of {src:'~/plugins/vue-tooltip.js', mode:'client'},
objects {src:'~/plugins/bar.js', mode:'server'},
{src:'~/plugins/axios.js'}
]
}
If plugin
// nuxt.config.js exports ES6
export default { module,use
plugins: [ transpile build
option!
'~/plugins/vue-tooltip.client.js',
Array of
strings '~/plugins/bar.server.js',
module.exports = {
'~/plugins/axios.js' build: {
] transpile:['vue-tooltip']
} }
}

The  plugins  directory contains JavaScript plugins that you want to run before instantiating the root Vue.js Application. This is the
place to add Vue plugins and to inject functions or constants. Every time you need to use  Vue.use() , you should create a file
in  plugins/  and add its path to  plugins  in  nuxt.config.js .

External Packages
You may want to use external packages/modules in your application (one great example is axios) for making HTTP requests for both
server and client.
First, install it via npm or Yarn.

Yarn npm

yarn add @nuxtjs/axios

You can configure for example the axios interceptors to react on possible errors from your API calls across the application. In this
example we redirect the user to a custom error page called sorry when we get a 500 status error from our API.

plugins/axios.js
export default function ({ $axios, redirect }) {
$axios.onError(error => {
if (error.response.status === 500) {
redirect('/sorry')
}
})
}

Last but not least, add the module and the newly created plugin to the project configuration.

nuxt.config.js
module.exports = {
modules: ['@nuxtjs/axios'],
plugins: ['~/plugins/axios.js']
}

Then we can use it directly in your page components:

pages/index.vue
<template>
<h1>{{ post.title }}</h1>
</template>

<script>
export default {
async asyncData ({ $axios, params }) {
const post = await $axios.$get(`https://api.nuxtjs.dev/posts/${params.id}`)
return { post }
}
}
</script>

Another way to use  axios  without installing the module is by importing  axios direct in the  <script>  tag.

pages/index.vue
<script>
import axios from 'axios'

export default {
async asyncData ({ params }) {
const { data: post } = await axios.get(`https://api.nuxtjs.dev/posts/${params.id}`)
return { post }
}
}
</script>

If you get an Cannot use import statement outside a module error, you may need to add your package to the  build  >  transpile  option
in  nuxt.config.js  for webpack loader to make your plugin available.
nuxt.config.js
build: {
// You can extend webpack config here
transpile: ['npm-package-name'],
},

Vue Plugins
If we want to use Vue plugins, like v-tooltip to display tooltips in your application, we need to setup the plugin before launching the
app.

First we need to install it

Yarn npm

yarn add v-tooltip

Then we create the file  plugins/vue-tooltip.js

plugins/vue-tooltip.js
import Vue from 'vue'
import VTooltip from 'v-tooltip'

Vue.use(VTooltip)

The plugins Property


Then we add the file path inside the  plugins  key of our  nuxt.config.js . The plugins property lets you add Vue.js plugins easily to
your main application. All the paths defined in the  plugins  property will be imported before initializing the main application.

nuxt.config.js
export default {
plugins: ['~/plugins/vue-tooltip.js']
}

ES6 Plugins
If the plugin is located in  node_modules  and exports an ES6 module, you may need to add it to the  transpile  build option:

nuxt.config.js
module.exports = {
build: {
transpile: ['vue-tooltip']
}
}

You can refer to the configuration build docs for more build options.

Client or server side only


Some plugins might work only in the browser because they lack SSR support.

Name conventional plugin


If a plugin is assumed to be run only on client or server side,   .client.js   or  .server.js  can be applied as an extension of the
plugin file. The file will be automatically included only on the respective (client or server) side.

nuxt.config.js
export default {
plugins: [
'~/plugins/foo.client.js', // only in client side
'~/plugins/bar.server.js', // only in server side
'~/plugins/baz.js' // both client & server
]
}

Object syntax
You can also use the object syntax with the  mode  property ( 'client'   or  'server' ) in  plugins .

nuxt.config.js
export default {
plugins: [
{ src: '~/plugins/both-sides.js' },
{ src: '~/plugins/client-only.js', mode: 'client' }, // only on client side
{ src: '~/plugins/server-only.js', mode: 'server' } // only on server side
]
}

Inject in  $root  & context


Sometimes you want to make functions or values available across your app. You can inject those variables into Vue instances (client
side), the context (server side) and even in the Vuex store. It is a convention to prefix those functions with a  $ .

Nuxt.js provides you with an  inject(key, value)  method to do this easily. Inject is given as the second parameter when exporting a
function. The  $  will be prepended automatically to the key.

It is important to know that in any Vue instance lifecycle, only   beforeCreate  and  created  hooks are called both, from client-side and server-
side. All other hooks are called only from the client-side.

plugins/hello.js
export default ({ app }, inject) => {
// Inject $hello(msg) in Vue, context and store.
inject('hello', msg => console.log(`Hello ${msg}!`))
}

nuxt.config.js
export default {
plugins: ['~/plugins/hello.js']
}

Now  $hello  service can be accessed from  context  and  this  in pages, components, plugins, and store actions.

example-component.vue
export default {
mounted() {
this.$hello('mounted')
// will console.log 'Hello mounted!'
},
asyncData({ app, $hello }) {
$hello('asyncData')
// If using Nuxt <= 2.12, use 👇
app.$hello('asyncData')
}
}

store/index.js
export const state = () => ({
someValue: ''
})

export const actions = {


setSomeValueToWhatever({ commit }) {
this.$hello('store action')
const newValue = 'whatever'
commit('changeSomeValue', newValue)
}
}

Don't use  Vue.use() ,  Vue.component() , and globally, don't plug anything in Vue inside this function, dedicated to Nuxt injection. It will
cause memory leak on server-side.

The extendPlugins Property


You may want to extend plugins or change the plugins order created by Nuxt.js. This function accepts an array of plugin objects and
should return an array of plugin objects.

Example of changing plugins order:


nuxt.config.js
export default {
extendPlugins(plugins) {
const pluginIndex = plugins.findIndex(
({ src }) => src === '~/plugins/shouldBeFirst.js'
)
const shouldBeFirstPlugin = plugins[pluginIndex]

plugins.splice(pluginIndex, 1)
plugins.unshift(shouldBeFirstPlugin)

return plugins
}
}

Global mixins
Global mixins can be easily added with Nuxt plugins but can cause trouble and memory leaks when not handled correctly. Whenever
you add a global mixin to your application, you should use a flag to avoid registering it multiple times:

plugins/my-mixin-plugin.js
import Vue from "vue"

// Make sure to pick a unique name for the flag


// so it won't conflict with any other mixin.
if (!Vue.__my_mixin__) {
Vue.__my_mixin__ = true
Vue.mixin({ ... }) // Set up your mixin then
}
pages static
static
The  static  directory is directly mapped to the server root and contains files that likely won't be changed. All included files will be
automatically served by Nuxt and are accessible through your project root URL.

/static/robots.txt  will be available at  http://localhost:3000/robots.txt

/static/favicon.ico  will be available at   http://localhost:3000/favicon.ico

This option is helpful for files like  robots.txt ,  sitemap.xml  or  CNAME  (which is important for GitHub Pages deployment).

This directory cannot be renamed without extra configuration.

Static Assets
If you don't want to use Webpack assets from the  assets  directory, you can add the images to the static directory.

In your code, you can then reference these files relative to the root ( / ):

<!-- Static image from static directory -->


<img src="/my-image.png" />

<!-- webpacked image from assets directory -->


<img src="~/assets/my-image-2.png" />

Nuxt doesn't change this path, so if you customize your  router.base  then you'll need to make sure to add that manually to your paths. For
example:
<img :src="`${yourPrefix}/my-image.png`" />

Static Directory Config


Should you need to you can configure the  static/  directory behavior in the  nuxt.config.js  file.

Static asset Prefix


If you deploy Nuxt.js to a subfolder, e.g.  /blog/ , the router base will be added to the static asset path by default. If you want to
disable this behavior, you can set  static.prefix  to false in the  nuxt.config.js .

export default {
static: {
prefix: false
}
}

Default:  /blog/my-image.png

With  static.prefix  disabled:  /my-image.png

plugins store
store
The  store  directory contains your Vuex Store files. The Vuex Store comes with Nuxt.js out of the box but is disabled by default.
Creating an   index.js   file in this directory enables the store.

This directory cannot be renamed without extra configuration.

Using a store to manage the state is important for every big application. That's why Nuxt.js implements Vuex in its core.

Activate the Store


Nuxt.js will look for the  store  directory. If it contains a file, that isn't a hidden file or a  README.md  file, then the store will be
activated. This means that Nuxt will:

. Import Vuex,

. Add the  store  option to the root Vue instance.

Modules
Every  .js  file inside the  store  directory is transformed as a namespaced module ( index  being the root module). Your  state  value
should always be a  function  to avoid unwanted shared state on the server side.

To get started, export the state as a function, and the mutations and actions as objects.
store/index.js
export const state = () => ({
counter: 0
})

export const mutations = {


increment(state) {
state.counter++
}
}

Then, you can have a  store/todos.js  file:

store/todos.js
export const state = () => ({
list: []
})

export const mutations = {


add(state, text) {
state.list.push({
text,
done: false
})
},
remove(state, { todo }) {
state.list.splice(state.list.indexOf(todo), 1)
},
toggle(state, todo) {
todo.done = !todo.done
}
}

The store will be created as such:

new Vuex.Store({
state: () => ({
counter: 0
}),
mutations: {
increment(state) {
state.counter++
}
},
modules: {
todos: {
namespaced: true,
state: () => ({
list: []
}),
mutations: {
add(state, { text }) {
state.list.push({
text,
done: false
})
},
remove(state, { todo }) {
state.list.splice(state.list.indexOf(todo), 1)
},
toggle(state, { todo }) {
todo.done = !todo.done
}
}
}
}
})

And in your  pages/todos.vue , using the  todos  module:

pages/todos.vue
<template>
<ul>
<li v-for="todo in todos" :key="todo.text">
<input :checked="todo.done" @change="toggle(todo)" type="checkbox">
<span :class="{ done: todo.done }">{{ todo.text }}</span>
</li>
<li><input @keyup.enter="addTodo" placeholder="What needs to be done?"></li>
</ul>
</template>

<script>
import { mapMutations } from 'vuex'

export default {
computed: {
todos () {
return this.$store.state.todos.list
}
},
methods: {
addTodo (e) {
this.$store.commit('todos/add', e.target.value)
e.target.value = ''
},
...mapMutations({
toggle: 'todos/toggle'
})
}
}
</script>

<style>
.done {
text-decoration: line-through;
}
</style>

The module method also works for top-level definitions without implementing a sub-directory in the store directory.

Example for state: you create a file  store/state.js  and add the following.

export default () => ({


counter: 0
})

And the corresponding mutations can be in the file   store/mutations.js

store/mutations.js
export default {
increment(state) {
state.counter++
}
}

Example folder structure


A complex store setup file/folder structure might look like this:

store/
--| index.js
--| ui.js
--| shop/
----| cart/
------| actions.js
------| getters.js
------| mutations.js
------| state.js
----| products/
------| mutations.js
------| state.js
------| itemsGroup1/
--------| state.js

Plugins in the Store


You can add additional plugins to the store by putting them into the  store/index.js  file:
store/index.js
import myPlugin from 'myPlugin'

export const plugins = [myPlugin]

export const state = () => ({


counter: 0
})

export const mutations = {


increment(state) {
state.counter++
}
}

More information about the plugins: Vuex documentation.

The nuxtServerInit Action


If the action  nuxtServerInit  is defined in the store and the mode is  universal , Nuxt.js will call it with the context (only from the
server-side). It's useful when we have some data on the server we want to give directly to the client-side.

For example, let's say we have sessions on the server-side and we can access the connected user through  req.session.user . To give
the authenticated user to our store, we update our  store/index.js  to the following:

store/index.js
actions: {
nuxtServerInit ({ commit }, { req }) {
if (req.session.user) {
commit('user', req.session.user)
}
}
}

Only the primary module (in  store/index.js ) will receive this action. You'll need to chain your module actions from there.

The context is given to  nuxtServerInit  as the 2nd argument in the  asyncData  method.

If  nuxt generate  is ran,  nuxtServerInit  will be executed for every dynamic route generated.

Asynchronous  nuxtServerInit  actions must return a Promise or leverage async/await to allow the nuxt server to wait on them.

store/index.js
actions: {
async nuxtServerInit({ dispatch }) {
await dispatch('core/load')
}
}

Vuex Strict Mode


Strict mode is enabled by default on dev mode and turned off in production mode. To disable strict mode in dev, follow the below
example in  store/index.js :

export const strict = false


static nuxt.config
nuxt.config
By default, Nuxt.js is configured to cover most use cases. This default configuration can be overwritten with the nuxt.config.js file.

nuxt.config.js

alias
This option lets you define aliases that will be available within your JavaScript and CSS.

nuxt.config.js
import { resolve } from 'path'

export default {
alias: {
'style': resolve(__dirname, './assets/style')
}
}

See more on the alias property

build
This option lets you configure various settings for the  build  step, including  loaders ,  filenames , the  webpack  config
and  transpilation .
nuxt.config.js
export default {
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {}
}
}

See more on the build property

css
This option lets you define the CSS files, modules, and libraries you want to include globally (on every page).

nuxt.config.js
export default {
css: ['~/assets/css/main.css', '~/assets/css/animations.scss']
}

You can omit the file extension for CSS, SCSS, Postcss, Less, Stylus, ... files listed in the css array in your nuxt config file.

nuxt.config.js
export default {
css: ['~/assets/css/main', '~/assets/css/animations']
}
By omitting the extension, if you have a css file and decide to change to use sass for example, you won't have to update your
nuxt.config as it will use the new extension once the filename remains the same.

See more on the css property

dev
This option lets you define the  development  or  production  mode of Nuxt.js (important when you use Nuxt.js programmatically)

nuxt.config.js
export default {
dev: process.env.NODE_ENV !== 'production'
}

See more on the dev property

env
This option lets you define environment variables that are required at build time (rather than runtime) such
as  NODE_ENV=staging  or  VERSION=1.2.3 . However, for runtime environment variables  runtimeConfig  is required.

nuxt.config.js
export default {
env: {
baseURL: process.env.BASE_URL
}
}
runtimeConfig
The runtime config has built-in dotenv support for better security and faster development. The runtime config is added to the Nuxt
payload so there is no need to rebuild in order to update the runtime configuration when working in development or with server-
side rendering or client-side only applications. (For static sites you will still need to regenerate your site to see changes.)

.env  support

If you have a  .env  file in your project root directory, it will be automatically loaded into  process.env  and accessible within
your  nuxt.config / serverMiddleware  and any other files they import.

You can customize the path by using  --dotenv <file>  or disable entirely with  --dotenv false . For example, you might specify a
different  .env  file in production, staging or development environments.

publicRuntimeConfig

should hold all env variables that are public as these will be exposed on the frontend. This could include a reference to your
public URL for example.

is available using  $config  in both server and client.

nuxt.config.js
export default {
publicRuntimeConfig: {
baseURL: process.env.BASE_URL || 'https://nuxtjs.org'
}
}

privateRuntimeConfig
should hold all env variables that are private and that should not be exposed on the frontend. This could include a reference to
your API secret tokens for example.

is only available on server using same  $config  (it overrides publicRuntimeConfig)

nuxt.config.js
export default {
privateRuntimeConfig: {
apiSecret: process.env.API_SECRET
}
}

Using your config values:

You can then access these values anywhere by using the context in your pages, store, components and plugins by
using  this.$config  or  context.$config .

pages/index.vue
<script>
asyncData ({ $config: { baseURL } }) {
const posts = await fetch(`${baseURL}/posts`)
.then(res => res.json())
}
</script>

Inside your templates you can access your runtimeConfigs directly using  $config.*

pages/index.vue
<template>
<p>Our Url is: {{ $config.baseURL}}</p>
</template>

Your private config could be exposed if you use  $config  outside of a server-only context (for example, if you
use  $config  in  fetch ,  asyncData  or directly inside your template).

See more on the runtimeConfig

See our blog post on Moving from @nuxtjs/dotenv to runtime config

See more on the env property

generate
This option lets you set up parameter values for every dynamic route in your application that will be transformed into HTML files by
Nuxt.js.

nuxt.config.js
export default {
generate: {
dir: 'gh_pages', // gh_pages/ instead of dist/
subFolders: false // HTML files are generated according to the route path
}
}
See more on the generate property

head

nuxt.config.js
export default {
head: {
title: 'my title',
meta: [
{ charset: 'utf-8' },
.....
]
}
}

This option lets you define all default meta tags for your application.

See more on head integration

loading
This option lets you customize the loading component that Nuxt.js uses by default.

nuxt.config.js
export default {
loading: {
color: '#fff'
}
}

See more on loading integration

modules
With this option you can add Nuxt.js modules to your project.

nuxt.config.js
export default {
modules: ['@nuxtjs/axios']
}

See more on the modules property

modulesDir
The modulesDir property is used to set the modules directories for path resolving. For example:
Webpack's resolveLoading, nodeExternals and postcss. The configuration path is relative to  options.rootDir  (default: process.cwd()).

nuxt.config.js
export default {
modulesDir: ['../../node_modules']
}

Setting this field may be necessary if your project is organized as a Yarn workspace-styled mono-repository.
See more on the modulesDir property

plugins
This option lets you define JavaScript plugins that should be run before instantiating the root Vue.js application.

nuxt.config.js
export default {
plugins: ['~/plugins/url-helpers.js']
}

See more on the plugins property

router
With the  router  option you can overwrite the default Nuxt.js configuration of Vue Router.

nuxt.config.js
export default {
router: {
linkExactActiveClass: 'text-primary'
}
}

See more on the router property


server
This option lets you configure the connection variables for the server instance of your Nuxt.js application.

nuxt.config.js
import path from 'path'
import fs from 'fs'

export default {
server: {
https: {
key: fs.readFileSync(path.resolve(__dirname, 'server.key')),
cert: fs.readFileSync(path.resolve(__dirname, 'server.crt'))
}
}
}

See more on the server property

srcDir
This option lets you define the source directory of your Nuxt.js application.

nuxt.config.js
export default {
srcDir: 'client/'
}

Project structure example with your Nuxt.js application in the  client  directory.
**-| app/
---| node_modules/
---| nuxt.config.js
---| package.json
---| client/
------| assets/
------| components/
------| layouts/
------| middleware/
------| pages/
------| plugins/
------| static/
------| store/**

dir
This option lets you define custom names of your Nuxt.js directories.

nuxt.config.js
export default {
pages: 'views' // Nuxt will look for the views/ instead of the pages/ folder
}

See more on the dir property

pageTransition
This option lets you define the default properties of the page transitions.

nuxt.config.js
export default {
pageTransition: 'page'
}

See more on the transition property

Other configuration files


Besides the  nuxt.config.js  there might be other config files in your project root, such as .eslintrc, prettier.config.json or .gitignore.
These are used to configure other tools such as your linter, code formatter or your git repository and detached from
the  nuxt.config.js .

.gitignore
In your .gitignore file you will need to add the following so that they are ignored and not added to version
control.  node_modules  which is where all your installed modules are. The  nuxt  folder which is what gets created when running the
dev or build commands. The  dist  folder is the folder that gets created when running the generate command.

.gitignore
node_modules .nuxt dist

What's next
Check out the configuration-glossary

store  
The alias Property
Nuxt.js allows you to use aliases to access custom directories within your JavaScript and CSS.

Type:  Object

Default:

{
'~~': `<rootDir>`,
'@@': `<rootDir>`,
'~': `<srcDir>`,
'@': `<srcDir>`,
'assets': `<srcDir>/assets`, // (unless you have set a custom `dir.assets`)
'static': `<srcDir>/static`, // (unless you have set a custom `dir.static`)
}

This option lets you define aliases to directories within your project (in addition to the ones above). These aliases can be used within
your JavaScript and CSS.

nuxt.config.js
import { resolve } from 'path'
export default {
alias: {
'images': resolve(__dirname, './assets/images'),
'style': resolve(__dirname, './assets/style'),
'data': resolve(__dirname, './assets/other/data')
}
}
components/example.vue
<template>
<img src="~images/main-bg.jpg">
</template>

<script>
import data from 'data/test.json'

// etc.
</script>

<style>
@import '~style/variables.scss';
@import '~style/utils.scss';
@import '~style/base.scss';

body {
background-image: url('~images/main-bg.jpg');
}
</style>

Within a Webpack context (image sources, CSS - but not JavaScript) you must prefix your alias with  ~  (as in the example above).

If you are using TypeScript and want to use the alias you define within your TypeScript files, you will need to add the aliases to
your  paths  object within tsconfig.json  .

  build
Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The build Property
Nuxt.js lets you customize the webpack configuration for building your web application as you want.

analyze
Nuxt.js use webpack-bundle-analyzer to let you visualize your bundles and how to optimize them.

Type:  Boolean  or  Object

Default:  false

If an object, see available properties here.

nuxt.config.js
export default {
build: {
analyze: true,
// or
analyze: {
analyzerMode: 'static'
}
}
}

Info: you can use the command  yarn nuxt build --analyze  or  yarn nuxt build -a  to build your application and launch the bundle
analyzer on http://localhost:8888. If you are not using  yarn  you can run the command with  npx .
corejs
As of Nuxt@2.14 Nuxt automatically detects the current version of  core-js  in your project, also you can specify which version you
want to use.

Type:  number  |  string  (Valid values are  'auto' ,  2  and  3 )

Default:  'auto'

babel
Customize Babel configuration for JavaScript and Vue files.  .babelrc  is ignored by default.

Type:  Object

See  babel-loader  options and  babel  options

Default:

{
babelrc: false,
cacheDirectory: undefined,
presets: ['@nuxt/babel-preset-app']
}

The default targets of @nuxt/babel-preset-app are  ie: '9'  in the  client  build, and  node: 'current'  in the  server  build.
presets

Type:  Function

Argument:

. Object : { isServer: true | false }

. Array :

preset name  @nuxt/babel-preset-app

options  of  @nuxt/babel-preset-app

Note: The presets configured in  build.babel.presets  will be applied to both, the client and the server build. The target will be set
by Nuxt accordingly (client/server). If you want configure the preset differently for the client or the server build, please
use  presets  as a function:

We highly recommend to use the default preset instead of below customization

export default {
build: {
babel: {
presets({ isServer }, [ preset, options ]) {
// change options directly
options.targets = isServer ? ... : ...
options.corejs = ...
// return nothing
}
}
}
}
Or override default value by returning whole presets list:

export default {
build: {
babel: {
presets({ isServer }, [preset, options]) {
return [
[
preset,
{
targets: isServer ? ... : ...,
...options
}
],
[
// Other presets
]
]
}
}
}
}

cache
Type:  Boolean
Default:  false

⚠ Experimental

Enable cache of terser-webpack-plugin and cache-loader

cssSourceMap
Type:  boolean

Default:  true  for dev and  false  for production.

Enables CSS Source Map support

devMiddleware
Type:  Object

See webpack-dev-middleware for available options.

devtools
Type:  boolean

Default:  false

Configure whether to allow vue-devtools inspection.

If you already activated through nuxt.config.js or otherwise, devtools enable regardless of the flag.
extend
Extend the webpack configuration manually for the client & server bundles.

Type:  Function

The extend is called twice, one time for the server bundle, and one time for the client bundle. The arguments of the method are:

. The Webpack config object,

. An object with the following keys (all boolean except  loaders ):  isDev ,  isClient ,  isServer ,  loaders .

Warning: The  isClient  and  isServer  keys provided in are separate from the keys available in  context . They are not deprecated. Do not
use  process.client and  process.server  here as they are  undefined  at this point.

nuxt.config.js
export default {
build: {
extend(config, { isClient }) {
// Extend only webpack config for client-bundle
if (isClient) {
config.devtool = 'source-map'
}
}
}
}

If you want to see more about our default webpack configuration, take a look at our webpack directory.
loaders in extend
loaders  has the same object structure as build.loaders, so you can change the options of loaders inside  extend .

nuxt.config.js
export default {
build: {
extend(config, { isClient, loaders: { vue } }) {
// Extend only webpack config for client-bundle
if (isClient) {
vue.transformAssetUrls.video = ['src', 'poster']
}
}
}
}

extractCSS
Enables Common CSS Extraction using Vue Server Renderer guidelines.

Type:  Boolean  or  Object

Default:  false

Using  extract-css-chunks-webpack-plugin  under the hood, all your CSS will be extracted into separate files, usually one per
component. This allows caching your CSS and JavaScript separately and is worth a try in case you have a lot of global or shared CSS.

Example ( nuxt.config.js ):
export default {
build: {
extractCSS: true,
// or
extractCSS: {
ignoreOrder: true
}
}
}

Note: There was a bug prior to Vue 2.5.18 that removed critical CSS imports when using this options.

You may want to extract all your CSS to a single file. There is a workaround for this:

It is not recommended to extract everything into a single file. Extracting into multiple CSS files is better for caching and preload isolation. It can
also improve page performance by downloading and resolving only those resources that are needed.

export default {
build: {
extractCSS: true,
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.(css|vue)$/,
chunks: 'all',
enforce: true
}
}
}
}
}
}

filenames
Customize bundle filenames.

Type:  Object

Default:

{
app: ({ isDev, isModern }) => isDev ? `[name]${isModern ? '.modern' : ''}.js` : `[contenthash:7]${isModern ? '.modern' :
chunk: ({ isDev, isModern }) => isDev ? `[name]${isModern ? '.modern' : ''}.js` : `[contenthash:7]${isModern ? '.modern'
css: ({ isDev }) => isDev ? '[name].css' : 'css/[contenthash:7].css',
img: ({ isDev }) => isDev ? '[path][name].[ext]' : 'img/[name].[contenthash:7].[ext]',
font: ({ isDev }) => isDev ? '[path][name].[ext]' : 'fonts/[name].[contenthash:7].[ext]',
video: ({ isDev }) => isDev ? '[path][name].[ext]' : 'videos/[name].[contenthash:7].[ext]'
}
This example changes fancy chunk names to numerical ids:

nuxt.config.js
export default {
build: {
filenames: {
chunk: ({ isDev }) => (isDev ? '[name].js' : '[id].[contenthash].js')
}
}
}

To understand a bit more about the use of manifests, take a look at this webpack documentation.

Be careful when using non-hashed based filenames in production as most browsers will cache the asset and not detect the changes on first load.

friendlyErrors
Type:  Boolean

Default:  true  (Overlay enabled)

Enables or disables the overlay provided by FriendlyErrorsWebpackPlugin

hardSource
Type:  Boolean

Default:  false
⚠ Experimental

Enables the HardSourceWebpackPlugin for improved caching

hotMiddleware
Type:  Object

See webpack-hot-middleware for available options.

html.minify
Type:  Object

Default:

{
collapseBooleanAttributes: true,
decodeEntities: true,
minifyCSS: true,
minifyJS: true,
processConditionalComments: true,
removeEmptyAttributes: true,
removeRedundantAttributes: true,
trimCustomFragments: true,
useShortDoctype: true
}
Attention: If you make changes to  html.minify , they won't be merged with the defaults!

Configuration for the html-minifier plugin used to minify HTML files created during the build process (will be applied for all modes).

indicator
Display build indicator for hot module replacement in development (available in  v2.8.0+ )

Type:  Boolean

Default:  true

loaders
Customize options of Nuxt.js integrated webpack loaders.

Type:  Object

Default:

{
file: {},
fontUrl: { limit: 1000 },
imgUrl: { limit: 1000 },
pugPlain: {},
vue: {
transformAssetUrls: {
video: 'src',
source: 'src',
object: 'src',
embed: 'src'
}
},
css: {},
cssModules: {
localIdentName: '[local]_[hash:base64:5]'
},
less: {},
sass: {
indentedSyntax: true
},
scss: {},
stylus: {},
vueStyle: {}
}

Note: In addition to specifying the configurations in  nuxt.config.js , it can also be modified by build.extend

loaders.file
More details are in file-loader options.
loaders.fontUrl and loaders.imgUrl
More details are in url-loader options.

loaders.pugPlain
More details are in pug-plain-loader or Pug compiler options.

loaders.vue
More details are in vue-loader options.

loaders.css and loaders.cssModules


More details are in css-loader options. Note: cssModules is loader options for usage of CSS Modules

loaders.less
You can pass any Less specific options to the  less-loader  via  loaders.less . See the Less documentation for all available options in
dash-case.

loaders.sass and loaders.scss


See the Sass documentation for all available Sass options. Note:  loaders.sass  is for Sass Indented Syntax

loaders.vueStyle
More details are in vue-style-loader options.

optimization
Type:  Object

Default:

{
minimize: true,
minimizer: [
// terser-webpack-plugin
// optimize-css-assets-webpack-plugin
],
splitChunks: {
chunks: 'all',
automaticNameDelimiter: '.',
name: undefined,
cacheGroups: {}
}
}

The default value of  splitChunks.name  is  true  in  dev  or  analyze  mode.

You can set  minimizer  to a customized Array of plugins or set  minimize  to  false to disable all minimizers. ( minimize  is being
disabled for development by default)
See Webpack Optimization.

optimizeCSS
Type:  Object  or  Boolean

Default:

false

{}  when extractCSS is enabled

OptimizeCSSAssets plugin options.

See NMFR/optimize-css-assets-webpack-plugin.

parallel
Type:  Boolean

Default:  false

⚠ Experimental

Enable thread-loader in webpack building

plugins
Add webpack plugins
Type:  Array

Default:  []

nuxt.config.js
import webpack from 'webpack'
import { version } from './package.json'
export default {
build: {
plugins: [
new webpack.DefinePlugin({
'process.VERSION': version
})
]
}
}

postcss
Customize PostCSS Loader plugins.

Type:  Array  (legacy, will override defaults),  Object  (recommended),  Function or  Boolean

Note: Nuxt.js has applied PostCSS Preset Env. By default it enables Stage 2 features and Autoprefixer, you can
use  build.postcss.preset  to configure it.

Default:
nuxt.config.js
{
plugins: {
'postcss-import': {},
'postcss-url': {},
'postcss-preset-env': this.preset,
'cssnano': { preset: 'default' } // disabled in dev mode
},
order: 'presetEnvAndCssnanoLast',
preset: {
stage: 2
}
}

Your custom plugin settings will be merged with the default plugins (unless you are using an  Array  instead of an  Object ).

nuxt.config.js
export default {
build: {
postcss: {
plugins: {
// Disable `postcss-url`
'postcss-url': false,
// Add some plugins
'postcss-nested': {},
'postcss-responsive-type': {},
'postcss-hexrgba': {}
},
preset: {
autoprefixer: {
grid: true
}
}
}
}
}

If the postcss configuration is an  Object ,  order  can be used for defining the plugin order:

Type:  Array  (ordered plugin names),  String  (order preset name),  Function

Default:  cssnanoLast  (put  cssnano  in last)

nuxt.config.js
export default {
build: {
postcss: {
// preset name
order: 'cssnanoLast',
// ordered plugin names
order: ['postcss-import', 'postcss-preset-env', 'cssnano']
// Function to calculate plugin order
order: (names, presets) => presets.cssnanoLast(names)
}
}
}

postcss plugins & @nuxtjs/tailwindcss


If you want to apply a postcss plugin (e.g. postcss-pxtorem) on the @nuxtjs/tailwindcss configuration, you have to change order and
load tailwindcss first.

This setup has no impact on nuxt-purgecss.

nuxt.config.js
import { join } from 'path'

export default {
// ...
build: {
postcss: {
plugins: {
tailwindcss: join(__dirname, 'tailwind.config.js'),
'postcss-pxtorem': {
propList: ['*', '!border*']
}
}
}
}
}

profile
Type:  Boolean

Default: enabled by command line argument  --profile

Enable the profiler in WebpackBar


publicPath
Nuxt.js lets you upload your dist files to your CDN for maximum performances, simply set the  publicPath  to your CDN.

Type:  String

Default:  '/_nuxt/'

nuxt.config.js
export default {
build: {
publicPath: 'https://cdn.nuxtjs.org'
}
}

Then, when launching  nuxt build , upload the content of  .nuxt/dist/client directory to your CDN and voilà!

In Nuxt 2.15+, changing the value of this property at runtime will override the configuration of an app that has already been built.

quiet
Suppresses most of the build output log

Type:  Boolean

Default: Enabled when a  CI  or  test  environment is detected by std-env

splitChunks
Type:  Object

Default:

nuxt.config.js
export default {
build: {
splitChunks: {
layouts: false,
pages: true,
commons: true
}
}
}

If split codes for  layout ,  pages  and  commons  (common libs: vue|vue-loader|vue-router|vuex...).

ssr
Creates special webpack bundle for SSR renderer.

Type:  Boolean

Default:  true  for universal mode and  false  for spa mode

This option is automatically set based on  mode  value if not provided.
standalone
Inline server bundle dependencies (advanced)

Type:  Boolean

Default:  false

This mode bundles  node_modules  that are normally preserved as externals in the server build (more information).

* Warning : Runtime dependencies (modules,  nuxt.config  , server middleware and static directory) are not bundled. This feature only disables
use of webpack-externals for server-bundle.

Info: you can use the command  yarn nuxt build --standalone  to enable this mode on the command line. (If you are not using  yarn  you
can run the command with  npx  .)

styleResources
Type:  Object

Default:  {}

Warning: This property is deprecated. Please use the style-resources-moduleinstead for improved performance and better DX!

This is useful when you need to inject some variables and mixins in your pages without having to import them every time.

Nuxt.js uses https://github.com/yenshih/style-resources-loader to achieve this behavior.

You need to specify the patterns/path you want to include for the given pre-processors:  less ,  sass ,  scss  or  stylus
You cannot use path aliases here ( ~  and  @ ), you need to use relative or absolute paths.

nuxt.config.js
{
build: {
styleResources: {
scss: './assets/variables.scss',
less: './assets/*.less',
// sass: ...,
// scss: ...
options: {
// See https://github.com/yenshih/style-resources-loader#options
// Except `patterns` property
}
}
}
}

templates
Nuxt.js allows you provide your own templates which will be rendered based on Nuxt configuration. This feature is specially useful for
using with modules.

Type:  Array

nuxt.config.js
export default {
build: {
templates: [
{
src: '~/modules/support/plugin.js', // `src` can be absolute or relative
dst: 'support.js', // `dst` is relative to project `.nuxt` dir
options: {
// Options are provided to template as `options` key
live_chat: false
}
}
]
}
}

Templates are rendered using  lodash.template  you can learn more about using them here.

terser
Type:  Object  or  Boolean

Default:

nuxt.config.js
{
parallel: true,
cache: false,
sourceMap: false,
extractComments: {
filename: 'LICENSES'
},
terserOptions: {
output: {
comments: /^\**!|@preserve|@license|@cc_on/
}
}
}

Terser plugin options. Set to  false  to disable this plugin.

Enabling  sourceMap  will leave  //# sourceMappingURL  linking comment at the end of each output file if webpack  config.devtool  is
set to  source-map .

See webpack-contrib/terser-webpack-plugin.

transpile
Type:  Array<String | RegExp | Function>

Default:  []

If you want to transpile specific dependencies with Babel, you can add them in  build.transpile . Each item in transpile can be a
package name, a string or regex object matching the dependency's file name.

Starting with  v2.9.0 , you can also use a function to conditionally transpile, the function will receive a object ( { isDev, isServer,
isClient, isModern, isLegacy } ):

nuxt.config.js
{
build: {
transpile: [({ isLegacy }) => isLegacy && 'ky']
}
}
vueLoader
Note: This config has been removed since Nuxt 2.0, please use  build.loaders.vue instead.

Type:  Object

Default:

nuxt.config.js
{
productionMode: !this.options.dev,
transformAssetUrls: {
video: 'src',
source: 'src',
object: 'src',
embed: 'src'
}
}

Specify the Vue Loader Options.

watch
You can provide your custom files to watch and regenerate after changes. This feature is specially useful for using with modules.

Type:  Array<String>
nuxt.config.js
export default {
build: {
watch: ['~/.nuxt/support.js']
}
}

followSymlinks
By default, the build process does not scan files inside symlinks. This boolean includes them, thus allowing usage of symlinks inside
folders such as the "pages" folder, for example.

Type:  Boolean

nuxt.config.js
export default {
build: {
followSymlinks: true
}
}

alias buildDir

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The buildDir Property
Type:  String

Default:  .nuxt

Define the dist directory for your Nuxt.js application

nuxt.config.js
export default {
buildDir: 'nuxt-dist'
}

By default, many tools assume that  .nuxt  is a hidden directory, because its name starts with a dot. You can use this option to
prevent that.

build cli

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The cli Property
Nuxt.js lets you customize the CLI configuration.

badgeMessages
Type  Array

Add a message to the CLI banner.

nuxt.config.js
cli: {
badgeMessages: ['Hello World!']
}
bannerColor
Type:  String

Default:  'green'
Change the color of the 'Nuxt.js' title in the CLI banner.

Available colors:

black ,  red ,  green ,  yellow ,  blue ,  magenta ,  cyan ,  white ,  gray ,  redBright ,  greenBright ,  yellowBright ,  blueBright ,  magentaBright ,  cyanBright ,  whiteBright

nuxt.config.js
export default {
cli: {
bannerColor: 'yellow'
}
}

buildDir css

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The css Property
Nuxt.js lets you define the CSS files/modules/libraries you want to set globally (included in every page).

In case you want to use  sass  make sure that you have installed  sass  and  sass-loader  packages. If you didn't just

npm install --save-dev sass sass-loader@10 fibers

Synchronous compilation with  sass  (2x speed increase) is enabled automaticallywhen  fibers  is installed.

Type:  Array

Items:  string

nuxt.config.js
export default {
css: [
// Load a Node.js module directly (here it's a Sass file)
'bulma',
// CSS file in the project
'@/assets/css/main.css',
// SCSS file in the project
'@/assets/css/main.scss'
]
}
Nuxt.js will automatically guess the file type by its extension and use the appropriate pre-processor loader for webpack. You will still
need to install the required loader if you need to use them.

Style Extensions
You can omit the file extension for CSS/SCSS/Postcss/Less/Stylus/... files listed in the css array in your nuxt config file.

nuxt.config.js
export default {
css: ['~/assets/css/main', '~/assets/css/animations']
}

If you have two files with the same name e.g.  main.scss  and  main.css , and don't specify an extension in the css array entry, e.g.  css:
['~/assets/css/main'] , then only one file will be loaded depending on the order of  styleExtensions . In this case only the  css  file will be
loaded and the  scss file will be ignored because  css  comes first in the default  styleExtension  array.

Default order:  ['css', 'pcss', 'postcss', 'styl', 'stylus', 'scss', 'sass', 'less']

cli components

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The components Property
Nuxt.js 2.13+ can scan and auto import your components.

Type:  Boolean  or  Object

Default:  false

When set to  true  or using an object, it will include the nuxt/componentsdependencies and auto import your components (defined
in  ~/components ) when you use them in your templates.

Please refer to nuxt/components repository for usage and options.

css dev

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The dev Property
Type:  Boolean

Default:  true

Define the development or production mode of Nuxt.js.

This property is overwritten by the nuxt commands:

dev  is forced to  true  with  nuxt

dev  is forced to  false  with  nuxt build ,  nuxt start  and  nuxt generate

This property should be used when using Nuxt.js programmatically:

nuxt.config.js
export default {
dev: process.env.NODE_ENV !== 'production'
}

server.js
const { Nuxt, Builder } = require('nuxt')
const app = require('express')()
const port = process.env.PORT || 3000

// We instantiate Nuxt.js with the options


const config = require('./nuxt.config.js')
const nuxt = new Nuxt(config)
app.use(nuxt.render)
// Build only in dev mode
if (config.dev) {
new Builder(nuxt).build()
}

// Listen the server


app.listen(port, '0.0.0.0').then(() => {
console.log(`Server is listening on port: ${port}`)
})

package.json
{
"scripts": {
"dev": "node server.js",
"build": "nuxt build",
"start": "NODE_ENV=production node server.js"
}
}

components dir

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The dir Property
Type:  Object

Default:

{
assets: 'assets',
app: 'app',
layouts: 'layouts',
middleware: 'middleware',
pages: 'pages',
static: 'static',
store: 'store'
}

Define the custom directories for your Nuxt.js application

nuxt.config.js
export default {
dir: {
assets: 'custom-assets',
app: 'custom-app',
layouts: 'custom-layouts',
middleware: 'custom-middleware',
pages: 'custom-pages',
static: 'custom-static',
store: 'custom-store'
}
}

dev env

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The env Property
Type:  Object

Nuxt.js lets you create environment variables client side, also to be shared from server side.

The env property defines environment variables that should be available on the client side. They can be assigned using server side
environment variables, the dotenv module ones or similar.

Make sure to read about  process.env  and  process.env == {}  below for better troubleshooting.

nuxt.config.js
export default {
env: {
baseUrl: process.env.BASE_URL || 'http://localhost:3000'
}
}

This lets you create a  baseUrl  property that will be equal to the  BASE_URL  server side environment variable if available or defined. If
not,  baseUrl  in client side will be equal to  'http://localhost:3000' . The server side variable BASE_URL is therefore copied to the
client side via the  env  property in the  nuxt.config.js . Alternatively, the other value is defined (http://localhost:3000).

Then, I can access my  baseUrl  variable in 2 ways:

. Via  process.env.baseUrl .

. Via  context.env.baseUrl , see context API.

You can use the  env  property for giving a public token for example.

For the example above, we can use it to configure axios.


plugins/axios.js
import axios from 'axios'

export default axios.create({


baseURL: process.env.baseUrl
})

Then, in your pages, you can import axios like this:  import axios from '~/plugins/axios'

Automatic injection of environment variables


If you define environment variables starting with  NUXT_ENV_  in the build phase (e.g.  NUXT_ENV_COOL_WORD=freezing nuxt build  or  SET
NUXT_ENV_COOL_WORD=freezing & nuxt build  for the Windows console, they'll be automatically injected into the process environment.
Be aware that they'll potentially take precedence over defined variables in your  nuxt.config.js  with the same name.

process.env == {}
Note that Nuxt uses webpack's  definePlugin  to define the environmental variable. This means that the
actual  process  or  process.env  from Node.js is neither available nor defined. Each of the  env  properties defined in nuxt.config.js is
individually mapped to  process.env.xxxx  and converted during compilation.

Meaning,  console.log(process.env)  will output  {}  but  console.log(process.env.your_var)  will still output your value. When
webpack compiles your code, it replaces all instances of  process.env.your_var  with the value you've set it to, e.g.:  env.test =
'testing123' . If you use  process.env.test in your code somewhere, it is actually translated to 'testing123'.

before

if (process.env.test == 'testing123')
after

if ('testing123' == 'testing123')

serverMiddleware
As serverMiddleware is decoupled from the main Nuxt build,  env  variables defined in  nuxt.config.js  are not available there.

dir extendPlugins

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The extendPlugins Property
The extendPlugins property lets you customize Nuxt.js plugins (options.plugins).

Type:  Function

Default:  undefined

You may want to extend plugins or change plugins order created by Nuxt.js. This function accepts an array of plugin objects and
should return array of plugin objects.

Example of changing plugins order:

nuxt.config.js
export default {
extendPlugins(plugins) {
const pluginIndex = plugins.findIndex(
({ src }) => src === '~/plugins/shouldBeFirst.js'
)
const shouldBeFirstPlugin = plugins[pluginIndex]

plugins.splice(pluginIndex, 1)
plugins.unshift(shouldBeFirstPlugin)

return plugins
}
}

env generate
Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!
The generate Property
Type:  Object

Configure the generation of your universal web application to a static web application.

When calling  nuxt.generate() , Nuxt.js will use the configuration defined in the  generate  property.

nuxt.config.js
export default {
generate: {
...
}
}

cache
Introduced in v2.14.0

Type:  Object  or  false

This option is used by  nuxt generate  with static target to avoid re-building when no tracked file has been changed.

Defaults:

{
ignore: [
'.nuxt', // buildDir
'static', // dir.static
'dist', // generate.dir
'node_modules',
'.**/*',
'.*',
'README.md'
]
}

If you want to avoid re-building when changing a configuration file, just add it to the list by providing the  cache.ignore  option:

nuxt.config.js
export default {
generate: {
cache: {
ignore: ['renovate.json'] // ignore changes applied on this file
}
}
}

concurrency
Type:  Number

Default:  500

The generation of routes are concurrent,  generate.concurrency  specifies the amount of routes that run in one thread.

crawler
Type:  boolean

Default: true

As of Nuxt >= v2.13 Nuxt.js comes with a crawler installed that will crawl your relative links and generate your dynamic links based
on these links. If you want to disable this feature you can set the value to  false

export default {
generate: {
crawler: false
}
}

dir
Type:  String

Default:  'dist'

Directory name created when building web applications using the  nuxt generate command.

devtools
Type:  boolean

Default:  false

Configure whether to allow vue-devtools inspection.


If you already activated through nuxt.config.js or otherwise, devtools enable regardless of the flag.

exclude
Type:  Array

Items:  String  or  RegExp

It accepts an array of string or regular expressions and will prevent generation of routes matching them. The routes will still be
accessible when  generate.fallback  is used.

Taking this examples of structure:

-| pages/
---| index.vue
---| admin/
-----| about.vue
-----| index.vue

By default, running  nuxt generate  a file will be created for each route.

-| dist/
---| index.html
---| admin/
-----| about.html
-----| item.html

When adding a regular expression which matches all routes with "ignore", it will prevent the generation of these routes.
nuxt.config.js
export default {
generate: {
exclude: [
/^\/admin/ // path starts with /admin
]
}
}

-| dist/
---| index.html

You can also exclude a specific route by giving a string:

nuxt.config.js
export default {
generate: {
exclude: ['/my-secret-page']
}
}

fallback
Type:  String  or  Boolean

Default:  200.html
nuxt.config.js
export default {
generate: {
fallback: '404.html'
}
}

The path to the fallback HTML file. It should be set as the error page, so that also unknown routes are rendered via Nuxt. If unset or
set to a falsy value, the name of the fallback HTML file will be  200.html . If set to  true , the filename will be  404.html . If you provide
a string as a value, it will be used instead.

nuxt.config.js
fallback: false;

If working with statically generated pages then it is recommended to use a  404.html  for error pages and for those covered
by excludes (the files that you do not want generated as static pages).

nuxt.config.js
fallback: true

However, Nuxt allows you to configure any page you like so if you don't want to use the  200.html  or  404.html  you can add a string
and then you just have to make sure you redirect to that page instead. This is of course not necessary and is best to redirect
to  200.html / 404.html .

nuxt.config.js
fallback: 'fallbackPage.html'

Note: Multiple services (e.g. Netlify) detect a  404.html  automatically. If you configure your web server on your own, please consult its
documentation to find out how to set up an error page (and set it to the  404.html  file)
interval
Type:  Number

Default:  0

Interval in milliseconds between two render cycles to avoid flooding a potential API with calls from the web application.

minify
Deprecated!

Use build.html.minify instead

routes
Type:  Array

As of Nuxt v2.13 there is a crawler installed that will crawl your link tags and generate your routes when running  nuxt generate .

If have unlinked pages (such as secret pages) and you would like these to also be generated then you can use the  generate.routes  property.

Dynamic routes are ignored by the  generate  command when using  Nuxt <= v2.12

Example:
-| pages/
---| index.vue
---| users/
-----| _id.vue

Only the route  /  will be generated by Nuxt.js.

If you want Nuxt.js to generate routes with dynamic params, you need to set the  generate.routes  property to an array of dynamic
routes.

We add routes for  /users/:id :

nuxt.config.js
export default {
generate: {
routes: ['/users/1', '/users/2', '/users/3']
}
}

Then when we launch  nuxt generate :

[nuxt] Generating...
[...]
nuxt:render Rendering url / +154ms
nuxt:render Rendering url /users/1 +12ms
nuxt:render Rendering url /users/2 +33ms
nuxt:render Rendering url /users/3 +7ms
nuxt:generate Generate file: /index.html +21ms
nuxt:generate Generate file: /users/1/index.html +31ms
nuxt:generate Generate file: /users/2/index.html +15ms
nuxt:generate Generate file: /users/3/index.html +23ms
nuxt:generate HTML Files generated in 7.6s +6ms
[nuxt] Generate done

Great, but what if we have dynamic params?

. Use a  Function  which returns a  Promise .

. Use a  Function  with a  callback(err, params) .

Function which returns a Promise

nuxt.config.js
import axios from 'axios'

export default {
generate: {
routes() {
return axios.get('https://my-api/users').then(res => {
return res.data.map(user => {
return '/users/' + user.id
})
})
}
}
}
Function with a callback
nuxt.config.js
import axios from 'axios'

export default {
generate: {
routes(callback) {
axios
.get('https://my-api/users')
.then(res => {
const routes = res.data.map(user => {
return '/users/' + user.id
})
callback(null, routes)
})
.catch(callback)
}
}
}

Speeding up dynamic route generation with  payload


In the example above, we're using the  user.id  from the server to generate the routes but tossing out the rest of the data. Typically,
we need to fetch it again from inside the  /users/_id.vue . While we can do that, we'll probably need to set the  generate.interval  to
something like  100  in order not to flood the server with calls. Because this will increase the run time of the generate script, it would
be preferable to pass along the entire  user  object to the context in  _id.vue . We do that by modifying the code above to this:
nuxt.config.js
import axios from 'axios'

export default {
generate: {
routes() {
return axios.get('https://my-api/users').then(res => {
return res.data.map(user => {
return {
route: '/users/' + user.id,
payload: user
}
})
})
}
}
}

Now we can access the  payload  from  /users/_id.vue  like so:

async asyncData ({ params, error, payload }) {


if (payload) return { user: payload }
else return { user: await backend.fetchUser(params.id) }
}

subFolders
Type:  Boolean
Default:  true

By default, when running  nuxt generate , Nuxt.js will create a directory for each route & serve an  index.html  file.

Example:

-| dist/
---| index.html
---| about/
-----| index.html
---| products/
-----| item/
-------| index.html

When set to false, HTML files are generated according to the route path:

nuxt.config.js
export default {
generate: {
subFolders: false
}
}

-| dist/
---| index.html
---| about.html
---| products/
-----| item.html
extendPlugins globalName

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The globalName Property
Nuxt.js lets you customize the global ID used in the main HTML template as well as the main Vue instance name and other options.

Type:  String

Default:  nuxt

nuxt.config.js
{
globalName: 'myCustomName'
}

The  globalName  needs to be a valid JavaScript identifier, and changing it may break support for certain plugins that rely on Nuxt-named
functions. If you're looking to just change the visible  __nuxt  HTML ID, then use the  globals property.

The globals property


Customizes specific global names which are based on  globalName  by default.

Type:  Object

Default:

nuxt.config.js
globals: {
id: globalName => `__${globalName}`,
nuxt: globalName => `$${globalName}`,
context: globalName => `__${globalName.toUpperCase()}__`,
pluginPrefix: globalName => globalName,
readyCallback: globalName => `on${_.capitalize(globalName)}Ready`,
loadedCallback: globalName => `_on${_.capitalize(globalName)}Loaded`
},

generate head

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The head Property
Nuxt.js let you define all default meta for your application inside  nuxt.config.js , use the same  head  property

Type:  Object  or  Function

nuxt.config.js
export default {
head: {
titleTemplate: '%s - Nuxt.js',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },

// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{ hid: 'description', name: 'description', content: 'Meta description' }
]
}
}

To know the list of options you can give to  head , take a look at vue-meta documentation.

You can also use  head  as a function in your components to access the component data through  this  (read more).

To avoid duplicated meta tags when used in child component, set up a unique identifier with the  hid  key for your meta elements (read more).

globalName hooks
Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The hooks Property
Type:  Object

Hooks are listeners to Nuxt events that are typically used in Nuxt modules, but are also available in  nuxt.config.js .

nuxt.config.js
import fs from 'fs'
import path from 'path'

export default {
hooks: {
build: {
done(builder) {
const extraFilePath = path.join(
builder.nuxt.options.buildDir,
'extra-file'
)
fs.writeFileSync(extraFilePath, 'Something extra')
}
}
}
}

Internally, hooks follow a naming pattern using colons (e.g.,  build:done ). For ease of configuration, you can structure them as an
hierarchical object when using  nuxt.config.js  (as exemplified above) to set your own hooks. See Nuxt Internals for more detailed
information on how they work.
List of hooks
Nuxt hooks

Renderer hooks

ModulesContainer hooks

Builder hooks

Generator hooks

Examples

Redirect to router.base when not on root


Let´s say you want to serve pages as  /portal  instead of  / .

This is maybe an edge-case, and the point of nuxt.config.js’  router.base  is for when a web server will serve Nuxt elsewhere than the
domain root.

But when in local development, hitting localhost, when router.base is not / returns a 404. In order to prevent this, you can setup a
Hook.

Maybe redirecting is not the best use-case for a production Web site, but this will help you leverage Hooks.

To begin, you can change  router.base ; Update your  nuxt.config.js :

nuxt.config.js
import hooks from './hooks'
export default {
router: {
base: '/portal'
}
hooks: hooks(this)
}

Then, create a few files;

. hooks/index.js , Hooks module

hooks/index.js
import render from './render'

export default nuxtConfig => ({


render: render(nuxtConfig)
})

. hooks/render.js , Render hook

hooks/render.js
import redirectRootToPortal from './route-redirect-portal'

export default nuxtConfig => {


const router = Reflect.has(nuxtConfig, 'router') ? nuxtConfig.router : {}
const base = Reflect.has(router, 'base') ? router.base : '/portal'

return {
/**
* 'render:setupMiddleware'
* {@link node_modules/nuxt/lib/core/renderer.js}
*/
setupMiddleware(app) {
app.use('/', redirectRootToPortal(base))
}
}
}

. hooks/route-redirect-portal.js , The Middleware itself

hooks/route-redirect-portal.js
/**
* Nuxt middleware hook to redirect from / to /portal (or whatever we set in nuxt.config.js router.base)
*
* Should be the same version as connect
* {@link node_modules/connect/package.json}
*/
import parseurl from 'parseurl'

/**
* Connect middleware to handle redirecting to desired Web Application Context Root.
*
* Notice that Nuxt docs lacks explaining how to use hooks.
* This is a sample router to help explain.
*
* See nice implementation for inspiration:
* - https://github.com/nuxt/nuxt.js/blob/dev/examples/with-cookies/plugins/cookies.js
* - https://github.com/yyx990803/launch-editor/blob/master/packages/launch-editor-middleware/index.js
*
* [http_class_http_clientrequest]: https://nodejs.org/api/http.html#http_class_http_clientrequest
* [http_class_http_serverresponse]: https://nodejs.org/api/http.html#http_class_http_serverresponse
*
* @param {http.ClientRequest} req Node.js internal client request object [http_class_http_clientrequest]
* @param {http.ServerResponse} res Node.js internal response [http_class_http_serverresponse]
* @param {Function} next middleware callback
*/
export default desiredContextRoot =>
function projectHooksRouteRedirectPortal(req, res, next) {
const desiredContextRootRegExp = new RegExp(`^${desiredContextRoot}`)
const _parsedUrl = Reflect.has(req, '_parsedUrl') ? req._parsedUrl : null
const url = _parsedUrl !== null ? _parsedUrl : parseurl(req)
const startsWithDesired = desiredContextRootRegExp.test(url.pathname)
const isNotProperContextRoot = desiredContextRoot !== url.pathname
if (isNotProperContextRoot && startsWithDesired === false) {
const pathname = url.pathname === null ? '' : url.pathname
const search = url.search === null ? '' : url.search
const Location = desiredContextRoot + pathname + search
res.writeHead(302, {
Location
})
res.end()
}
next()
}

Then, whenever a colleague in development accidentally hits  /  to reach the development web development service, Nuxt will
automatically redirect to  /portal

head ignore
Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!
The ignore Property

.nuxtignore
You can use a  .nuxtignore  file to let Nuxt.js ignore  layout ,  page ,  store  and  middleware  files in your project’s root directory
( rootDir ) during the build phase. The  .nuxtignore  file is subject to the same specification as  .gitignore  and  .eslintignore  files,
in which each line is a glob pattern indicating which files should be ignored.

For example:

# ignore layout foo.vue


layouts/foo.vue
# ignore layout files whose name ends with -ignore.vue
layouts/*-ignore.vue

# ignore page bar.vue


pages/bar.vue
# ignore page inside ignore folder
pages/ignore/*.vue

# ignore store baz.js


store/baz.js
# ignore store files match *.test.*
store/ignore/*.test.*

# ignore middleware files under foo folder except foo/bar.js


middleware/foo/*.js
!middleware/foo/bar.js
More details about the spec are in gitignore doc

The ignorePrefix Property


Type:  String

Default:  '-'

Any file in pages/, layouts/, middleware/ or store/ will be ignored during building if its filename starts with the prefix specified
by  ignorePrefix .

By default all files which start with  -  will be ignored, such as  store/-foo.js  and  pages/-bar.vue . This allows for co-locating tests,
utilities, and components with their callers without themselves being converted into routes, stores, etc.

The ignore Property


Type:  Array

Default:  ['**/*.test.*']

More customizable than  ignorePrefix : all files matching glob patterns specified inside  ignore  will be ignored in building.

ignoreOptions
nuxtignore  is using  node-ignore  under the hood,  ignoreOptions  can be configured as  options  of  node-ignore .

nuxt.config.js
export default {
ignoreOptions: {
ignorecase: false
}
}

hooks loading

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The loading Property
Type:  Boolean  or  Object  or  String

Out of the box, Nuxt.js gives you its own loading progress bar component that's shown between routes. You can customize it, disable
it or create your own component.

export default {
mounted() {
this.$nextTick(() => {
this.$nuxt.$loading.start()

setTimeout(() => this.$nuxt.$loading.finish(), 500)


})
}
}

Disable the Progress Bar


Type:  Boolean

nuxt.config.js
export default {
loading: false
}
Customizing the Progress Bar
Type:  Object

export default {
loading: {
color: 'blue',
height: '5px'
}
}

List of properties to customize the progress bar.

Key Type Default Description


color String 'black' CSS color of the progress bar
CSS color of the progress bar when an error appended while rendering the route (if  data  or  fetch  sent
failedColor String 'red'
back an error for example).
height String '2px' Height of the progress bar (used in the  style property of the progress bar)
In ms, wait for the specified time before displaying the progress bar. Useful for preventing the bar from
throttle Number 200
flashing.
In ms, the maximum duration of the progress bar, Nuxt.js assumes that the route will be rendered before
duration Number 5000
5 seconds.
continuous Boolean false Keep animating progress bar when loading takes longer than  duration .
css Boolean true Set to false to remove default progress bar styles (and add your own).
rtl Boolean false Set the direction of the progress bar from right to left.

Using a Custom Loading Component


Type:  String
Your component has to expose some of these methods:

Method Required Description


start() Required Called when a route changes, this is where you display your component.
finish() Required Called when a route is loaded (and data fetched), this is where you hide your component.
fail(error) Optional Called when a route couldn't be loaded (failed to fetch data for example).
increase(num) Optional Called during loading the route component,  num  is an Integer < 100.

components/loading.vue
<template lang="html">
<div class="loading-page" v-if="loading">
<p>Loading...</p>
</div>
</template>

<script>
export default {
data: () => ({
loading: false
}),
methods: {
start() {
this.loading = true
},
finish() {
this.loading = false
}
}
}
</script>

<style scoped>
.loading-page {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.8);
text-align: center;
padding-top: 200px;
font-size: 30px;
font-family: sans-serif;
}
</style>

nuxt.config.js
export default {
loading: '~/components/loading.vue'
}

ignore loadingIndicator

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The loading indicator Property
Show fancy loading indicator while page is loading!

Without Server Side Rendering (when  ssr  option is  false ), there is no content from the server side on the first page load. So,
instead of showing a blank page while the page loads, we may show a spinner.

This property can have 3 different types:  string  or  false  or  object . If a string value is provided it is converted to object style.

Default value is:

loadingIndicator: {
name: 'circle',
color: '#3B8070',
background: 'white'
}

Built-in indicators
These indicators are imported from the awesome SpinKit project. You can use its demo page to preview spinners.

circle

cube-grid

fading-circle

folding-cube
chasing-dots

nuxt

pulse

rectangle-bounce

rotating-plane

three-bounce

wandering-cubes

Built-in indicators support  color  and  background  options.

Custom indicators
If you need your own special indicator, a String value or Name key can also be a path to an HTML template of indicator source code!
All of the options are passed to the template, too.

Nuxt's built-in source code is also available if you need a base!

loading mode

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The mode Property
Type:  string

Default:  universal

Possible values:

'spa' : No server-side rendering (only client-side navigation)

'universal' : Isomorphic application (server-side rendering + client-side navigation)

You can use this option to change default nuxt mode for your project using  nuxt.config.js

Deprecated: please use  ssr: false  instead of  mode: spa

To learn more about the  ssr  option, checkout the ssr property.

To learn more about the  mode  option, checkout the rendering modes section.

loadingIndicator modern

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The modern Property
This feature is inspired by vue-cli modern mode

Type:  String  or  Boolean

Default: false

Possible values:

'client' : Serve both, the modern bundle  <script type="module">  and the legacy bundle  <script nomodule>  scripts, also
provide a  <link rel="modulepreload">  for the modern bundle. Every browser that understands the  module  type will load the
modern bundle while older browsers fall back to the legacy (transpiled) one.

'server'  or  true : The Node.js server will check browser version based on the user agent and serve the corresponding
modern or legacy bundle.

false : Disable modern build

The two versions of bundles are:

. Modern bundle: targeting modern browsers that support ES modules

. Legacy bundle: targeting older browsers based on babel config (IE9 compatible by default).

Info:

Use command option  [--modern | -m]=[mode]  to build/start modern bundles:

package.json
{
"scripts": {
"build:modern": "nuxt build --modern=server",
"start:modern": "nuxt start --modern=server"
}
}

Note about nuxt generate: The  modern  property also works with the  nuxt generate  command, but in this case only
the  client  option is honored and will be selected automatically when launching the  nuxt generate --modern  command without
providing any values.

Nuxt will automatically detect  modern  build in  nuxt start  when  modern  is not specified, auto-detected mode is:

ssr Modern Mode


true server
false client

Modern mode for  nuxt generate  can only be  client

Use  render.crossorigin  to set  crossorigin  attribute in  <link>  and  <script>

Please refer Phillip Walton's excellent post for more knowledge regarding modern builds.

mode modules

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The modules Property
Type:  Array

Modules are Nuxt.js extensions which can extend its core functionality and add endless integrations. Learn More

Example ( nuxt.config.js ):

export default {
modules: [
// Using package name
'@nuxtjs/axios',

// Relative to your project srcDir


'~/modules/awesome.js',

// Providing options
['@nuxtjs/google-analytics', { ua: 'X1234567' }],

// Inline definition
function () {}
]
}

Module developers usually provide additionally needed steps and details for usage.

Nuxt.js tries to resolve each item in the modules array using node require path (in the  node_modules ) and then will be resolved from
project  srcDir  if  ~  alias is used. Modules are executed sequentially so the order is important.
Modules should export a function to enhance nuxt build/runtime and optionally return a promise until their job is finished. Note
that they are required at runtime so should be already transpiled if depending on modern ES6 features.

Please see Modules Guide for more detailed information on how they work or if interested developing your own module. Also we
have provided an official Modules Section listing dozens of production ready modules made by Nuxt Community.

buildModules

This feature is available since Nuxt v2.9

Some modules are only required during development and build time. Using  buildModules  helps to make production startup faster
and also significantly decreasing  node_modules  size for production deployments. Please refer to each module docs to see if it is
recommended to use  modules  or  buildModules .

The usage difference is:

Instead of adding to  modules  inside  nuxt.config.js , use  buildModules

Instead of adding to  dependencies  inside  package.json , use  devDependencies ( yarn add --dev  or  npm install --save-dev )

modern modulesDir

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The modulesDir Property
Type:  Array

Default:  ['node_modules']

Used to set the modules directories for path resolving, for example: Webpack's  resolveLoading ,  nodeExternals  and  postcss .
Configuration path is relative to options.rootDir (default:  process.cwd() ).

nuxt.config.js
export default {
modulesDir: ['../../node_modules']
}

Setting this field may be necessary if your project is organized as a Yarn workspace-styled mono-repository.

modules plugins

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
API: The plugins Property
Note: Since Nuxt.js 2.4,  mode  has been introduced as option of  plugins  to specify plugin type, possible value
are:  client  or  server .  ssr: false  will be adapted to  mode: 'client'  and deprecated in next major release.

Type:  Array

Items:  String  or  Object

If the item is an object, the properties are:

src:  String  (path of the file)

mode:  String  (can be  client  or  server ) If defined, the file will be included only on the respective (client or server) side.

Note: Old version

Type:  Array

Items:  String  or  Object

If the item is an object, the properties are:

src:  String  (path of the file)

ssr:  Boolean  (default to  true ) If false, the file will be included only on the client-side.

The plugins property lets you add Vue.js plugins easily to your main application.

nuxt.config.js
export default {
plugins: [
{ src: '~/plugins/both-sides.js' },
{ src: '~/plugins/client-only.js', mode: 'client' },
{ src: '~/plugins/server-only.js', mode: 'server' }
]
}

nuxt.config.js
export default {
plugins: ['@/plugins/ant-design-vue']
}

plugins/ant-design-vue.js
import Vue from 'vue'
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css' // Per Ant Design's docs

Vue.use(Antd)

Note that the css was imported as per Ant Design Documentation

All the paths defined in the  plugins  property will be imported before initializing the main application.

modulesDir render

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The render Property
Nuxt.js lets you customize runtime options for rendering pages

bundleRenderer
Type:  Object

Use this option to customize vue SSR bundle renderer. This option is skipped if  ssr: false .

nuxt.config.js
export default {
render: {
bundleRenderer: {
directives: {
custom1(el, dir) {
// something ...
}
}
}
}
}

Learn more about available options on Vue SSR API Reference. It is recommended to not use this option as Nuxt.js is already
providing best SSR defaults and misconfiguration might lead to SSR problems.

etag
Type:  Object

Default:  { weak: true }

To disable etag for pages set  etag: false

See etag docs for possible options.

You can use your own hash function by specifying  etag.hash :

nuxt.config.js
import { murmurHash128 } from 'murmurhash-native'

export default {
render: {
etag: {
hash: html => murmurHash128(html)
}
}
}

In this case we use murmurhash-native, which is faster for larger HTML body sizes. Note that the  weak  option is ignored, when
specifying your own hash function.

compressor
Type  Object

Default:  { threshold: 0 }
When providing an object, the compression middleware will be used (with respective options).

If you want to use your own compression middleware, you can reference it directly (e.g.  otherComp({ myOptions: 'example' }) ).

To disable compression, use  compressor: false .

fallback
Type  Object

Default:  { dist: {}, static: { skipUnknown: true } }

dist  key is for routes matching the publicPath (ie:  /_nuxt/* )

static  key is for routes matching routes matching  /*

dist  and  static  values are forwarded to serve-placeholder middleware.

If you want to disable one of them or both, you can pass a falsy value.

Example of allowing  .js  extension for routing (ex:  /repos/nuxt.js ):

nuxt.config.js
export default {
render: {
fallback: {
static: {
// Avoid sending 404 for these extensions
handlers: {
'.js': false
}
}
}
}
}

http2
Type  Object

Default:  { push: false, pushAssets: null }

Activate HTTP2 push headers.

You can control what links to push using  pushAssets  function.

Example:

pushAssets: (req, res, publicPath, preloadFiles) =>


preloadFiles
.filter(f => f.asType === 'script' && f.file === 'runtime.js')
.map(f => `<${publicPath}${f.file}>; rel=preload; as=${f.asType}`)

You can add your own assets to the array as well. Using  req  and  res  you can decide what links to push based on the request
headers, for example using the cookie with application version.

The assets will be joined together with  ,  and passed as a single  Link  header.

asyncScripts
Type:  Boolean

Default:  false

Adds an  async  attribute to  <script>  tags for Nuxt bundles, enabling them to be fetched in parallel to parsing (available
with  2.14.8+ ). More information.

injectScripts
Type:  Boolean

Default:  true

Adds the  <script>  for Nuxt bundles, set it to  false  to render pure HTML without JS (available with  2.8.0+ )

resourceHints
Type:  Boolean

Default:  true

Adds  prefetch  and  preload  links for faster initial page load time.

You may want to only disable this option if you have many pages and routes.

ssr
Type:  Boolean
Default:  true

false  only client side rendering

Enable SSR rendering

This option is automatically set based on global  ssr  value if not provided. This can be useful to dynamically enable/disable SSR on
runtime after image builds (with docker for example).

crossorigin
Type:  String

Default:  undefined  Configure the  crossorigin  attribute on  <link rel="stylesheet">  and  <script> tags in generated HTML.

More Info: CORS settings attributes

ssrLog
Type:  Boolean  |  String

Default:  true  in dev mode and  false  in production

Forward server-side logs to the browser for better debugging (only available in development)

To collapse the logs, use  'collapsed'  value.


static
Type:  Object

Default:  {}

Configure the  static/  directory behavior

See serve-static docs for possible options.

Additional to them, we introduced a  prefix  option which defaults to  true . It will add the router base to your static assets.

Example:

Assets:  favicon.ico

Router base:  /t

With  prefix: true  (default):  /t/favicon.ico

With  prefix: false :  /favicon.ico

Caveats:

Some URL rewrites might not respect the prefix.

dist
Type:  Object

Default:  { maxAge: '1y', index: false }


Options used for serving distribution files. Only applicable in production.

See serve-static docs for possible options.

csp
Type:  Boolean  or  Object

Default:  false

Use this to configure Content-Security-Policy to load external resources

Prerequisites:

These CSP settings are only effective when using Nuxt with  target: 'server'  to serve your SSR application. The Policies defined
under  csp.policies  are added to the response  Content-Security-Policy  HTTP header.

Updating settings:

These settings are read by the Nuxt server directly from  nuxt.config.js . This means changes to these settings take effect when the
server is restarted. There is no need to rebuild the application to update the CSP settings.

HTML meta tag:

In order to add  <meta http-equiv="Content-Security-Policy"/>  to the  <head>  you need to set  csp.addMeta  to  true . Please note
that this feature is independent of the  csp.policies  configuration:

it only adds a  script-src  type policy, and

the  script-src  policy only contains the hashes of the inline  <script>  tags.

When  csp.addMeta  is set to  true , the complete set of the defined policies are still added to the HTTP response header.
Note that CSP hashes will not be added as  <meta>  if  script-src  policy contains  'unsafe-inline' . This is due to browser
ignoring  'unsafe-inline'  if hashes are present. Set option  unsafeInlineCompatibility  to  true  if you want both hashes
and  'unsafe-inline'  for CSPv1 compatibility. In that case the  <meta>  tag will still only contain the hashes of the
inline  <script>  tags, and the policies defined under  csp.policies  will be used in the  Content-Security-Policy  HTTP response
header.

nuxt.config.js
export default {
render: {
csp: true
}
}

// OR

export default {
render: {
csp: {
hashAlgorithm: 'sha256',
policies: {
'script-src': [
'https://www.google-analytics.com',
'https://name.example.com'
],
'report-uri': ['https://report.example.com/report-csp-violations']
},
addMeta: true
}
}
}
// OR
/*
The following example allows Google Analytics, LogRocket.io, and Sentry.io
for logging and analytic tracking.

Review to this blog on Sentry.io


https://blog.sentry.io/2018/09/04/how-sentry-captures-csp-violations

To learn what tracking link you should use.


*/
const PRIMARY_HOSTS = `loc.example-website.com`
export default {
render: {
csp: {
reportOnly: true,
hashAlgorithm: 'sha256',
policies: {
'default-src': ["'self'"],
'img-src': ['https:', '*.google-analytics.com'],
'worker-src': ["'self'", `blob:`, PRIMARY_HOSTS, '*.logrocket.io'],
'style-src': ["'self'", "'unsafe-inline'", PRIMARY_HOSTS],
'script-src': [
"'self'",
"'unsafe-inline'",
PRIMARY_HOSTS,
'sentry.io',
'*.sentry-cdn.com',
'*.google-analytics.com',
'*.logrocket.io'
],
'connect-src': [PRIMARY_HOSTS, 'sentry.io', '*.google-analytics.com'],
'form-action': ["'self'"],
'frame-ancestors': ["'none'"],
'object-src': ["'none'"],
'base-uri': [PRIMARY_HOSTS],
'report-uri': [
`https://sentry.io/api/<project>/security/?sentry_key=<key>`
]
}
}
}
}

plugins rootDir

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The rootDir Property
Type:  String

Default:  process.cwd()

Define the workspace directory of your Nuxt.js application.

This property will be overwritten by the nuxt commands(nuxt start, nuxt build etc) if an argument is passed to them. Eg
running  nuxt ./my-app/  will set the  rootDir  to the absolute path of  ./my-app/  from the current/working directory.

Because of that its normally not needed to configure this option unless you will use Nuxt.js programmatically.

Both  rootDir  as the package root containing the  node_modules  directory need to be within the same directory tree to be able to resolve
dependencies. See the  srcDir  option for examples of directory structure when that is not the case.

render router

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The router Property
The router property lets you customize Nuxt.js router (vue-router).

base
Type:  String

Default:  '/'

The base URL of the app. For example, if the entire single page application is served under  /app/ , then base should use the
value  '/app/' .

This can be useful if you need to serve Nuxt as a different context root, from within a bigger Web site. Notice that you may, or may
not set up a Front Proxy Web Server.

If you want to have a redirect to  router.base , you can do so using a Hook, see Redirect to router.base when not on root.

In Nuxt 2.15+, changing the value of this property at runtime will override the configuration of an app that has already been built.

nuxt.config.js
export default {
router: {
base: '/app/'
}
}

When  base  is set, Nuxt.js will also add in the document header  <base href="{{ router.base }}"/> .
This option is given directly to the vue-router base.

routeNameSplitter
Type:  String

Default:  '-'

You may want to change the separator between route names that Nuxt.js uses. You can do so via the  routeNameSplitter  option in
your configuration file. Imagine we have the page file  pages/posts/_id.vue . Nuxt will generate the route name programmatically, in
this case  posts-id . Changing the  routeNameSplitter config to  /  the name will therefore change to  posts/id .

nuxt.config.js
export default {
router: {
routeNameSplitter: '/'
}
}

extendRoutes
Type:  Function

You may want to extend the routes created by Nuxt.js. You can do so via the  extendRoutes  option.

nuxt.config.js
export default {
router: {
extendRoutes(routes, resolve) {
routes.push({
name: 'custom',
path: '*',
component: resolve(__dirname, 'pages/404.vue')
})
}
}
}

If you want to sort your routes, you can use the  sortRoutes(routes)  function from  @nuxt/utils :

nuxt.config.js
import { sortRoutes } from '@nuxt/utils'
export default {
router: {
extendRoutes(routes, resolve) {
// Add some routes here ...

// and then sort them


sortRoutes(routes)
}
}
}

The schema of the route should respect the vue-router schema.

When adding routes that use Named Views, don't forget to add the corresponding  chunkNames  of named  components .
nuxt.config.js
export default {
router: {
extendRoutes(routes, resolve) {
routes.push({
path: '/users/:id',
components: {
default: resolve(__dirname, 'pages/users'), // or routes[index].component
modal: resolve(__dirname, 'components/modal.vue')
},
chunkNames: {
modal: 'components/modal'
}
})
}
}
}

fallback
Type:  boolean

Default:  false

Controls whether the router should fallback to hash mode when the browser does not support history.pushState but mode is set to
history.

Setting this to false essentially makes every router-link navigation a full page refresh in IE9. This is useful when the app is server-
rendered and needs to work in IE9, because a hash mode URL does not work with SSR.
This option is given directly to the vue-router fallback.

linkActiveClass
Type:  String

Default:  'nuxt-link-active'

Globally configure  <nuxt-link>  default active class.

nuxt.config.js
export default {
router: {
linkActiveClass: 'active-link'
}
}

This option is given directly to the vue-router linkActiveClass.

linkExactActiveClass
Type:  String

Default:  'nuxt-link-exact-active'

Globally configure  <nuxt-link>  default exact active class.

nuxt.config.js
export default {
router: {
linkExactActiveClass: 'exact-active-link'
}
}

This option is given directly to the vue-router linkExactActiveClass.

linkPrefetchedClass
Type:  String

Default:  false

Globally configure  <nuxt-link>  default prefetch class (feature disabled by default)

nuxt.config.js
export default {
router: {
linkPrefetchedClass: 'nuxt-link-prefetched'
}
}

middleware
Type:  String  or  Array

Items:  String

Set the default(s) middleware for every page of the application.


nuxt.config.js
export default {
router: {
// Run the middleware/user-agent.js on every page
middleware: 'user-agent'
}
}

middleware/user-agent.js
export default function (context) {
// Add the userAgent property in the context (available in `asyncData` and `fetch`)
context.userAgent = process.server
? context.req.headers['user-agent']
: navigator.userAgent
}

To learn more about the middleware, see the middleware guide.

mode
Type:  String

Default:  'history'

Configure the router mode, this is not recommended to change it due to server-side rendering.

nuxt.config.js
export default {
router: {
mode: 'hash'
}
}

This option is given directly to the vue-router mode.

parseQuery / stringifyQuery
Type:  Function

Provide custom query string parse / stringify functions. Overrides the default.

This option is given directly to the vue-router parseQuery / stringifyQuery.

prefetchLinks
Added with Nuxt v2.4.0

Type:  Boolean

Default:  true

Configure  <nuxt-link>  to prefetch the code-splitted page when detected within the viewport. Requires IntersectionObserver to be
supported (see Caniuse).

We recommend conditionally polyfilling this feature with a service like Polyfill.io:

nuxt.config.js
export default {
head: {
script: [
{
src:
'https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver',
body: true
}
]
}
}

To disable the prefetching on a specific link, you can use the  no-prefetch  prop. Since Nuxt.js v2.10.0, you can also use
the  prefetch  prop set to  false :

<nuxt-link to="/about" no-prefetch>About page not prefetched</nuxt-link>


<nuxt-link to="/about" :prefetch="false">About page not prefetched</nuxt-link>

To disable the prefetching on all links, set the  prefetchLinks  to  false :

nuxt.config.js
export default {
router: {
prefetchLinks: false
}
}

Since Nuxt.js v2.10.0, if you have set  prefetchLinks  to  false  but you want to prefetch a specific link, you can use
the  prefetch  prop:

<nuxt-link to="/about" prefetch>About page prefetched</nuxt-link>


prefetchPayloads
Added with v2.13.0, only available for static target.

Type:  Boolean

Default:  true

When using  nuxt generate  with  target: 'static' , Nuxt will generate a  payload.js  for each page.

With this option enabled, Nuxt will automatically prefetch the payload of the linked page when the  <nuxt-link>  is visible in the
viewport, making instant navigation.

This option depends of the prefetchLinks option to be enabled.

You can disable this behavior by setting  prefetchPaylods  to  false :

nuxt.config.js
export default {
router: {
prefetchPayloads: false
}
}

scrollBehavior
Type:  Function
The  scrollBehavior  option lets you define a custom behavior for the scroll position between the routes. This method is called every
time a page is rendered. To learn more about it, see vue-router scrollBehavior documentation.

Starting from v2.9.0, you can use a file to overwrite the router scrollBehavior, this file should be placed
in  ~/app/router.scrollBehavior.js  (note: filename is case-sensitive if running on Windows).

You can see Nuxt default  router.scrollBehavior.js  file here: packages/vue-app/template/router.scrollBehavior.js.

Example of forcing the scroll position to the top for every routes:

app/router.scrollBehavior.js

app/router.scrollBehavior.js
export default function (to, from, savedPosition) {
return { x: 0, y: 0 }
}

trailingSlash
Type:  Boolean  or  undefined

Default:  undefined

Available since: v2.10

If this option is set to true, trailing slashes will be appended to every route. If set to false, they'll be removed.

Attention: This option should not be set without preparation and has to be tested thoroughly. When
setting  router.trailingSlash  to something else than  undefined , the opposite route will stop working. Thus 301 redirects should be
in place and your internal linking has to be adapted correctly. If you set  trailingSlash  to  true , then only  example.com/abc/  will
work but not  example.com/abc . On false, it's vice-versa

Example behavior (with child routes)


For a directory with this structure:

-| pages/
---| index.vue
---| posts.vue
---| posts/
-----| _slug.vue
-----| index.vue

This is the behavior for each possible setting of  trailingSlash :

default true false

Route Page
/ ~/pages/index.vue
/posts ~/pages/posts.vue (parent) + ~/pages/posts.vue (child route)
/posts/ ~/pages/posts.vue (parent) + ~/pages/posts.vue (child route)
/posts/foo ~/pages/posts.vue (parent) + ~/pages/_slug.vue (child route)
/posts/foo/ ~/pages/posts.vue (parent) + ~/pages/_slug.vue (child route)

rootDir runtimeConfig
Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
RuntimeConfig properties
Runtime config allows passing dynamic config and environment variables to the nuxt context. For more information of usage, please
see runtime config guide

publicRuntimeConfig

Type:  Object

Value of this object is accessible from both client and server using  $config .

privateRuntimeConfig

Type:  Object

Value of this object is accessible from server only using  $config . Overrides  publicRuntimeConfig  for server.

router server

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The server Property
Type:  Object

Nuxt.js let you define the server connection variables for your application inside  nuxt.config.js .

Basic example:
nuxt.config.js
export default {
server: {
port: 8000, // default: 3000
host: '0.0.0.0', // default: localhost,
timing: false
}
}

This lets you specify the host and port for your Nuxt.js server instance.

Example using HTTPS configuration


nuxt.config.js
import path from 'path'
import fs from 'fs'

export default {
server: {
https: {
key: fs.readFileSync(path.resolve(__dirname, 'server.key')),
cert: fs.readFileSync(path.resolve(__dirname, 'server.crt'))
}
}
}

You can find additional information on creating server keys and certificates on  localhost  on certificates for localhost article.

Example using sockets configuration


nuxt.config.js
export default {
server: {
socket: '/tmp/nuxt.socket'
}
}

timing
Type:  Object  or  Boolean

Default:  false

Enabling the  server.timing  option adds a middleware to measure the time elapsed during server-side rendering and adds it to the
headers as 'Server-Timing'

Example using timing configuration


server.timing  can be an object for providing options. Currently, only  total  is supported (which directly tracks the whole time
spent on server-side rendering)

nuxt.config.js
export default {
server: {
timing: {
total: true
}
}
}

Using timing API


The  timing  API is also injected into the  response  on server-side when  server.time  is enabled.

Syntax

res.timing.start(name, description)
res.timing.end(name)

Example using timing in serverMiddleware

export default function (req, res, next) {


res.timing.start('midd', 'Middleware timing description')
// server side operation..
// ...
res.timing.end('midd')
next()
}

Then  server-timing  head will be included in response header like:

Server-Timing: midd;desc="Middleware timing description";dur=2.4

Please refer to Server-Timing MDN for more details.

runtimeConfig serverMiddleware

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The serverMiddleware Property
Type:  Array

Items:  String  or  Object  or  Function

Nuxt internally creates a connect instance that you can add your own custom middleware to. This allows us to register additional
routes (typically  /api  routes) without need for an external server.

Because connect itself is a middleware, registered middleware will work with both  nuxt start  and also when used as a middleware
with programmatic usages like express-template. Nuxt Modules can also
provide  serverMiddleware  using this.addServerMiddleware()

Additional to them, we introduced a  prefix  option which defaults to  true . It will add the router base to your server middlewares.

Example:

Server middleware path:  /server-middleware

Router base:  /admin

With  prefix: true  (default):  /admin/server-middleware

With  prefix: false :  /server-middleware

serverMiddleware vs middleware!
Don't confuse it with routes middleware which are called before each route by Vue in Client Side or SSR. Middleware listed in
the  serverMiddleware  property runs server-side before  vue-server-renderer  and can be used for server specific tasks like handling
API requests or serving assets.
Do not add serverMiddleware to the middleware/ directory.

Middleware, are bundled by webpack into your production bundle and run on beforeRouteEnter. If you add serverMiddleware to the
middleware/ directory it will be wrongly picked up by Nuxt as middleware and will add wrong dependencies to your bundle or generate errors.

Usage
If middleware is String Nuxt.js will try to automatically resolve and require it.

nuxt.config.js
import serveStatic from 'serve-static'

export default {
serverMiddleware: [
// Will register redirect-ssl npm package
'redirect-ssl',

// Will register file from project server-middleware directory to handle /server-middleware/* requires
{ path: '/server-middleware', handler: '~/server-middleware/index.js' },

// We can create custom instances too


{ path: '/static2', handler: serveStatic(__dirname + '/static2') }
]
}

If you don't want middleware to register for all routes you have to use Object form with specific path, otherwise nuxt default handler won't
work!
Custom Server Middleware
It is also possible to write custom middleware. For more information See Connect Docs.

Middleware ( server-middleware/logger.js ):

server-middleware/logger.js
export default function (req, res, next) {
// req is the Node.js http request object
console.log(req.url)

// res is the Node.js http response object

// next is a function to call to invoke the next middleware


// Don't forget to call next at the end if your middleware is not an endpoint!
next()
}

nuxt.config.js
serverMiddleware: ['~/server-middleware/logger']

Custom API endpoint


A server middleware can also extend Express. This allows the creation of REST endpoints.

server-middleware/rest.js
const bodyParser = require('body-parser')
const app = require('express')()

app.use(bodyParser.json())
app.all('/getJSON', (req, res) => {
res.json({ data: 'data' })
})

module.exports = app

nuxt.config.js
serverMiddleware: [
{ path: "/server-middleware", handler: "~/server-middleware/rest.js" },
],

Object Syntax
If your server middleware consists of a list of functions mapped to paths:

export default {
serverMiddleware: [
{ path: '/a', handler: '~/server-middleware/a.js' },
{ path: '/b', handler: '~/server-middleware/b.js' },
{ path: '/c', handler: '~/server-middleware/c.js' }
]
}

You can alternatively pass an object to define them, as follows:

export default {
serverMiddleware: {
'/a': '~/server-middleware/a.js',
'/b': '~/server-middleware/b.js',
'/c': '~/server-middleware/c.js'
}
}

server srcDir

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The srcDir Property
Type:  String

Default: rootDir value

Define the source directory of your Nuxt.js application

If a relative path is specified it will be relative to the  rootDir .

Example 1: Prerequisites:

nuxt.config.js
export default {
srcDir: 'client/'
}

package.json
"script": {
"dev": "yarn nuxt"
}

works with the following folder structure (note that nuxt.config is listed in the app directory)

-| app/
---| node_modules/
---| nuxt.config.js
---| package.json
---| client/
------| assets/
------| components/
------| layouts/
------| middleware/
------| pages/
------| plugins/
------| static/
------| store/

Example 2:

Instead of example 1 you can also move the nuxt.config into your  client  folder. In this case you only need to specify  client  as
the  rootDir  and you can leave  srcDir  empty:

Prerequisites:

nuxt.config.js
export default {
srcDir: '' // or just remove it
}

package.json
"script": {
"dev": "yarn nuxt client" // this sets client as the rootDir
}

works with the following folder structure (note that nuxt.config is listed in the client directory)

-| app/
---| node_modules/
---| package.json
---| client/
------| nuxt.config.js
------| assets/
------| components/
------| layouts/
------| middleware/
------| pages/
------| plugins/
------| static/
------| store/

serverMiddleware ssr

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The ssr Property
Type:  boolean

Default:  true

Possible values:

true : Server-side rendering enabled

false : No server-side rendering (only client-side rendering)

You can set this option to  false  when you want only client side rendering

nuxt.config.js
export default {
ssr: false // Disable Server Side rendering
}

Previously,  mode  was used to disable or enable server-side rendering. Here is the  mode  documentation.

srcDir target

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The target Property
Deployment targets for Nuxt >= v2.13:

Type:  string

Default:  server

Possible values:

'server' : For server side rendering

'static' : For static sites

You can use this option to change default nuxt target for your project using  nuxt.config.js

To learn more about the target option check out the deployment targets section.

ssr telemetry

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
telemetry Property

The telemetry Property


Nuxt v2.13.0 introduces Nuxt Telemetry to collect anonymous telemetry data about general usage. This helps us to accurately gauge
Nuxt feature usage and customization across all our users.

Type:  Boolean

Default is based on your user preferences

Why collect Telemetry


Nuxt.js has grown a lot from its initial release (7 Nov 2016) and we are keep listening to community feedback to improve it.

However, this manual process only collects feedback from a subset of users that takes the time to fill the issue template and it may
have different needs or use-case than you.

Nuxt Telemetry collects anonymous telemetry data about general usage. This helps us to accurately gauge feature usage and
customization across all our users. This data will let us better understand how Nuxt.js is used globally, measuring improvements
made (DX and performances) and their relevance.

We collect multiple events:

Command invoked (nuxt dev, nuxt build, etc)

Versions of Nuxt.js and Node.js

General machine information (MacOS/Linux/Windows and if command is run within CI, the CI name)
Duration of the Webpack build and average size of the application, as well as the generation stats (when using nuxt generate)

What are the public dependency of your project (Nuxt modules)

The code is open source and available at https://github.com/nuxt/telemetry.

Opting-out
You can disable Nuxt Telemetry for your project with several ways:

. Using  npx nuxt telemetry disable

npx nuxt telemetry [status|enable|disable] [-g,--global] [dir]

. Using an environment variable

NUXT_TELEMETRY_DISABLED=1

. Setting  telemetry: false  in your  nuxt.config.js :

nuxt.config.js
export default {
telemetry: false
}

You can learn more about Nuxt Telemetry and the events sent on https://github.com/nuxt/telemetry

target transition
Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!
transition Properties

The pageTransition Property


Nuxt v2.7.0 introduces key "pageTransition" in favor of the "transition" key to consolidate the naming with layout transition keys.

Type:  String  or  Object

Used to set the default properties of the page transitions.

Default:

{
name: 'page',
mode: 'out-in'
}

nuxt.config.js
export default {
pageTransition: 'page'
// or
pageTransition: {
name: 'page',
mode: 'out-in',
beforeEnter (el) {
console.log('Before enter...');
}
}
}
The transition key in  nuxt.config.js  is used to set the default properties for the page transitions. To learn more about the available
keys when the  transition key is an object, see the pages transition property.

The layoutTransition Property


Type:  String  or  Object

Used to set the default properties of the layout transitions. The value provided in the  name  option is configured to work with the name
provided in  layout  from your  layouts  folder.

Default:

{
name: 'layout',
mode: 'out-in'
}

nuxt.config.js
export default {
layoutTransition: 'layout'
// or
layoutTransition: {
name: 'layout',
mode: 'out-in'
}
}
assets/main.css
.layout-enter-active,
.layout-leave-active {
transition: opacity 0.5s;
}
.layout-enter,
.layout-leave-active {
opacity: 0;
}

telemetry vue.config

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The vue.config Property
Type:  Object

Default:  { silent: !isDev, performance: isDev }

The vue.config property provides a direct configuration bridge for the  Vue.config

Example

nuxt.config.js
export default {
vue: {
config: {
productionTip: true,
devtools: false
}
}
}

This configuration will lead to the following Vue.config:

Vue.config.productionTip // true
Vue.config.devtools // false
Vue.config.silent // !isDev [default value]
Vue.config.performance // isDev [default value]

To learn more about the  Vue.config  API, check out the official Vue documentation
transition watch

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The watch Property
Type:  Object

Default:  []

The watch property lets you watch custom files for restarting the server.

watch: ['~/custom/*.js']

chokidar is used to set up the watchers. To learn more about chokidar's pattern options, see the chokidar API.

vue.config watchers

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!

SPONSOR Authentic Jobs — Your new development career awaits. Check out the latest listings.
The watchers Property
Type:  Object

Default:  {}

The watchers property lets you overwrite watchers configuration in your nuxt.config.js.

chokidar
Type:  Object

Default:  {}

To learn more about chokidar options, see the chokidar API.

webpack
Type:  Object

Default:

watchers: {
webpack: {
aggregateTimeout: 300,
poll: 1000
}
}
To learn more about webpack watchOptions, see the webpack documentation.

What's next

Check out the Internals Glossary book

watch  

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!


The Context
The  context  provides additional objects/params from Nuxt to Vue components and is available in special nuxt lifecycle areas
like  asyncData ,  fetch ,  plugins ,  middleware  and  nuxtServerInit .

Note: "The Context" we refer to here is not to be confused with the  context object available in  Vuex Actions . The two are unrelated.

function (context) {
// Universal keys
const {
app,
store,
route,
params,
query,
env,
isDev,
isHMR,
redirect,
error,
$config
} = context
// Server-side
if (process.server) {
const { req, res, beforeNuxtRender } = context
}
// Client-side
if (process.client) {
const { from, nuxtState } = context
}
}

Universal keys
These keys are available both on client-side and server-side.

app
app  (NuxtAppOptions)

The root Vue instance options that includes all your plugins. For example, when using  i18n , you can get access
to  $i18n  through  context.app.i18n .

store
store  (Vuex Store)

Vuex Store instance. Available only if the vuex store is set.

route
route  (Vue Router Route)

Vue Router route instance.


params
params  (Object)

Alias of  route.params .

query
query  (Object)

Alias of  route.query .

env
env  (Object)

Environment variables set in  nuxt.config.js , see env API.

isDev
isDev  (Boolean)

Boolean to let you know if you're in dev mode, can be useful for caching some data in production.

isHMR
isHMR  (Boolean)
Boolean to let you know if the method/middleware is called from webpack hot module replacement (true only on client-side in dev
mode).

redirect
redirect  (Function)

Use this method to redirect the user to another route, the status code is used on the server-side, defaults
to  302 .  redirect([status,] path [, query]) .

Examples:

redirect(302, '/login')
redirect({ name: 'slug', params: { slug: mySlug } })
redirect('https://vuejs.org')

See the Vue Router docs more info on the Location property.

It's not possible to use  redirect  or  error  in client-side Nuxt plugin due to hydration errors (client content would be different from what it'd
expect from the server).

A valid workaround would be using  window.onNuxtReady(() => { window.$nuxt.$router.push('/your-route') })

error
error  (Function)

Use this method to show the error page:  error(params) . The  params  should have the properties  statusCode  and  message .
$config

$config  (Object)

The actual runtime config.

Server-side keys
These keys are available only on the server-side.

req
req  (http.Request)

Request from the Node.js server. If Nuxt is used as a middleware, the request object might be different depending on the framework
you're using.
Not available via  nuxt generate .

Res
res  (http.Response)

Response from the Node.js server. If Nuxt is used as a middleware, the res object might be different depending on the framework
you're using.
Not available via  nuxt generate .

beforeNuxtRender
beforeNuxtRender(fn)  (Function)

Use this method to update  __NUXT__  variable rendered on client-side, the  fn (can be asynchronous) is called with  { Components,
nuxtState } , see example.

Client-side keys
These keys are available only on client-side.

from
from  (Vue Router Route)

The route navigated from.

nuxtState
nuxtState  (Object)

Nuxt state, useful for plugins which uses  beforeNuxtRender  to get the nuxt state on client-side before hydration. Available only
in  universal  mode.

  $nuxt: The Nuxt.js helper


$nuxt: The Nuxt.js helper
$nuxt  is a helper designed to improve user experience. For more info on the Nuxt.js helper check out the context and helpers
chapter in the Concepts book

Connection checker
isOffline

Type:  Boolean

Description:  true  when the user's internet connection becomes offline

isOnline

Type:  Boolean

Description: Opposite of  isOffline

layouts/default.vue
<template>
<div>
<div v-if="$nuxt.isOffline">You are offline</div>
<nuxt />
</div>
</template>

Refreshing page data


refresh()

When you want to only refresh the data provided by asyncData or fetch

example.vue
<template>
<div>
<div>{{ content }}</div>
<button @click="refresh">Refresh</button>
</div>
</template>

<script>
export default {
asyncData() {
return { content: 'Created at: ' + new Date() }
},
methods: {
refresh() {
this.$nuxt.refresh()
}
}
}
</script>

Controlling the loading bar


$loading
When you want to control Nuxt's loading bar programmatically

export default {
mounted() {
this.$nextTick(() => {
this.$nuxt.$loading.start()
setTimeout(() => this.$nuxt.$loading.finish(), 500)
})
}
}

The Context Nuxt Modules


Nuxt Modules Intro
Nuxt.js has a fully modular architecture which allows developers extending any part of Nuxt Core using a flexible API.

Please see Modules Guide for more detailed information if interested developing your own module.

This section helps getting familiar to Nuxt internals and can be used as a reference to understand it better while writing your own
modules.

Core
These classes are the heart of Nuxt and should exist on both runtime and build time.

Nuxt

Nuxt  Class

Source: core/nuxt.js

Renderer

Renderer  Class

Source: vue-renderer/renderer.js

ModuleContainer
ModuleContainer  Class

Source: core/module.js

Build
These classes are only needed for build or dev mode.

Builder

Builder  Class

Source: builder/builder.js

Generator

Generator  Class

Source: generator/generator.js

Common

Utils

Source: utils/src
Options

Source: config/options.js

Packaging & Usage


Nuxt exports all classes by default. To import them:

import { Nuxt, Builder, Utils } from 'nuxt'

Common patterns
All Nuxt classes have a reference to  nuxt  instance and options, this way we always have a consistent API across classes to
access  options  and  nuxt .

class SomeClass {
constructor(nuxt) {
super()
this.nuxt = nuxt
this.options = nuxt.options
}

someFunction() {
// We have access to `this.nuxt` and `this.options`
}
}
Classes are pluggable so they should register a plugin on main  nuxt  container to register more hooks.

class FooClass {
constructor(nuxt) {
super()
this.nuxt = nuxt
this.options = nuxt.options

this.nuxt.callHook('foo', this)
}
}

So we can hook into  foo  module like this:

nuxt.hook('foo', foo => {


// ...
})

$nuxt: The Nuxt.js helper Nuxt Class


The Nuxt Class
Source: core/nuxt.js

This is the core container which allows all modules and classes communicate with each other. All modules have access to Nuxt
instance using  this.nuxt .

Hooks
We can register hooks on certain life cycle events.

nuxt.hook('ready', async nuxt => {


// Your custom code here
})

Plugin Arguments When


ready (nuxt) Nuxt is ready to work ( ModuleContainer  and  Renderer ready).
error (error) An unhandled error when calling hooks.
close (nuxt) Nuxt instance is gracefully closing.
listen (server, {host, port}) Nuxt internal server starts listening. (Using  nuxt start or  nuxt dev ).

Nuxt Modules Renderer


The Renderer Class
Source: vue-renderer/renderer.js

This class is exporting a connect middleware which handles and serves all SSR and asset requests.

Hooks
We can register hooks on certain life cycle events.

Hook Arguments When


(renderer, Before setting up middleware and resources for the Renderer class, useful to overload some
render:before
options) methods or options.
(app) connect
render:setupMiddleware Before Nuxt adds its middleware stack. We can use it to register custom server side middleware.
instance
render:errorMiddleware
(app) connect Before adding Nuxt error middleware, useful to add your own middleware before using Nuxt's.
instance See the Sentry module for more info.
render:resourcesLoaded (resources) Called after resources for renderer are loaded (client manifest, server bundle, etc).
render:done (renderer) SSR Middleware and all resources are ready (Renderer ready)
Every time a route is server-rendered and before  render:route  hook. Called before serializing
render:routeContext (context.nuxt)
Nuxt context into  window.__NUXT__ , useful to add some data that you can fetch on client-side.
(url, result,
render:route Every time a route is server-rendered. Called before sending back the request to the browser.
context)
(url, result,
render:routeDone Every time a route is server-rendered. Called after the response has been sent to the browser.
context)

Nuxt Class Module Container


The ModuleContainer Class
Source: core/module.js

All modules will be called within context of  ModuleContainer  instance.

Tapable plugins
We can register hooks on certain life cycle events.

nuxt.moduleContainer.plugin('ready', async moduleContainer => {


// Do this after all modules where ready
})

Inside modules context we can use this instead:

this.plugin('ready', async moduleContainer => {


// Do this after all modules where ready
})

Plugin Arguments When


ready moduleContainer All modules in  nuxt.config.js  has been initialized

Methods
addVendor (vendor)
Deprecated as  vendor  isn't used anymore

Adds to  options.build.vendor  and apply unique filter.

addTemplate (template)

template:  String  or  Object

src

options

fileName

Renders given template using lodash template during build into project  buildDir ( .nuxt ).

If  fileName  is not provided or  template  is string, target file name defaults to  [dirName].[fileName].[pathHash].[ext] .

This method returns final  { dst, src, options }  object.

addPlugin (template)

template: Object properties ( src ,  options ,  fileName ,  mode ).

Registers a plugin using  addTemplate  and prepends it it to  plugins[]  array.

this.addPlugin({
src: path.resolve(__dirname, 'templates/foo.js'),
fileName: 'foo.server.js' // [optional] only include in server bundle
options: moduleOptions
})

Note: You can use  mode  or  .client  and  .server  modifiers with  fileName  option to use plugin only in client or server side.
(See plugins for all available options)

If you choose to specify a  fileName , you can configure a custom path for the  fileName  too, so you can choose the folder structure
inside  .nuxt  folder in order to prevent name collisioning:

{
fileName: path.join('folder', 'foo.client.js'), // will result in `.nuxt/folder/foo.client.js`
}

addServerMiddleware (middleware)
Pushes middleware into options.serverMiddleware.

extendBuild (fn)
Allows easily extending webpack build config by chaining options.build.extendfunction.

extendRoutes (fn)
Allows easily extending routes by chaining options.build.extendRoutes function.

addModule (moduleOpts, requireOnce)


Async function

Registers a module.  moduleOpts  can be a string or an array ( [src, options] ). If  requireOnce  is  true  and the resolved module
exports  meta , it prevents registering same module twice.

requireModule (moduleOpts)
Async function

Is a shortcut for  addModule(moduleOpts, true)

Hooks
We can register hooks on certain life cycle events.

Hook Arguments When


modules:before (moduleContainer, options) Called before creating ModuleContainer class, useful to overload methods and options.
modules:done (moduleContainer) Called when all modules have been loaded.

Renderer Builder
The Builder Class
Source: builder/builder.js

Hooks
We can register hooks on certain life cycle events.

// Add hook for build


this.nuxt.hook('build:done', (builder) => {
...
})

Hook Arguments When


build:before (nuxt, buildOptions) Before Nuxt build started
builder:prepared (nuxt, buildOptions) The build directories have been created
builder:extendPlugins (plugins) Generating plugins
({ templatesFiles,
build:templates Generating  .nuxt  template files
templateVars, resolve })
build:extendRoutes (routes, resolve) Generating routes
webpack:config (webpackConfigs) Before configuration of compilers
Before webpack compile (compiler is a webpack  Compiler  instance), if universal
build:compile        ({ name, compiler })
mode, called twice with name  'client'  and  'server'
build:compiled      ({ name, compiler, stats }) webpack build finished
build:done (nuxt) Nuxt build finished

Module Container Generator


The Generator Class
Source: generator/generator.js

Hooks
generate:  hooks:

Hook Arguments When


(generator,
generate:before Hook on before generation
generateOptions)
generate:distRemoved (generator) Hook on destination folder cleaned
generate:distCopied (generator) Hook on copy static and built files
Hook before generating the page, useful for dynamic payload, see #7422, available
generate:route ({ route, setPayload })
for Nuxt 2.13+
generate:page ({ route, path, html }) Hook to let user update the path & html after generation
generate:routeCreated ({ route, path, errors }) Hook on saving generated page success
generate:extendRoutes (routes) Hook to let user update the routes to generate
generate:routeFailed ({ route, errors }) Hook on saving generated page failure
generate:done (generator, errors) Hook on generation finished

Builder Using Nuxt Programmatically


Using Nuxt.js Programmatically
You might want to use your own server with your middleware and your API. That's why you can use Nuxt.js programmatically.

Nuxt Constructor
To see the list of options to give to Nuxt.js, see the configuration section.

const { loadNuxt, build } = require('nuxt')

// Check if we need to run Nuxt in development mode


const isDev = process.env.NODE_ENV !== 'production'

// Get a ready to use Nuxt instance


const nuxt = await loadNuxt(isDev ? 'dev' : 'start')

// Enable live build & reloading on dev


if (isDev) {
build(nuxt)
}

// We can use `nuxt.render(req, res)` or `nuxt.renderRoute(route, context)`

You can take a look at the nuxt-express and adonuxt starters to get started quickly.

Debug logs
If you want to display Nuxt.js logs, you can add the following to the top of your file:

process.env.DEBUG = 'nuxt:*'

Generator render
nuxt.render(req, res)
Type:  Function

Arguments:

. Request

. Response

Returns:  Promise

You can use Nuxt.js as a middleware with  nuxt.render  for your Node.js server.

Example with Express:

const { loadNuxt, build } = require('nuxt')

const app = require('express')()


const isDev = process.env.NODE_ENV !== 'production'
const port = process.env.PORT || 3000

async function start() {


// We get Nuxt instance
const nuxt = await loadNuxt(isDev ? 'dev' : 'start')

// Render every route with Nuxt.js


app.use(nuxt.render)

// Build only in dev mode with hot-reloading


if (isDev) {
build(nuxt)
}
// Listen the server
app.listen(port, '0.0.0.0')
console.log('Server listening on `localhost:' + port + '`.')
}

start()

It's recommended to call  nuxt.render  at the end of your middlewares since it will handle the rendering of your web application
and won't call  next()

Using Nuxt Programmatically renderRoute


nuxt.renderRoute(route, context)
Type:  Function

Arguments:

. String  : route to render

. Optional,  Object , context given, available keys:  req  &  res

Returns:  Promise

html :  String

error :  null  or  Object

redirected :  false  or  Object

Render a specific route with a given context.

This method should be used mostly for test purposes as well as with  nuxt.renderAndGetWindow .

nuxt.renderRoute  should be executed after the build process in production mode.

const { loadNuxt, build } = require('nuxt')

async function start() {


// Get nuxt instance for start (production mode)
// Make sure to have run `nuxt build` before running this script
const nuxt = await loadNuxt({ for: 'start' })
const { html, error, redirected } = await nuxt.renderRoute('/')

// `html` will always be a string

// `error` not null when the error layout is displayed, the error format is:
// { statusCode: 500, message: 'My error message' }

// `redirected` is not `false` when `redirect()` has been used in `asyncData()` or `fetch()`
// { path: '/other-path', query: {}, status: 302 }
}

start()

What's next

Check out the the Components Glossary book

render renderAndGetWindow
nuxt.renderAndGetWindow(url, options)
Type:  Function

Argument:  String

. String : URL to render

. Optional,  Object : options

virtualConsole:  Boolean  (default:  true )

Returns:  Promise

Returns:  window

Get the window from a given url of a Nuxt.js application.

This method is made for test purposes.

To use this function, you have to install  jsdom :

npm install --save-dev jsdom

Example:

const { loadNuxt } = require('nuxt')

async function init() {


// Assuming you've already built your project
const nuxt = await loadNuxt({ for: 'start' })
await nuxt.listen(3000)
const window = await nuxt.renderAndGetWindow('http://localhost:3000')
// Display the head `<title>`
console.log(window.document.title)
nuxt.close()
}

init()

renderRoute  
The Fetch Hook

Nuxt >= 2.12


Nuxt.js  v2.12  introduces a new hook called  fetch  which you can use in any of your Vue components. Use fetch every time you
need to get asynchronousdata.  fetch  is called on server-side when rendering the route, and on client-side when navigating.

It exposes  $fetchState  at the component level:

$fetchState.pending :  Boolean , allows you to display a placeholder when  fetch  is being called on client-side.

$fetchState.error :  null  or  Error , allows you to display an error message

$fetchState.timestamp :  Integer , is a timestamp of the last fetch, useful for caching with  keep-alive

If you want to call the  fetch  hook from your template use:

<button @click="$fetch">Refresh</button>

or component method:

// from component methods in script section


export default {
methods: {
refresh() {
this.$fetch()
}
}
}
You can access the Nuxt context within the fetch hook using  this.$nuxt.context .

Options

fetchOnServer :  Boolean  or  Function  (default:  true ), call  fetch()  when server-rendering the page

fetchKey :  String  or  Function  (defaults to the component scope ID or component name), a key (or a function that produces a
unique key) that identifies the result of this component's fetch (available on Nuxt 2.15+) More information available in original PR.

fetchDelay :  Integer  (default:  200 ), set the minimum executing time in milliseconds (to avoid quick flashes)

When  fetchOnServer  is falsy ( false  or returns  false ),  fetch  will be called only on client-side and  $fetchState.pending  will
return  true  when server-rendering the component.

<script>
export default {
data() {
return {
posts: []
}
},
async fetch() {
this.posts = await this.$http.$get('https://api.nuxtjs.dev/posts')
},
fetchOnServer: false,
// multiple components can return the same `fetchKey` and Nuxt will track them both separately
fetchKey: 'site-sidebar',
// alternatively, for more control, a function can be passed with access to the component instance
// It will be called in `created` and must not depend on fetched data
fetchKey(getCounter) {
// getCounter is a method that can be called to get the next number in a sequence
// as part of generating a unique fetchKey.
return this.someOtherData + getCounter('sidebar')
}
}
</script>

For more info on the Fetch Hook checkout the data fetching chapter of our Features book

  Head Method
The head Method
Nuxt.js uses vue-meta to update the  headers  and  html attributes  of your application.

Type:  Object  or  Function

Use the  head  method to set the HTML Head tags for the current page.

<template>
<h1>{{ title }}</h1>
</template>

<script>
export default {
data() {
return {
title: 'Hello World!'
}
},
head() {
return {
title: this.title,
meta: [
// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{
hid: 'description',
name: 'description',
content: 'My custom description'
}
]
}
}
}
</script>

To avoid duplicated meta tags when used in child component, set up a unique identifier with the  hid  key for your meta elements (read more).

Fetch Hook Key Property


The key Property
Set the  key  property of internal  <router-view>  component

Type:  String  or  Function

The  key  property is propagated into  <router-view> , which is useful to make transitions inside a dynamic page and different route.
Different keys result in re-rendering of page components.

There are several ways to set the key. For more details, please refer to the  nuxtChildKey  prop in the nuxt component.

export default {
key(route) {
return route.fullPath
}
}

Head Method Layout Property


The layout Property
Every file (first level) in the layouts directory will create a custom layout accessible with the layout property in the page component.

Type:  String  or  Function  (default:  'default' )

Use the  layout  key in your pages components to define which layout to use:

export default {
layout: 'blog',
// OR
layout(context) {
return 'blog'
}
}

Key Property Loading Property


The loading Property
The loading property gives you the option to disable the default loading progress bar on a specific page.

Type:  Boolean  (default:  true )

By default, Nuxt.js uses its own component to show a progress bar between the routes.

You can disable or customize it globally through the Configuration's loading option, but also disable it for specific pages by setting
the  loading  property to  false  :

<template>
<h1>My page</h1>
</template>

<script>
export default {
loading: false
}
</script>

Layout Property Middleware Property


The middleware Property
Type:  String  or  Array  or  Function

Items:  String  or  Function

Set the middleware for a specific page of the application.

Named middleware
You can create named middleware by creating a file inside the  middleware/ directory, the file name will be the middleware name.

middleware/authenticated.js
export default function ({ store, redirect }) {
// If the user is not authenticated
if (!store.state.authenticated) {
return redirect('/login')
}
}

pages/secret.vue
<template>
<h1>Secret page</h1>
</template>

<script>
export default {
middleware: 'authenticated'
}
</script>

Anonymous middleware
If you need to use a middleware only for a specific page, you can directly use a function for it (or an array of functions):

pages/secret.vue
<template>
<h1>Secret page</h1>
</template>

<script>
export default {
middleware({ store, redirect }) {
// If the user is not authenticated
if (!store.state.authenticated) {
return redirect('/login')
}
}
}
</script>

Loading Property Transition Property


The page `transition` Property
Nuxt.js uses the  <transition>  component to let you create amazing transitions/animations between your pages.

Type:  String  or  Object  or  Function

To define a custom transition for a specific route, simply add the  transition  key to the page component.

export default {
// Can be a String
transition: ''
// Or an Object
transition: {}
// or a Function
transition (to, from) {}
}

String
If the  transition  key is set as a string, it will be used as the  transition.name .

export default {
transition: 'test'
}

Nuxt.js will use these settings to set the component as follows:


<transition name="test"></transition>

Object
If the  transition  key is set as an object:

export default {
transition: {
name: 'test',
mode: 'out-in'
}
}

Nuxt.js will use these settings to set the component as follows:

<transition name="test" mode="out-in"></transition>

The  transition  object can have the following properties:

key Type Default definition


name String "page" The transition name applied on all the route transitions.
"out-
mode String
in" The transition mode applied on all routes, see Vue.js documentation.
Whether to apply CSS transition classes. Defaults to  true . If set to  false , will only trigger
css Boolean true
JavaScript hooks registered via component events.
duration Integer n/a The duration (in milliseconds) applied on the transition, see Vue.js documentation.
key Type Default definition
Specify the type of transition events to wait for to determine transition end timing. Available values
type String n/a are  "transition"  and  "animation" . By default, it will automatically detect the type that has a
longer duration.
enterClass String n/a The starting state of the transition class. See Vue.js documentation.
enterToClass String n/a The ending state for the transition. See Vue.js documentation.
enterActiveClass String n/a The class applied across the entire transition duration. See Vue.js documentation.
leaveClass String n/a The starting state of the transition class. See Vue.js documentation.
leaveToClass String n/a The ending state for the transition. See Vue.js documentation.
leaveActiveClass String n/a The class applied across the entire transition duration. See Vue.js documentation.
You can also define methods in the page  transition  property, these are for the JavaScript hooks:

beforeEnter(el)

enter(el, done)

afterEnter(el)

enterCancelled(el)

beforeLeave(el)

leave(el, done)

afterLeave(el)

leaveCancelled(el)

export default {
transition: {
afterLeave(el) {
console.log('afterLeave', el)
}
}
}

Note: it’s also a good idea to explicitly add  css: false  for JavaScript-only transitions so that Vue can skip the CSS detection. This
also prevents CSS rules from accidentally interfering with the transition.

Transition Mode
The default transition mode for pages differs from the default mode in Vue.js. The  transition  mode is by default set to  out-in .
If you want to run leaving and entering transitions simultaneously, you have to set the mode to the empty string  mode: '' .

export default {
transition: {
name: 'test',
mode: ''
}
}

Function
If the  transition  key is set as a function:

export default {
transition(to, from) {
if (!from) {
return 'slide-left'
}
return +to.query.page < +from.query.page ? 'slide-right' : 'slide-left'
}
}

Transitions applied on navigation:

/  to  /posts  =>  slide-left ,

/posts  to  /posts?page=3  =>  slide-left ,

/posts?page=3  to  /posts?page=2  =>  slide-right .

Middleware Property scrollToTop Property


The scrollToTop Property
The scrollToTop property lets you tell Nuxt.js to scroll to the top before rendering the page.

Type:  Boolean  (default:  false )

By default, Nuxt.js scrolls to the top when you go to another page, but with children routes, Nuxt.js keeps the scroll position. If you
want to tell Nuxt.js to scroll to the top when rendering your child route, set  scrollToTop  to  true :

<template>
<h1>My child component</h1>
</template>

<script>
export default {
scrollToTop: true
}
</script>

Conversely, you can manually set  scrollToTop  to  false  on parent routes as well.

If you want to overwrite the default scroll behavior of Nuxt.js, take a look at the scrollBehavior option.

Transition Property Validate Method


The validate Method
Nuxt.js lets you define a validator method inside your dynamic route component.

Type:  Function  or  Async Function

validate  is called every time before navigating to a new route. It will be called server-side once (on the first request to the Nuxt
app) and client-side when navigating to further routes. This method takes the  context  object as an argument.

validate({ params, query, store }) {


return true // if the params are valid
return false // will stop Nuxt.js to render the route and display the error page
}

async validate({ params, query, store }) {


// await operations
return true // if the params are valid
return false // will stop Nuxt.js to render the route and display the error page
}

You can also return promises:

validate({ params, query, store }) {


return new Promise((resolve) => setTimeout(() => resolve()))
}

Nuxt.js lets you define a validator method inside your dynamic route component (In this example:  pages/users/_id.vue ).
If the validate method does not return  true , Nuxt.js will automatically load the 404 error page.

export default {
validate({ params }) {
// Must be a number
return /^\d+$/.test(params.id)
}
}

You can also check some data in your store for example (filled by  nuxtServerInit  before action):

export default {
validate({ params, store }) {
// Check if `params.id` is an existing category
return store.state.categories.some(category => category.id === params.id)
}
}

You can also throw expected or unexpected errors during validate function execution:

export default {
async validate({ params, store }) {
// Throws a 500 internal server error with custom message
throw new Error('Under Construction!')
}
}
scrollToTop Property WatchQuery Property
The watchQuery Property
Watch query strings and execute component methods on change (asyncData, fetch(context), validate, layout, ...)

Type:  Boolean  or  Array  or  Function  (default:  [] )

Use the  watchQuery  key to set up a watcher for query strings. If the defined strings change, all component methods (asyncData,
fetch(context), validate, layout, ...) will be called. Watching is disabled by default to improve performance.

If you want to set up a watcher for all query strings, set  watchQuery: true .

export default {
watchQuery: ['page']
}

You can also use the function  watchQuery(newQuery, oldQuery)  to have more refined watchers.

export default {
watchQuery(newQuery, oldQuery) {
// Only execute component methods if the old query string contained `bar`
// and the new query string contains `foo`
return newQuery.foo && oldQuery.bar
}
}

Warning: The new  fetch  hook introduced in 2.12 is not affected by  watchQuery . For more information see listening to query string changes.
Validate Method  
Deploy Nuxt on Google App Engine
Deploying to Google App Engine is a fast and easy solution for hosting your universal Nuxt application on Google's Cloud Services.

In this guide, we build the application locally and then simply upload the entire project folder to Google App Engine. After the
upload, Google App Engine will automatically start the  start  script in our package.json and your app will be available immediately.

Getting Started
Make sure you have a Google Cloud Account, a project and an empty Google App Engine app set up on Google App Engine.
Furthermore, make sure to download and install the Cloud SDK (CLI) from Google as explained here and log into your Google Cloud
Account.

Configure your application


All you need to add to your universal Nuxt app for deploying it to the App Engine is a file called  app.yaml . Create a new file with
that name in your root project directory and add the following content:

runtime: nodejs10

instance_class: F2

handlers:
- url: /_nuxt
static_dir: .nuxt/dist/client
secure: always
- url: /(.*\.(gif|png|jpg|ico|txt))$
static_files: static/\1
upload: static/.*\.(gif|png|jpg|ico|txt)$
secure: always

- url: /.*
script: auto
secure: always

env_variables:
HOST: '0.0.0.0'

or for flexible environment the minimal configuration is:

runtime: nodejs
env: flex

Build and deploy the app


Now build your app with  npm run build .

At this point, your app is ready to be uploaded to Google App Engine. Now just run the following command:

gcloud app deploy app.yaml --project [project-id]

Voilà! Your Nuxt.js application is now hosted on Google App Engine!


Further Information
The  instance_class  attribute in your app.yaml file sets the class of your app instance. Instance F2 is not completely free, but has
the minimum memory needed to run a Nuxt application.

Make sure  start  in package.json is the command that you want to run after deployment. If you usually run by  start:prod  or
some other command, your app will not work as expected.

Make sure to put the  project-id  and not the  project-name  in the deploy command. These are two different things but easy to mix
up.

GitHub Google Cloud Run


Deploy Nuxt on Google Cloud Run
Google Cloud Run is a fully managed compute platform for deploying and scaling containerized applications quickly and securely.

In this guide, we simply upload the entire project folder to Google Cloud Build with a Dockerfile. After the upload, Cloud Build will
automatically generate a container. Then we will deploy this container to Google Cloud Run which will start it with the  start  script
in our package.json.

Getting Started
Make sure you have a Google Cloud Account, a project and the accesses as editor on Cloud Build and Cloud Run. Furthermore, make
sure to download and install the Cloud SDK (CLI) from Google as explained here and log into your Google Cloud Account. If you do
not want to download the Cloud SDK, be aware that you can use gcloud CLI from the Google Cloud Console.

Now, let's do few checks!

If the Cloud Build API and the Cloud Run API are not enabled, enable them:

# Enabling Cloud Build


$ gcloud services enable cloudbuild.googleapis.com

# Enabling Cloud Run


$ gcloud services enable run.googleapis.com

Go in your application directory and install dependencies:


# For yarn users
$ yarn

# For npm users


$ npm install

Start the application locally:

# For yarn users


$ yarn dev

# For npm users


$ npm run dev

Check that everything works.

Containerize your application


Now, we will create a container with Cloud Build.

You need to add to your Nuxt app a  Dockerfile . Create a new file named  Dockerfile  in your root project directory and add the
following content:

For yarn users:

FROM node:14

WORKDIR /usr/src/app
COPY . ./
RUN yarn

EXPOSE 8080

ENV HOST=0.0.0.0
ENV PORT=8080

RUN yarn build

CMD [ "yarn", "start" ]

For npm users:

FROM node:14

WORKDIR /usr/src/app

COPY . ./
RUN npm install

EXPOSE 8080

ENV HOST=0.0.0.0
ENV PORT=8080

RUN npm run build

CMD [ "npm", "run", "start" ]


Run the following command to start the build process:

gcloud builds submit --tag gcr.io/<YOUR_GOOGLE_CLOUD_PROJECT_ID>/my-nuxt-app-name:1.0.0 .

!Attention: if you want to implement continuous delivery or .env files configurations, you will have to use a Cloud Build
configuration file.

Deploying your application on Cloud Run


Run the following command to deploy your application:

gcloud run deploy --image=gcr.io/<YOUR_GOOGLE_CLOUD_PROJECT_ID>/my-nuxt-app-name:1.0.0 --platform managed --port 3000

Allow unauthenticated invocations if you want to set up a public access.

Be aware that Cloud Run applications will have a default concurrency value of 80 (each container instance will handle up to 80
requests at a time). You can specify the concurrency value this way:

gcloud run deploy --image=gcr.io/<YOUR_GOOGLE_CLOUD_PROJECT_ID>/my-nuxt-app-name:1.0.0 --platform managed --port 3000 --


concurrency <YOUR_CONCURRENCY_VALUE>

Run the following command to check if the deployment was created successfully:

gcloud run services list --platform managed

A list of Cloud Run services is displayed. Click on the URL of your deployment and enjoy the result!
Deploy Nuxt on Amazon Web Services
AWS stands for Amazon Web Services.
S3 is their static storage which can be configured for Static Site Hosting. CloudFront is their CDN (content delivery network)

AWS w/ the Amplify Console


Hosting a static generated Nuxt app on AWS w/ the Amplify Console is powerful and cheap.

First, push your Nuxt app to the Git provider of your choice. Then, visit the Amplify Console. Click the GET STARTED button under
the Deploy header if you haven't used Amplify Hosting before, otherwise click the Connect App button.

From your existing code


On the "From your existing code" page, select your Git provider and click Continue.

Add repository branch


On the "Add repository branch" page, select your repository and the branch you want to deploy. Then, click Next.

Configure build settings


On the "Configure build settings" page, click the  Edit  button under the "Build and test settings". Change the following:

. Set the build commands to  npm run generate .

. Set the  baseDirectory  location to be  dist .


The settings should look like this once you are done editing them:

version: 1
frontend:
phases:
preBuild:
commands:
- yarn install
build:
commands:
- npm run generate
artifacts:
# IMPORTANT - Please verify your build output directory
baseDirectory: dist
files:
- '**/*'
cache:
paths:
- node_modules/**/*

Then, click Save and Next.

Review
On the review page, click Save and deploy.

Then, your application will deploy. This may take a few minutes.

Once  Provision ,  Build ,  Deploy , and  Verify  are green, click on the URL that the Amplify Console provides to view your site.
AWS w/ S3 + CloudFront
Hosting a static generated Nuxt app on AWS w/ S3 + CloudFront is powerful and cheap.

AWS is a death by 1000 paper cuts. If we missed a step, please submit a PR to update this document.

Overview
We'll host super cheap with some AWS services. Briefly:

S3

cloud data "bucket" for our website files

can be configured to host static websites

CloudFront

a CDN (content delivery network)

offers free HTTPS certs

Makes your site load faster

We'll push the site like this:

Nuxt Generate -> Local folder -> AWS S3 Bucket -> AWS CloudFront CDN -> Browser
[ nuxt generate ] [ gulp deploy ]
[ deploy.sh ]
First, we'll generate the site with  nuxt generate (<= v2.12). Then, we'll use Gulp to publish the files to a S3 bucket and invalidate a
CloudFront CDN.

gulp

gulp-awspublish

gulp-cloudfront-invalidate-aws-publish

concurrent-transform (for parallel uploads)

Our deploy script needs these environment variables set:

AWS_BUCKET_NAME="example.com"

AWS_CLOUDFRONT="UPPERCASE"

AWS_ACCESS_KEY_ID="key"

AWS_SECRET_ACCESS_KEY="secret"

We'll have these files:

deploy.sh - run `nuxt generate` and `gulp deploy`


gulpfile.js - `gulp deploy` code to push files to S3 and invalidate CloudFront

Setting it up

. Make a S3 bucket and configure it for static site hosting

. Create a CloudFront distribution

. Configure security access


. Setup build script in your project

AWS: Setup your S3 bucket and CloudFront Distribution


Please follow this tutorial to setup your S3 and CloudFront for step one and two.

You should now have this data:

AWS_BUCKET_NAME="example.com"

AWS_CLOUDFRONT="UPPERCASE"

AWS: Configure security access


For step 3, we need to create a user that can:

Update the bucket contents

Invalidate the CloudFront distribution (propagates changes to users faster)

Create a programmatic user with this policy:

NOTE: replace 2x  example.com  with your S3 bucket name below. This policy allows pushing to the specified bucket, and invalidating
any CloudFront distribution.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": ["arn:aws:s3:::example.com"]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:DeleteObject",
"s3:ListMultipartUploadParts",
"s3:AbortMultipartUpload"
],
"Resource": ["arn:aws:s3:::example.com/*"]
},
{
"Effect": "Allow",
"Action": [
"cloudfront:CreateInvalidation",
"cloudfront:GetInvalidation",
"cloudfront:ListInvalidations",
"cloudfront:UnknownOperation"
],
"Resource": "*"
}
]
}
Then get an access key and secret.

You should now have this data:

AWS_ACCESS_KEY_ID="key"

AWS_SECRET_ACCESS_KEY="secret"

Laptop: Setup your project's build script


4.1) Create a  deploy.sh  script. See optional nvm (node version manager).

#!/bin/bash

export AWS_ACCESS_KEY_ID="key"
export AWS_SECRET_ACCESS_KEY="secret"
export AWS_BUCKET_NAME="example.com"
export AWS_CLOUDFRONT="UPPERCASE"

# Load nvm (node version manager), install node (version in .nvmrc), and npm install packages
[ -s "$HOME/.nvm/nvm.sh" ] && source "$HOME/.nvm/nvm.sh" && nvm use
# Npm install if not already.
[ ! -d "node_modules" ] && npm install

npm run generate


gulp deploy

4.2) Make  deploy.sh  runnable and DON'T CHECK INTO GIT (deploy.sh has secrets in it)
chmod +x deploy.sh
echo "
# Don't commit build files
node_modules
dist
.nuxt
.awspublish
deploy.sh
" >> .gitignore

4.3) Add Gulp to your project and to your command line

npm install --save-dev gulp gulp-awspublish gulp-cloudfront-invalidate-aws-publish concurrent-transform


npm install -g gulp

4.4) Create a  gulpfile.js  with the build script

const gulp = require('gulp')


const awspublish = require('gulp-awspublish')
const cloudfront = require('gulp-cloudfront-invalidate-aws-publish')
const parallelize = require('concurrent-transform')

// https://docs.aws.amazon.com/cli/latest/userguide/cli-environment.html

const config = {
// Required
params: {
Bucket: process.env.AWS_BUCKET_NAME
},
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
signatureVersion: 'v3'
},

// Optional
deleteOldVersions: false, // NOT FOR PRODUCTION
distribution: process.env.AWS_CLOUDFRONT, // CloudFront distribution ID
region: process.env.AWS_DEFAULT_REGION,
headers: {
/* 'Cache-Control': 'max-age=315360000, no-transform, public', */
},

// Sensible Defaults - gitignore these Files and Dirs


distDir: 'dist',
indexRootPath: true,
cacheFileName: '.awspublish',
concurrentUploads: 10,
wait: true // wait for CloudFront invalidation to complete (about 30-60 seconds)
}

gulp.task('deploy', function () {
// create a new publisher using S3 options
// http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property
const publisher = awspublish.create(config)

let g = gulp.src('./' + config.distDir + '/**')


// publisher will add Content-Length, Content-Type and headers specified above
// If not specified it will set x-amz-acl to public-read by default
g = g.pipe(
parallelize(publisher.publish(config.headers), config.concurrentUploads)
)

// Invalidate CDN
if (config.distribution) {
console.log('Configured with CloudFront distribution')
g = g.pipe(cloudfront(config))
} else {
console.log(
'No CloudFront distribution configured - skipping CDN invalidation'
)
}

// Delete removed files


if (config.deleteOldVersions) {
g = g.pipe(publisher.sync())
}
// create a cache file to speed up consecutive uploads
g = g.pipe(publisher.cache())
// print upload updates to console
g = g.pipe(awspublish.reporter())
return g
})

4.5) Deploy and debug

Run it:
./deploy.sh

You should get an output similar to this:

$ ./deploy.sh

Found '/home/michael/scm/example.com/www/.nvmrc' with version <8>


Now using node v8.11.2 (npm v5.6.0)

> example.com@1.0.0 generate /home/michael/scm/example.com/www


> nuxt generate

nuxt:generate Generating... +0ms


nuxt:build App root: /home/michael/scm/example.com/www +0ms
nuxt:build Generating /home/michael/scm/example.com/www/.nuxt files... +0ms
nuxt:build Generating files... +36ms
nuxt:build Generating routes... +10ms
nuxt:build Building files... +24ms
████████████████████ 100%

Build completed in 7.009s

DONE Compiled successfully in 7013ms

Hash: 421d017116d2d95dd1e3
Version: webpack 3.12.0
Time: 7013ms
Asset Size Chunks Chunk Names
pages/index.ef923f795c1cecc9a444.js 10.6 kB 0 [emitted] pages/index
layouts/default.87a49937c330bdd31953.js 2.69 kB 1 [emitted] layouts/default
pages/our-values.f60c731d5c3081769fd9.js 3.03 kB 2 [emitted] pages/our-values
pages/join-us.835077c4e6b55ed1bba4.js 1.3 kB 3 [emitted] pages/join-us
pages/how.75f8cb5bc24e38bca3b3.js 2.59 kB 4 [emitted] pages/how
app.6dbffe6ac4383bd30a92.js 202 kB 5 [emitted] app
vendor.134043c361c9ad199c6d.js 6.31 kB 6 [emitted] vendor
manifest.421d017116d2d95dd1e3.js 1.59 kB 7 [emitted] manifest
+ 3 hidden assets
Hash: 9fd206f4b4e571e9571f
Version: webpack 3.12.0
Time: 2239ms
Asset Size Chunks Chunk Names
server-bundle.json 306 kB [emitted]
nuxt: Call generate:distRemoved hooks (1) +0ms
nuxt:generate Destination folder cleaned +10s
nuxt: Call generate:distCopied hooks (1) +8ms
nuxt:generate Static & build files copied +7ms
nuxt:render Rendering url /our-values +0ms
nuxt:render Rendering url /how +67ms
nuxt:render Rendering url /join-us +1ms
nuxt:render Rendering url / +0ms
nuxt: Call generate:page hooks (1) +913ms
nuxt: Call generate:page hooks (1) +205ms
nuxt: Call generate:page hooks (1) +329ms
nuxt: Call generate:page hooks (1) +361ms
nuxt:generate Generate file: /our-values/index.html +2s
nuxt:generate Generate file: /how/index.html +0ms
nuxt:generate Generate file: /join-us/index.html +0ms
nuxt:generate Generate file: /index.html +0ms
nuxt:render Rendering url / +2s
nuxt: Call generate:done hooks (1) +4ms
nuxt:generate HTML Files generated in 11.8s +5ms
nuxt:generate Generate done +0ms
[21:25:27] Using gulpfile ~/scm/example.com/www/gulpfile.js
[21:25:27] Starting 'deploy'...
Configured with CloudFront distribution
[21:25:27] [cache] README.md
[21:25:27] [cache] android-chrome-192x192.png
[21:25:27] [cache] android-chrome-512x512.png
[21:25:27] [cache] apple-touch-icon.png
[21:25:27] [cache] browserconfig.xml
[21:25:27] [cache] favicon-16x16.png
[21:25:27] [cache] favicon-32x32.png
[21:25:27] [cache] favicon.ico
[21:25:27] [cache] favicon.svg
[21:25:27] [cache] logo-branches.svg
[21:25:27] [cache] logo-small.svg
[21:25:27] [cache] logo.svg
[21:25:27] [cache] mstile-150x150.png
[21:25:27] [cache] og-image.jpg
[21:25:27] [cache] safari-pinned-tab.svg
[21:25:27] [cache] site.webmanifest
[21:25:28] [create] _nuxt/manifest.421d017116d2d95dd1e3.js
[21:25:29] [update] 200.html
[21:25:30] [create] videos/flag.jpg
[21:25:30] [create] _nuxt/vendor.134043c361c9ad199c6d.js
[21:25:34] [create] videos/flag.mp4
[21:25:34] [cache] _nuxt/pages/how.75f8cb5bc24e38bca3b3.js
[21:25:34] [cache] _nuxt/pages/join-us.835077c4e6b55ed1bba4.js
[21:25:34] [cache] _nuxt/pages/our-values.f60c731d5c3081769fd9.js
[21:25:36] [update] our-values/index.html
[21:25:36] [create] _nuxt/layouts/default.87a49937c330bdd31953.js
[21:25:36] [create] _nuxt/app.6dbffe6ac4383bd30a92.js
[21:25:37] [create] _nuxt/pages/index.ef923f795c1cecc9a444.js
[21:25:38] [update] join-us/index.html
[21:25:38] [update] how/index.html
[21:25:43] [create] videos/flag.webm
[21:25:43] [update] index.html
[21:25:43] CloudFront invalidation created: I16NXXXXX4JDOA
[21:26:09] Finished 'deploy' after 42 s
DevBlogs
Startup Developers
Developer
Login

Technology

How we use Nuxt at The NuxtJS Company


Languages 

.NET

Platform Development
Debbie
October 22nd, 2020
Data Development
  

Nuxt.js is an open-source intuitive web framework based on Vue.js and node.js as well
as using powerful development tools such as babel, webpack, and postCSS. Nuxt.js was
created by brothers Alexandre Chopin and Sébastien Chopin while open sourcing their
code to build Vue.js applications with server-side rendering. The first commit for Nuxt.js
on Github was made on October 26th, 2016. Since then the Nuxt.js framework has
grown from 2 creators in 2016 to having 10 full-time employees at the NuxtJS company,
as well as the amazing Nuxt community with maintainers, ambassadors, and
contributors who dedicate their free time to helping improve the ecosystem by creating
modules and resources that can be helpful for everyone.

The Nuxtjs.org website which contains the framework documentation translated into 6


different languages has reached more than 200K monthly unique visitors over time.

Time to re-architect our website


Since the creation of the framework, a lot of new features were added. Resources such
as modules, themes, and their documentation had increased. We felt the time had come
to re-architect our website to make it easier to learn Nuxt and find resources, for all
levels from a beginner to an expert developer. We worked on the documentation for
almost 3 months and had endless pages in a text editor with all these new docs and
code examples.

However, what happens when you work on an ongoing project? Things keep changing.
So we were updating our actual documentation as well as our new docs in the text
editor. This alone was not ideal and as time went on it was getting tedious to update
things in two places. When the engineering team tells you it will be the last major
release it doesn’t always mean it will be the last release. This is open source
programming after all.

The old stack issue


We couldn’t just replace the new docs with the old ones as the whole documentation
had been revamped. Redirecting from the old page to a new one wasn’t a solution
because the content had been completely restructured and some pages content had
been merged into others. We also couldn’t replace the old docs as we wanted to make
sure that developers could still easily find what they needed without having to figure
out where things now lived in the new docs. And also we only had the English version
complete so we couldn’t remove the old docs as our website supports multiple
languages.

Adding a Beta Documentation


Our solution was to create a new link in the header that links to the new docs and in the
old docs create an alert to let people know that we have better and improved docs and
where to find them. But how our docs were set up was not ideal. The developer

experience wasn’t the best and our architecture worked but wasn’t very developer-
friendly. It was time to rethink how our content API worked.

The Content module


At the NuxtJS company, we decided to transform our docs repository into a Nuxt
module. This is how the Content Module, which allows you to easily add markdown files
to your Nuxt.js project as well as use Vue components inside your markdown, was born.
This means by adding this module to our website repository, we didn’t need to have 2
separate repos: the website repo for the design and the docs repo for the content API.
Perfect!

As the content module was new we needed to test things out to see if it was going to
do what we wanted it to do and if not we needed to modify the module for our use
case. To give you an idea of how popular this module was it has had 57,000 downloads
since its release 3 months ago. Making changes to the module to suit our needs wasn’t
an easy task as we had to make sure not to add any breaking changes when adding
improvements.

Content Module Stats:

We, therefore, created a proof of concept and keeping the same look and feel as the
site we had, we copied over all the site and started deleting things we didn’t need such
as the built-in server, the store for the navigation and the markdown plugins, and then
error by error started to fix what was broken.

Migrate our data to the new stack


The small job of just adding the new docs was now bigger than we thought. However, it
showed us that although there was a bit of work upfront it was going to make not just
our lives easier but also those who were contributing to our documentation or writing
blog posts on our site. When it comes to contributions the Nuxt.js website has had
many contributors over time, as can be seen in the chart below:

Once our proof of concept had been created we decided it was the right decision so we
started to move everything to the dev branch of our Nuxtjs.org website and recreate
our proof of concept.

Time for improvements 


Then it was time to polish things off and improve things we weren’t happy with. For
example, we installed the nuxt-i18n module to handle translations instead of custom
integration. We also automated some actions by adding needed features to the content

module. For example, by using the content module we could automatically create the
navigation based on the files we added into the folders. We could then add a menu
property into the yaml at the top of the markdown file so that the navigation could be
based on the title or if the title was too long we could use the menu property.

We had to make various improvements to the content module so that things could
work exactly how we wanted them to, such as being able to search within folder
structures for example. This improved the module not just for us but also for all our
users. We soon realized that adding this module was seriously making our lives easier as
the content module also included a live edit feature which meant we could review in
development and make changes directly in the browser by double-clicking the content
whenever we spotted a mistake or something that was missing.

Asynchronous development
Of course, it wasn’t just the new docs that we had added using the content module but
the whole site. That meant a lot of refactoring of the main website pages plus all the old
docs, including all languages, which now had to have a YAML front matter block at the
top of each markdown page with the category name and position so it would be
positioned correctly in the navigation. Although the only change was the architecture
and the addition of the new docs, this was still a tedious task especially seen as we had
6 languages to maintain, but it had to be done.

Now came the real challenge. Pull requests were constantly being made as our
documentation is open source. We were now accepting the pull requests on the old
docs repo and at the same time adding these minor changes to the markdown files on
the dev branch. People were translating our old docs and we were still in the review
process of the new docs which made us feel bad as people were working on docs that
were soon going to be nonexistent. But at the same time, we couldn’t release the new
docs until we were sure that a minimum standard had been achieved and that the site
was production-ready.

Continuous code improvement


While working on the docs we saw that our 3 year old project standards didn’t fit
anymore, mostly because our focus had been on the framework development. However,
since the NuxtJS company got funded, Alexandre and Sébastien Chopin, the founders of
Nuxt, built a team of people who could work full-time and make sure all these things
were covered. We already had ESLint set up using the nuxt package but that was it.
People could still submit a console.log to the code and it would make it to production,
so we needed to fix this.

Lint-staged is a great tool and lints all your staged files and we added linting not just for
JavaScript but also for our markdown and styles. We also added Prettier to make sure
our code looked the same no matter who had written it. This took quite some time to
configure as some of the Prettier rules were clashing with the ESLint rules and to be
honest there is still an ongoing discussion as to if we should use both of these packages
or not. We also added Husky so we could make sure all this linting was done on pre-
commit meaning before someone made a commit these linters would run and alert the
developer of any issues before being able to push any changes.

Time to add Tests


Before we were not testing anything on our website. It really was just a small website
with documentation so was it really important? It wasn’t until we added a link to our
submit newsletter button, so we could better promote it on twitter, did we realise that
the submit button wasn’t working after we had updated a module. Nobody had
changed the code on our website so how would anyone have known that this was not
working. A test would have picked this up. Luckily we discovered it manually just after
releasing the tweet and it showed us that it was time to add tests to our website.

For testing we decided to add end-to-end tests and we opted for Cypress io as it is a
For testing we decided to add end to end tests and we opted for Cypress.io as it is a
great way of testing these types of scenarios, when a user inputs an email address for
example. We also wanted to make sure things like our previous and next links worked,
our navigation, and anything that involved the user clicking so that we didn’t have to
manually test this and could have the confidence that it all worked as it should. We
didn’t spend that much time adding tests and it is still an ongoing task as we realized
other things could also be tested but we also couldn’t hold off on releasing the docs
just because the tests hadn’t been written.

Live it is
Our website was now ready to go live with a whole complete architecture, yet this was
just the release of the new docs. We had set the project up with a solid architecture that
provides us modularity to maintain and improve our website easily. The only thing we
will have to change for the new design is to create new components or modify the
styles and possibly some functionality. As we are using Tailwind for our CSS this means
we can easily change our colour scheme through the config and then just update the
styles when needed. This wasn’t going to be a difficult task. We could easily work on a
dev branch and still accept pull requests to our documentation as all texts were now in
a content folder meaning it was easy to merge any changes to texts and translations as
our code and our content were completely separate.

When we went to merge, the dev branch was 241 commits ahead, 16 commits behind
the main branch. We merged it at 7 pm on a Monday as two members of the NuxtJS
team had talks to give at conferences and we needed to release the latest version of
Nuxt and we couldn’t release it without releasing the new docs. We released and hoped
for the best and found a few things that needed fixing but other than that it was all
good, or so we thought.

Mistakes we made
In an ideal world, we would go live when everything is ready, when we have
implemented a new design, added all the content, and created all the tests. However,
that was not the case. We needed to release the new documentation with the new
architecture first so that is was easier to maintain. And when we did, we found out a day
later that the Japanese version was not working. The language selector was pointing to
a different iso code. We hadn’t written the tests for it yet. Luckily we found it as it is very
important to us to not break existing translations.

Things we got right


We found that on releasing it was much easier for our translators to work on the new
docs. Before you had to clone two repos and run one repo inside another and now you
simply have to clone one repo and add the folder for your language, add the .env
variable for the language you want to see and start translating.

Before it wasn’t possible to translate all the pages as it hadn’t been properly set up and
there were a lot of markdown files for each component which made it hard to manage.
Now we had a language file with all translations for that particular language and by just
translating that file all pages such as the home, shop, support, etc would be translated.
It also meant that the pull requests were much easier to review as you were just
reviewing the i18n file and the content folder for that language when translations were
being made. This means that we can now encourage more people to help us translate
our docs and also add other languages that were not there before.

We are also working on more content, not just adding documentation but also adding
things like a resources section to showcase all the Nuxt modules that people can use to
enhance their site. Thanks to our new architecture it is really easy to create new content
on a feature branch and when finished, easily merge this new content and release it to
the world. When you create a great developer experience it makes you want to improve
and add more things to the site and that is a feeling we did not have with the old
architecture.

Conclusion
Proof of concepts are a great way of testing out what needs to be done when re-
architecting a site. Many people make the mistake of just trying to get it done without
first thinking it through and overcoming the problems in the early stages. At the NuxtJS
company we built the content module as we needed a better solution for our website.
We found that adding linters helps in making sure code is the same across teams as well
as helping in finding errors and making sure your code not just looks better but also
abides by the correct standards. Adding linters to an already created project is a task in
itself but is very much worth doing.

Testing is important and we never have time to test. I still have to add that test for the
language selector. When is the right time to add it? When it breaks again? We need to
prioritize things better. I guess you could say the job is never done, there are always
more things to improve, there is never a finished project and there is no perfect
solution. But sometimes you do have to take a step back, look at what you have done,
and take pride in the work you have achieved. Then you can set new goals, a new road-
map, and perhaps that test that never got written might just make it onto the next list of
tasks.

Summary of tools we used


Nuxt.js for framework with target ‘static’

nuxt-content for content

nuxt-i18n for internationalization

Cypress for testing

nuxt-tailwind for our CSS

nuxt-ESLint for linting

Markdownlint for linting markdown

Stylelint for linting styles

Prettier for code formatting

Husky for pre-commit hooks

Lint-staged for linting only staged files

Debbie O'Brien
Head of Learning and Developer Advocate at NuxtJS

Follow      

Posted in CTO Cookbook Startups Web

Tagged architecture nuxt

Read next

Our startup journey with Azure Functions, Moving from servers to server(less)
GraphQL, and React Akari’s cloud-native journey spanned 12 months, moving
In this article, the CTO of CorLife writes about the from servers to serverless for core applications. In this
architectural guidelines and principles that helped his article we’ll be talking about what we wish we did,
team ship high quality code as quickly as possible while development considerations for bootstrapping a project,
supporting the general operation of the platform. ops and observability ups and downs, and how we
optimize cost across our platform.
Ravi Nar January 12, 2021
Tom Hind January 19, 2021
0 comment
0 comment

0 comments
Comments are closed. Login to edit/delete your existing comments

Top Bloggers

Ruth Yakubu
Senior Cloud Advocate

Simona Cotin
Principal Cloud Advocate, DevRel

Jonathan Saring

Christopher Maneu
Startups Cloud Advocate

Tom Hind
Chief Technology Officer at Akari

Topics

Startups
CTO Cookbook
Web
Tech Exceptions
AI/ML

Archive

March 2021
February 2021
January 2021
October 2020
Stay informed

What's new Microsoft Store Education Enterprise Developer Company


Surface Duo Account profile Microsoft in education Azure Microsoft Visual Studio Careers

Surface Laptop Go Download Center Office for students AppSource Windows Dev Center About Microsoft

Surface Pro X Microsoft Store support Office 365 for schools Automotive Developer Center Company news

Surface Go 2 Returns Deals for students & Government Microsoft developer Privacy at Microsoft
parents program
Surface Book 3 Order tracking Healthcare Investors
Microsoft Azure in Channel 9
Microsoft 365 Virtual workshops and education Manufacturing Diversity and inclusion
training Microsoft 365 Dev Center
Windows 10 apps Financial services Accessibility
Microsoft Store Promise Microsoft 365 Developer
HoloLens 2 Retail Program Security
Financing
Microsoft Garage

 English (United States) Sitemap Contact Microsoft Privacy Terms of use Trademarks Safety & eco About our ads © Microsoft 2021
How To Build A Music Manager With Nuxt.js And
Express.js
This article introduces how Multer streamlines the process of handling file uploads. It also
introduces how to use Mongoose to interact with our database by building a music manager
app using Express.js alongside Multer for the music upload and Nuxt.js (Vue framework) for
our frontend.

Handling digital media assets such as audio and video in your application can be tricky because of
the considerations that have to be made server-side (e.g. networking, storage and the asynchronous
nature of handling file uploads). However, we can use libraries like Multer and Express.js to simplify
our workflow on the backend while using Nuxt.js (Vue framework) to build out the front-end
interactions.

Whenever a web client uploads a file to a server, it is generally submitted through a form and
encoded as multipart/form-data . Multer is a middleware for Express.js and Node.js that makes it easy to handle this so-
called multipart/form-data whenever your users upload files. In this tutorial, I will explain how you can build a music
manager app by using Express.js with Multer to upload music and Nuxt.js (Vue framework) for our frontend.

PREREQUISITES

Familiarity with HTML, CSS, and JavaScript (ES6+);

Node.js, npm and MongoDB installed on your development machine;


VS code or any code editor of your choice;

Basic Knowledge of Express.js.

Building The Back-End Service


Let’s start by creating a directory for our project by navigating into the directory, and issuing npm init -y on your terminal
to create a package.json file that manages all the dependencies for our application.

mkdir serverside && cd serverside


npm init -y

Next, install multer , express , and the other dependencies necessary to Bootstrap an Express.js app.

npm install express multer nodemon mongoose cors morgan body-parser --save

Next, create an index.js file:

touch index.js

Then, in the index.js file, we will initialize all the modules, create an Express.js app, and create a server for connecting to
browsers:
const express = require("express");
const PORT = process.env.PORT || 4000;
const morgan = require("morgan");
const cors = require("cors");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const config = require("./config/db");
const app = express();
//configure database and mongoose
mongoose.set("useCreateIndex", true);
mongoose
.connect(config.database, { useNewUrlParser: true })
.then(() => {
console.log("Database is connected");
})
.catch(err => {
console.log({ database_error: err });
});
// db configuaration ends here
//registering cors
app.use(cors());
//configure body parser
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
//configure body-parser ends here
app.use(morgan("dev")); // configire morgan
// define first route
app.get("/", (req, res) => {
res.json("Hola MEVN devs...Assemble");
});
app.listen(PORT, () => {
console.log(`App is running on ${PORT}`);
});
We, first of all, bring in Express.js into the project and then define a port that our application will be running on. Next, we
bring in the body-parser , morgan , mongoose and the cors dependencies.

We then save the express instance in a variable called app . We can use the app instance to configure middleware in our
application just as we configured the cors middleware. We also use the app instance to set up the root route that will run
in the port we defined.

Let’s now create a /config folder for our database config and multer config:

mkdir config and cd config


touch multer.js && touch db.js

Then open config/db.js and add the following code to configure our database:

module.exports = {
database: "mongodb://localhost:27017/",
secret: "password"
};

(This is actually an object that holds the database URL and the database secret.)

Running nodemon and navigating to localhost:4000 on your browser should give you this message:

"Hola MEVN devs...Assemble"

Also, this is what your terminal should now look like:


Terminal preview (Large preview)

Setting Up Model, Routes, And Controllers


Let’s set up a file structure by typing in the following:

mkdir api && cd api


mkdir model && cd model && touch Music.js
cd ..
mkdir controller && cd controller && touch musicController.js
cd ..
mkdir routes && cd routes && touch music.js

In our terminal, we use mkdir to create a new directory, and then cd to move into a directory. So we start by creating a
directory called api and then move into the api directory.

The touch command is used to create a new file inside a directory using the terminal, while the cd command is used to
move out of a directory.

Now let’s head on over to our api/model/Music.js file to create a music schema. A model is a class with which we
construct documents. In this case, each document will be a piece of music with properties and behaviors as declared in
our schema:
let mongoose = require("mongoose");
let musicSchema = mongoose.Schema({
title: {
type: String,
required: true
},
music: {
type: Object,
required: true
},
artist: {
type: String,
required: true
},
created: {
type: Date,
default: Date.now()
}
});
let Music = mongoose.model("Music", musicSchema);
module.exports = Music;

Let’s head over to config/multer to configure Multer:


let multer = require("multer");
const path = require("path");
const storage = multer.diskStorage({
destination: (req, res, cb) => {
cb(null, "./uploads");
},
filename: (req, file, cb) => {
cb(null, new Date().toISOString() + file.originalname);
}
});
const fileFilter = (req, file, cb) => {
if (
file.mimetype === "audio/mpeg" ||
file.mimetype === "audio/wave" ||
file.mimetype === "audio/wav" ||
file.mimetype === "audio/mp3"
) {
cb(null, true);
} else {
cb(null, false);
}
};
exports.upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5
},
fileFilter: fileFilter
});
In the multer.js file, we start by setting up a folder where all the uploaded music files will be uploaded. We need to make
this file static by defining that in the index.js file:

app.use('/uploads', express.static('uploads'));

After that, we write a simple validator that will check the file mimetype before uploading. We then define the multer
instance by adding the storage location, the limits of each file, and the validator that we created.

CREATE THE NECESSARY ROUTES

Now let’s create our routes. Below is the list of endpoints we will be creating.

HTTP POST /music Add new music

HTTP GET /music Get all music

HTTP DELETE /music/:blogId Delete a music

Let’s start by creating the blog route. Head over to api/routes/music.js and write the following code:
const express = require("express");
const router = express.Router();
const musicController = require("../controller/musicController");
const upload = require("../../config/multer");
router.get("/", musicController.getAllMusics);
router.post("/", upload.upload.single("music"), musicController.addNewMusic);
router.delete("/:musicId", musicController.deleteMusic);
module.exports = router;

Note: Now whenever we make a get request to /music . the route calls the getAllMusic function that is located in the
‘controllers’ file.

Let’s move on over to api/controllers/musicController to define the controllers. We start by writing a function to get all
the music in our database using the mongoose db.collection.find method which will return all the items in that
collection.

After doing that, we write another function that will create a piece of new music in the database. We need to create a new
music instance using the new keyword and then define the music object. After doing this, we will use the mongoose save
method to add new music to the database.

In order to delete a piece of music, we need to use the mongoose remove method by simply passing the music ID as a
parameter in the remove instance. This results to mongoose looking into the music collection that has that particular ID
and then removing it from that collection.
let mongoose = require("mongoose");
const Music = require("../model/Music");
exports.getAllMusics = async (req, res) => {
try {
let music = await Music.find();
res.status(200).json(music);
} catch (err) {
res.status(500).json(err);
}
};
exports.addNewMusic = async (req, res) => {
try {
const music = new Music({
title:req.body.title,
artist:req.body.artist,
music:req.file
});

let newMusic = await music.save();


res.status(200).json({ data: newMusic });
} catch (err) {
res.status(500).json({ error: err });
}
};
exports.deleteMusic = async (req, res) => {
try {
const id = req.params.musicId;
let result = await Music.remove({ _id: id });
res.status(200).json(result);
} catch (err) {
res.status(500).json(err);
}
};
Last but not least, in order to test the routes, we need to register the music routes in our index.js file:

const userRoutes = require("./api/user/route/user"); //bring in our user routes


app.use("/user", userRoutes);

Testing The End Points


To test our endpoints, we will be using POSTMAN.

ADDING NEW MUSIC

To test the Add Music functionality, set the method of the request by clicking on the methods drop-down. After doing this,
type the URL of the endpoint and then click on the body tab to select how you want to send your data. (In our case, we
will be using the form-data method.)

So click on the form-data and set up your model key. As you set it up, give the keys some value as shown in the image
below:

Testing Adding new music API in Postman dashboard (Large preview)


After doing this, click on ‘Send’ to make the request.

LISTING ALL MUSIC

To list all of the music in our database, we have to type the endpoint URL in the URL section provided. After doing this,
click on the ‘Send’ button to make the request.

Testing Listing API in Postman dashboard (Large preview)

DELETING MUSIC

To delete a piece of music, we need to pass the music id as a parameter.

Testing Delete API Postman dashboard (Large preview)

That’s it!
Building The Frontend
For our frontend, we will be using a Vue framework: Nuxt.js.

“Nuxt is a progressive framework based on Vue.js to create modern web applications. It is based on Vue.js official
libraries (vue, vue-router and vuex) and powerful development tools (webpack, Babel and PostCSS).”

— NuxtJS Guide

To create a new Nuxt.js application, open up your terminal and type in the following (with musicapp as the name of the
app we will be building):

$ npx create-nuxt-app musicapp

During the installation process, we will be asked some questions regarding the project setup:

Project name musicapp

project description A Simple music manager app

Author name <your name>

Package manager npm

UI framework Bootstrap vue

custom ui framework none


Nuxt modules Axios,pwa (use the spacebar on your keyboard to select items)

Linting tool Prettier

test framework None

Rendering Mode Universal (SSR)

development tool Jsonconfig.json

After selecting all of this, we have to wait a little while for the project to be set up. Once it’s ready, move into the /project
folder and serve the project as follows:

cd musicapp && npm run dev

Open up the project in any code editor of your choice and then open the project in the browser by accessing
localhost:3000 .

Nuxt.js Project Preview (Large preview)


Configuring Axios
We will be using axios to make an HTTP request to our back-end server. Axios is already installed in our project, so we
just have to configure the baseURL - to our backend server.

To do this, open the nuxt.config.js file in the root directory and add the baseURL in the axios object.

axios: {
baseURL:'http://localhost:4000'
},

Building The Music Manager

SETTING UP THE UI

Let’s start by cleaning up the UI. Open up the pages/index.vue file and remove all of the code in there with the following:

<template>
<div>Hello</div>
</template>

After doing this, you should only be able to see a “Hello” in the browser.

In the root directory, create a /partials folder. Inside the /partials folder, create a navbar.vue file and add the
following code:
<template>
<header>
<nav class="navbar navbar-expand-lg navbar-light bg-info">
<div class="container">
<a class="navbar-brand" href="#">Music App</a>
<button
class="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarNav"
aria-controls="navbarNav"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#">Player</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Manager</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
</template>
<style scoped>
.nav-link,
.navbar-brand {
color: #ffff !important;
}
</style>

Note: We will be using the component to navigate through pages in our application. This is just going to be a simple
component made up of Bootstrap navbar . Check out the official Bootstrap documentation for more reference.

Next, let’s define a custom layout for the application. Open the /layouts folder, replace the code in the default.vue file
with the code below.

<template>
<div>
<navbar />
<nuxt />
</div>
</template>
<script>
import navbar from '@/partial/navbar'
export default {
components: {
navbar
}
}
</script>

We import the navbar into this layout, meaning that all the pages in our application will have that navbar component in it.
(This is going to be the component that all other component in our application will be mounted.)

After this, you should be able to see this in your browser:


Nuxt.js Navbar component (Large preview)

Now let’s setup the UI for our manager. To do this, we need to create a /manager folder within the components folder and
then add a file into the folder named manager.vue.

In this file, add the following code:

<template>
<section class="mt-5">
<div class="container mb-4">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-body">
<div class="card-title mb-4">
<h4>Add Music</h4>
</div>
<form>
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" />
</div>
<div class="form-group">
<label for="artist">Artist</label>
<input type="text" class="form-control" />
</div>
<div class="form-group">
<label for="artist">Music</label>
<label for= artist >Music</label>
<div class="custom-file">
<input type="file" class="custom-file-input" id="customFile" />
<label class="custom-file-label" for="customFile">Choose file</label>
</div>
</div>
<div class="form-group">
<button class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="card bg-light p-1 showdow-sm">
<div class="card-title">
<button class="btn btn-info m-3">Add Music</button>
</div>
<div class="card-body">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Title</th>
<th scope="col">Artist</th>
<th scope="col">Date created</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Demo Title</td>
<td>Wisdom.vue</td>
<td>12/23/13</td>
<td>
<button class="btn btn-info">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</section>
</template>

Note: This is just a simple Bootstrap template for adding music into our application. The form will define a table template
that will list all os the music that can be found in our database.

After defining this component, we need to register it in the /pages folder to initailize routing.

Nuxt.js doesn’t have a ‘router.js’ file like Vue.js. It uses the pages folder for routing. For more details, visit the Nuxt.js website.

To register the component, create a /manager folder within the /pages folder and create an index.vue file. Then, place the
following code inside the file:
<template>
<div>
<manager />
</div>
</template>
<script>
import manager from '@/components/manager/manager'
export default {
components: {
manager
}
}
</script>

This is the component that will render in our pages route.

After doing this, head over to your browser and navigate to /manager — you should be seeing this:

Music manager UI (Large preview)

Listing All Music


Let’s continue by creating a function that will fetch all of the music. This function will be registered in the created life cycle
hook, so that whenever the component is created, the function will be called.
Let’s start by creating a variable in the vue instance that will hold all of the music:

allmusic = [];
musicLoading: false,

Then, define a getAllMusics function and add the following code:

async getAllMusics() {
this.musicLoading = true
try {
let data = await this.$axios.$get('/music')
this.allmusic = data
this.musicLoading = false
} catch (err) {
this.musicLoading = false
swal('Error', 'Error Fetting Musics', 'error')
}
}

Next, register within the created life cycle hook:

created() {
this.getAllMusics()
}

Outputting The Data


Now it’s time to output all of the songs on the table which we’ve created earlier:

<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Title</th>
<th scope="col">Artist</th>
<th scope="col">Date created</th>
<th scope="col">Action</th>
</tr>
</thead>
<div
v-if="musicLoading"
class="spinner-border"
style="width: 3rem; height: 3rem;"
role="status"
>
<span class="sr-only">Loading...</span>
</div>
<tbody v-else>
<tr v-for="(music, index) in allmusic" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ music.title }}</td>
<td>{{ music.artist }}</td>
<td>{{ music.created }}</td>
<td>
<button class="btn btn-info" @click="deleteMusic(music._id)">Delete</button>
</td>
</tr>
</tbody>
</table>
Remember that table we created earlier? Well, we will need to loop through the response we get back from our backend
to list all of the music received back from the database.

Adding Music
To add a new piece of music we need to make an HTTP request to the back-end server with the music details. To do this,
let’s start by modifying the form and handling of the file uploads.

On the form, we need to add an event listener that will listen to the form when it is submitted. On the input field, we add
a v- model to bind the value to the input field.
<form @submit.prevent="addNewMusic">
<div class="form-group">
<label for="title">Title</label>
<input type="text" v-model="musicDetails.title" class="form-control" />
</div>
<div class="form-group">
<label for="artist">Artist</label>
<input type="text" v-model="musicDetails.artist" class="form-control" />
</div>
<div class="form-group">
<label for="artist">Music</label>
<div class="custom-file">
<input
type="file"
id="customFile"
ref="file"
v-on:change="handleFileUpload()"
class="custom-file-input"
/>
<label class="custom-file-label" for="customFile">Choose file</label>
</div>
</div>
<div class="form-group">
<button class="btn btn-primary" :disabled="isDisabled">
<span
class="spinner-border spinner-border-sm"
v-if="addLoading"
role="status"
aria-hidden="true"
></span>Submit
</button>
</div>
</form>
And the script section should look like this:

<script>
export default {
data() {
return {
musicDetails: {
title: '',
artist: '',
music: ''
},
allmusic = [],
musicLoading: false,
isValid: false;
addLoading: false,
}
},
computed: {
isDisabled: function() {
if (
this.musicDetails.title === '' ||
this.musicDetails.artist === '' ||
this.musicDetails.music === ''
) {
return !this.isValid
}
}
},
methods: {
handleFileUpload() {
this.musicDetails.music = this.$refs.file.files[0]
console.log(this.musicDetails.music.type)
},
addNewMusic() {
let types = /(\.|\/)(mp3|mp4)$/i
if (
types.test(this.musicDetails.music.type) ||
types.test(this.musicDetails.music.name)
) {
console.log('erjkb')
} else {
alert('Invalid file type')
return !this.isValid
}
}
}
}
</script>

We will define a function that will send a request to our back-end service to create any new music that has been added to
the list. Also. we need to write a simple validation function that will check for the file type so that the users can only
upload files with an extention of .mp3 and .mp4.

It’s important to define a computed property to make sure that our input field isn’t empty. We also need to add a simple
validator that will make sure the the file we are trying to upload is actually a music file.

Let’s continue by editing the addMusic function to make a request to our back-end service. But before we do this, let’s first
install sweetalert which will provide us with a nice modal window. To do this this, open up your terminal and type in the
following:

npm i sweetalert
After installing the package, create a sweetalert.js file in the /plugins folder and add this:

import Vue from 'vue';


import swal from 'sweetalert';

Vue.prototype.$swal = swal;

Then, register the plugin in the nuxt.config.js file inside the plugin instace like this:

plugins: [
{
src: '~/plugins/sweetalert'
}
],

We have now successfully configured sweetalert in our application, so we can move on and edit the addmusic function to
this:
addNewMusic() {
let types = /(\.|\/)(mp3|mp4)$/i
if (
types.test(this.musicDetails.music.type) ||
types.test(this.musicDetails.music.name)
) {
let formData = new FormData()
formData.append('title', this.musicDetails.title)
formData.append('artist', this.musicDetails.artist)
formData.append('music', this.musicDetails.music)
this.addLoading = true
this.$axios
.$post('/music', formData)
.then(response => {
console.log(response)
this.addLoading = false
this.musicDetails = {}
this.getAllMusics() // we will create this function later
swal('Success', 'New Music Added', 'success')
})
.catch(err => {
this.addLoading = false
swal('Error', 'Something Went wrong', 'error')
console.log(err)
})
} else {
swal('Error', 'Invalid file type', 'error')
return !this.isValid
}
},

Let’s write a simple script that will toggle the form, i.e it should only display when we want to add new music.
We can do this by editing the ‘Add Music’ button in the table that displays all of the music that can be found:

<button
class="btn btn-info m-3"
@click="initForm">
{{addState?"Cancel":"Add New Music"}}
</button>

Then, add a state that will hold the state of the form in the data property:

addState: false

After doing this, let’s define the initForm function:

initForm() {
this.addState = !this.addState
},

And then add v-if="addState" to the div that holds the form:

<div class="card" v-if="addState">

Deleting Music
To delete music, we need to call the delete endpoint and pass the music id as a param. Let’s add a click event to the
‘Delete’ button that will trigger the function to delete a function:

<button class="btn btn-info" @click="deleteMusic(music._id)">Delete</button>

The delete function will be making an HTTP request to our back-end service. After getting the music ID from the
deleteMusic function parameter, we will add the ID in the URL that we are using to send the request. This specifies the
exact piece of music that ought to be removed from the database.
deleteMusic(id) {
swal({
title: 'Are you sure?',
text: 'Once deleted, you will not be able to recover this Music!',
icon: 'warning',
buttons: true,
dangerMode: true
}).then(willDelete => {
if (willDelete) {
this.$axios
.$delete('/music/' + id)
.then(response => {
this.getAllMusics()
swal('Poof! Your Music file has been deleted!', {
icon: 'success'
})
})
.catch(err => {
swal('Error', 'Somethimg went wrong', 'error')
})
} else {
swal('Your Music file is safe!')
}
})
}

With all of this, we have just built our music manager. Now it’s time to build the music player.

Let’s start by creating a new folder in the components folder named /player . Then, create a player.vue file within this
folder and add this:
<template>
<section>
<div class="container">
<div class="row">
<div class="col-md-12">
<h3 class="text-center">Player</h3>
</div>
</div>
</div>
</section>
</template>
<script>
export default {
data() {
return {}
}
}
</script>
<style scoped>
</style>

Next, let’s import this component into the index.vue file in the /pages folder. Replace the code in index.vue file to this:
<template>
<div>
<player />
</div>
</template>
<script>
import player from '@/components/player/player'
export default {
components: {
player
}
}
</script>

Let’s configure routing in our navbar component to enable routing between our pages.

To route in a Nuxt.js application, the nuxt-link is used after which you have specified the page for that route to a
particular instance. So let’s edit the code in the partials/navbar component to this:

<template>
<header>
<nav class="navbar navbar-expand-lg navbar-light bg-info">
<div class="container">
<nuxt-link to="/" class="navbar-brand">Music App</nuxt-link>
<button
class="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarNav"
aria-controls="navbarNav"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<nuxt-link to="/" class="nav-link">Player</nuxt-link>
</li>
<li class="nav-item">
<nuxt-link to="/manager" class="nav-link">Manager</nuxt-link>
</li>
</ul>
</div>
</div>
</nav>
</header>
</template>
<style scoped>
.nav-link,
.navbar-brand {
color: #ffff !important;
}
</style>

With this, we can navigate through our pages by using the navbar.

Building The Player


Before we begin, we need to extend Webpack to load audio files. Audio files should be processed by file-loader . This
loader is already included in the default Webpack configuration, but it is not set up to handle audio files.

To do this, go to the nuxt.config.js file and modify the build object to this:

build: {
extend(config, ctx) {
config.module.rules.push({
test: /\.(ogg|mp3|mp4|wav|mpe?g)$/i,
loader: 'file-loader',
options: {
name: '\[path\][name].[ext]'
}
})
}
}

Next, let’s write a function that will get all songs and then use the Audio constructor to play the first song in the allMusic
array.

For starters, let’s modify our player.vue file to this:

<template>
<section v-if="allMusic">
<div class="container">
<div class="row">
<div class="col-md-12">
<h3 class="text-center">Player</h3>
</div>
</div>
<div class="row">
<div class= row >
<div class="col-md-6">
<span>{{this.current.title}} - {{this.current.artist}}</span>
</div>
</div>
</div>
</section>
</template>
<script>
export default {
data() {
return {
current: {
title: '',
artist: ''
},
song: true,
isplaying: false,
allMusic: null,
index: 0,
player: ''
}
},
methods: {
async initPlayer() {
if (this.allMusic !== []) {
this.current = await this.allMusic[this.index]
this.player.src = `http://localhost:4000/${this.current.music.path}`
} else {
this.song = true
}
},
async getAllSongs() {
try {
let response = await this.$axios.$get('/music')
console.log(response)
if (response === []) {
this.song = true
this.current = null
} else {
this.song = false
this.allMusic = response
}
await this.initPlayer()
} catch (err) {
this.current = null
console.log(err)
}
}
},
created() {
if (process.client) {
this.player = new Audio()
}
this.getAllSongs()
}
}
</script>
<style scoped>
</style>

Once the file is served, the music will play in the background and then you should be able to see this in your browser:
Music player UI (Large preview)

To stop the music, all you need to do is comment out the await player.play() in the initPlayer function.

Creating The Player UI


Let’s now define our music player UI by replacing the template in our player.vue file with the following:

<template>
<section v-if="allMusic">
<div class="container">
<div class="row mb-5">
<div class="col-md-12">
<h3 class="text-center">Player</h3>
</div>
</div>
<div class="row mt-5">
<div class="col-md-6">
<img
src="https://images.pexels.com/photos/3624281/pexels-photo-3624281.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"
class="image"
/>
<div class="card player_card">
<div class="card-body">
<h6 class="card-title">
<b>{{this.current.title}} - {{this.current.artist}}</b>
</h6>
<div>
<i class="fas fa-backward control mr-4"></i>
<i class="fas fa-play play"></i>
<i class="fas fa-pause play"></i>
<i class="fas fa-forward control ml-4"></i>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card shadow">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Title</th>
<th scope="col">Artist</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>
<button class="btn btn-primary">Play</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
</template>
</te p ate>

Then, add the following style into the style section:

<style scoped>
.image {
border-radius: 5px !important;
position: relative;
height: 300px;
width: 100%;
}
.player_card {
text-align: center;
bottom: 20px;
margin: 0px 40px;
}
.text-muted {
font-size: 15px;
}
.play {
font-size: 40px;
}
.control {
font-size: 25px;
}
</style>

After modifying this, the player should look like this:


Final UI of music player (Large preview)

Adding The Play Function


We’ll continue by displaying the music description on the table. In order to do this, replace the table with the code below:
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Title</th>
<th scope="col">Artist</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr v-for="(music,index) in allMusic" :key="index">
<th scope="row">{{index+1}}</th>
<td>{{music.title}}</td>
<td>{{music.artist}}</td>
<td>
<button class="btn btn-primary">Play</button>
</td>
</tr>
</tbody>
</table>

We don’t want to display the ‘Play’ and ‘Pause’ icons at the same time. Instead, we want a situation that when the song
is playing, the ‘Pause’ icon is displayed. Also, when the song is paused, the play icon should be displayed.

To achieve this, we need to set a isPlaying state to the false instance and then use this instance to toggle the icons.
After that, we will add a function to our ‘Play’ icon.

isplaying:false
After doing this, modify your ‘Play’ and ‘Pause’ icon to this:

<i class="fas fa-play play" v-if="!isplaying" @click="play"></i>


<i class="fas fa-pause play" v-else></i>

With all this let’s define the play method:

play(song) {
console.log(song)
if (song) {
this.current = song
this.player.src = `http://localhost:4000/${this.current.music.path}`
}
this.player.play()
this.isplaying = true
},

We, first of all, get the current song and pass it into the function parameter. We then define the JavaScript Audio()
instance. Next, we check if the song is null: If it isn’t, we set this.current to the song we passed in the parameter, and
then we call the Audio player instance. (Also, don’t forget that we have to set the isPlaying state to true when the
music is playing.)

Adding The Pause Function


To pause a song, we will use the Audio pause method. We need to add a click event to the pause icon:

<i class="fas fa-pause play" @click="pause" v-else></i>


And then define the function in the methods instance:

pause() {
this.player.pause()
this.isplaying = false
},

Playing A Song From The Music List


This is quite simple to implement. All we have to do is add a click event that will change the song parameter in the play
method to the song we just created.

Simply modify the play button on the music list table to this:

<button class="btn btn-primary" @click="play(music)">Play</button>

And there you have it!

Adding The Next Function


To add the next function, we need to increment the index by one. To do this, add a click event to the next icon:

@click="next"
And then define the prev function in the methods instance:

next() {
this.index++
if (this.index > this.allMusic.length - 1) {
this.index = 0
}
this.current = this.allMusic[this.index]
this.play(this.current)
},

This conditional is responsible for replaying all of the songs whenever the last song in the list has been played.

Adding The previous Function


This is actually the opposite of the next function, so let’s add a click event to the previous function:

@click="prev"

Next, we define the previous function:


Nuxt.js over Vue.js: when
should you use it and why
Author Category Date
Domagoj Svjetličić Development Oct 18, 2019 7 min read

Nuxt.js is a frontend framework built upon Vue.js that offers great development
features such as server side rendering, automatically generated routes, improved
meta tags managing and SEO improvement.
Our Front-end team didn’t really consider using Nuxt.js as a main technology on the client side until we recently received a request for
a unique project with a number of very specific features. As this was also the first time a couple of members in our team used Nuxt.js,
I decided to write this blog to explain how it worked for us.

Why would you use Nuxt.js over Vue?


Nuxt.js offers many benefits to front-end developers, but there was one key feature that made our decision to use this framework final
– SEO improvement. Our application needs this feature because it is not a typical internal SPA (single-page application). It’s a public
web application that includes social sharing features and management.

Speaking of social sharing, Nuxt.js has great meta tags managing, so we could easily make specific and customisable social share
windows depending on the data received from back-end. Here’s one of the examples.

So, how does SEO improvement work?

To improve SEO, Nuxt.js uses SSR (Server Side Rendering). SSR is fetching AJAX data and rendering Vue.js components into HTML
strings on the server (Node.js). It sends them directly to the browser when all asynchronous logic is done, and then finally serves the
static markup into a fully interactive app on the client. This feature allows for great parsing through DOM elements with the Google
SEO parser. SEO parser is parsing through DOM elements with enormous speed immediately when the website DOM is loaded.

On the other hand, typical SPA applications built with frameworks like Vue.js, React, Angular and similar are fetching data from
backend with AJAX after DOM is loaded, and therefore SEO parser is not able to parse all of the DOM elements, because there are not
yet rendered. AJAX fetching is asynchronous, while SEO parsing is not.
Image: Nuxt.js SEO audit grade

Image: Vue.js SEO audit grade

Nuxt.js needs a different mindset that Vue


Nuxt.js and Vue.js handle logic very differently. The main difference is that Vue is always running on the client side, while Nuxt is not,
and that can cause major problems in some cases. For example – if you want to select a DOM element right after the application is
loaded, there is a possibility that the app is running on the Node.js side, and of course, there are no DOM elements in Node.js.
The same would happen when accessing a browser’s local storage. That is the main reason why Nuxt is using cookies over local
storage – because they are always accessible.

With Vue, we don’t have those kinds of problems because it is always running on the client, and therefore we do not have to bother
with those kind of potential problems.

Let’s see how to handle this types of potential problems in Vue and how to do it in Nuxt – with actual
code examples.

Image: Nuxt.js server/client handling

The most important thing in this picture is the early return in the “created” method. Nuxt has a globally accessible object “process”
that shows us are we currently running on the server side or the client side. The logic behind the code we see is focused on managing
socket connection, and obviously we do not want to update the DOM on receiving socket events if we are running on server, because
there is no DOM on the server side. If this was a Vue.js application, the code would be identical, except for the early return part –
because the process would always be running on client and there would never be a need to check that particular statement.
Image: Nuxt.js generated router based on folder
structure

Nuxt.js generates its own router based on the folder structure, while with Vue.js, it must be done manually – but keep in mind that
there are pros and cons to both principles. Automatically generated router’s pros are that it is easier and faster to create one. You just
create the directory and files, and Nuxt does all of the work. But the cons are that it is less controllable and manageable than a
manually written one.

Image: Vue.js manual router


With Vue.js you can easily add your own logic to the router, import services and have more control managing routes than with a
manually generated router. This principle is more time consuming and more complex, but that doesn’t always mean it is worse because
of it.

Is Nuxt ready for enterprise-scale applications?


There used to be two main factors that made Nuxt.js unready for enterprise-scale applications:

Poor typescript support


Bad server-side error handling

While we were in the research phase of our project (some 6 months ago), there were no reliable Typescript start-kits or configurations
whose usage was worth the risk. There were plenty of linting errors and missing types, so we decided to go with vanilla JS (ES6+). In
the meantime, Typescript support for Nuxt.js has drastically improved and now there are new start-kits and configurations ready to be
used without worrying about Typescript-related issues.

Bad server-side error handling was the biggest and the most demanding issue we had to deal with while developing a Nuxt.js
application. While code was executing on the Nuxt.js server (Node.js) side, the application was throwing very unrelated error
messages, and it was really hard and complex to debug and fix those same errors. It was necessary to handle errors on the Node.js side
in a specific way in order to make debugging simpler.

Now, with better Typescript support and a deeper understanding of SSR, I can reliably say that Nuxt.js is ready for mid-scale and
enterprise-scale applications, but there is still room for improvement – like better error handling and AJAX managing on the Node.js
side of Nuxt.

Nuxt application structure


Nuxt.js has a very similar architecture to Vue.js. There are only two major differences:

Router
Main App.vue component

Nuxt generates router logic and its routes based on the directory and file structure for pages. For example, if we create a directory and
file “about/index.vue”, Nuxt.js automatically creates the route “/about” for that page. There is no need to define or configure
routes anywhere else in application.

For nested routes, creating a directory inside the parent directory is all that is necessary – “about/me/index.vue” will generate
the “about/me” route. And for creating dynamic nested routes or nested route parameters, all that is required is to name the
subdirectory with the lodash prefix – “user/_id/index.vue” will create a dynamic nested route for users based on their id.
Image: Nuxt.js pages directory structure

Nuxt.js has one more structure-related feature that is very interesting – layouts. Vue.js applications have the main App.vue file, which
is the main root component wrapper for all application components. Nuxt.js uses layouts, where every layout serves as an individual
wrapper for application components. For example, if we want some specific pages to use different UI libraries, global CSS styles, font
families, design systems, meta tags or other elements, we can define what layout to use as its parent root component. By default, all
Nuxt.js pages are using the default.vue layout.

Vuex in Nuxt.js is structured almost identically to the usual Vue.js environment – with store modules. This type of structuring is
optional, but highly recommended for better structure and code maintenance. Every store should be structured and modularized based
on the application logic and data flow. For instance, if the application contains authorization logic, we must create the authorization
store module for managing all authorization data and logic, such as log in, log out, cookies, tokens, user data, etc.
Image: Nuxt.js store modules structure

Image: Nuxt.js root application structure

Conclusion
Developing your first Nuxt.js project will surely be confusing and complex at first, especially if you have Vue.js background without
SSR knowledge. But just like any other technology, it takes time, mistakes and a lot of lines of code to truly understand the power and
the benefits of the Nuxt.js framework. As for me, I’m eagerly awaiting my next Nuxt.js project where I’ll get to use my acquired
knowledge (and hopefully Typescript) without encountering any obstacles from the previous Nuxt.js + Typescript project I worked on.

If you’re interested in learning more about Nuxt.js, I highly recommend you check out these sources:

Udemy course: Nuxt.js – Vue.js on Steroids


freeCodeCamp article: Client-side vs. server-side rendering

Nuxt.js is a very powerful framework with many useful features that make developing front-end applications easier and more
entertaining. But keep in mind that it is not the best choice for all types of client-side applications and websites.

So, to answer the main question – Nuxt.js or Vue.js? The answer is that you have to know the
strengths and weaknesses of each, and you also need to know when to use one over the other based on
the project type, goals and requirements.

Nuxt offers better SEO improvement with its server-side rendering feature, faster development with auto-generic router, public share
features and management with great configuration options and meta tags methods, automatic code splitting with pre-rendered pages –
all of this is impossible or extremely complex to achieve with Vue.js. If these features are required for your next project, I assure you
that Nuxt.js will be an excellent choice.

On the other hand, if your goals are internal product, expanded code managing and coverage, typical client-side SPA, no need for SEO
rate and performance, and manual code logic over generic solutions, then the obvious choice is Vue.js, as it’s far superior to Nuxt.js
when it comes to handling all that.

__________
We’re available for partnerships and open for new projects. If you have an idea you’d like to discuss, share it with our team!
Running crawls with Postman

For this guide, we're going to assume you're interested in scraping keywords from a specific list of websites you're interested in.

1. Download your Postman collection


You can download a Postman collection directly from our web portal. Login at https://portal.80legs.com/login and then go to your profile
page. Click on the "Get Postman Collection" to download your collection.

The collection will be pre-populated with several API calls that use your API token.

Import this collection into Postman. You can do this by opening Postman and clicking on "Import" at the top-left of your screen.

2. Upload your URL list


Before we can create our web crawl, we need to create a URL list. A URL list is one or more URLs from which your crawl will start. Without the
URL list, a crawl won't know where to start.

With Postman open, click on the 80legs API collection. Then navigate to Secured Endpoints > Upload a URL List. Click on "Body" in the main
screen.

First, give your URL list a name by replacing 

:name
 in the API call with a unique name, like  urlList1 .

Then, enter the following in the text area:

JSON

[
"https://www.80legs.com",
"https://www.datafiniti.co"
]

In this example we're creating a URL list with just


In this example, we re creating a URL list with just 
https://www.80legs.com
 and  https://www.datafiniti.co . Any crawl using this URL list will start crawling from these two URLs.

Click the blue "Send" button. You should get this response:

JSON

{
"created": "urlList1"
}

3. Upload your 80app


The next thing we'll need to do is upload an 80app. An 80app is a small piece of code that runs every time your crawler requests a URL and
does the work of generating links to crawl and scraping data from the web page.

You can read more about 80apps here. You can also view sample 80app code here. For now, we'll just use the code from the KeywordCollector
80app, since we're interested in scraping keywords for this example.

In Postman, navigate to Secured Endpoints > Apps > Upload an 80app. Click on "Body" in the main screen.

First, give your 80app list a name by replacing 

:name
 in the API call with a unique name, like  keywordCollector.js .

Then, copy the code from KeywordCollector and paste it into the request body field, like so:

Click the blue "Send" button. You should get this response:

JSON
{
"created": "keywordCollector.js"
}

4. Configure and run your crawl


Now that we've created a URL list and an 80app, we're ready to run our web crawl!

In Postman navigate to Secured Endpoints > Crawls > Start a Crawl Click on "Body" in the main screen
In Postman, navigate to Secured Endpoints > Crawls > Start a Crawl. Click on Body in the main screen.

First, give your crawl a name by replacing 

:name
 with something unique, like 'testCrawl1`.

Next, configure your request body so that the crawl will use the URL list and 80app you just created. You can also change the 

max_depth
 and  max_urls  field if you like. Read more about what these fields mean here. Your request body should look something like this:

JSON

{
"app": "keywordCollector.js",
"urllist": "urlList1",
"max_depth": 10,
"max_urls": 1000
}

Once you've configured the crawl using the request body, click the blue "Send" button. You should get a response like this:

JSON
{
"id": 123456,
"name": "testCrawl1",
"user": "abcdefghijklmnopqrstuvwxyz012345",
"app": "keywordCollector",
"urllist": "urlList1",
"max_depth": 10,
"max_urls": 1000,
"status": "STARTED",
"depth": 0,
"urls_crawled": 0,
"date_created": "2018-7-25 19:0:54",
"date_completed": "",
"date_started": "2018-7-25 19:0:54"
}

Let's break down each of the parameters we sent in our request:

Request Body Parameter Description


Request Body Parameter Description
Request Body Parameter Description

app The name of the 80app we're going to use.

urllist The name of the URL list we're going to use.

max_depth The maximum depth level for this crawl. Learn more about crawl depth here.

max_urls The maximum number of URLs this crawl will request.

Now let's dive through the response the API returned:

Response Field Description

id The ID of the crawl. This is a globally unique identifier.

name The name you gave the crawl.

user Your API token.

app The name of the 80app this crawl is using.

urllist The URL list this crawl is using.

max_depth The maximum depth level for this crawl.

max_urls The maximum number of URLs this crawl will request.

status The current status of the crawl. Check the possible values here.

depth The current depth level of the crawl.

urls_crawled The number of URLs crawled so far.

date_created The date you created this crawl.

date_completed The date the crawl completed. This will be empty until the crawl completes or is canceled.

The date the crawl started running. This can be different than  date_created  when the crawl starts off
date_started
as queued.
5. Check on crawl status
As mentioned, there is a 

status
 field in the response body above. This field shows us the crawl has started, which means it's running. Web crawls typically do not complete
instantaneously, since they need to spend requesting URLs and crawling links. In order to tell if the crawl has finished, we can check on its
status on a periodic basis.

To do this in Postman, navigate to Secured Endpoints > Crawls > Get a Crawl. Replace 

:name
 with the name of your crawl. In this example, the name would be  testCrawl1 . Click on the blue "Send" button. You'll get another crawl object
as your response like this:

JSON

{
"id": 123456,
"name": "testCrawl1",
"user": "abcdefghijklmnopqrstuvwxyz012345",
"app": "keywordCollector",
"urllist": "urlList1",
"max_depth": 10,
"max_urls": 1000,
"status": "STARTED",
"depth": 1,
"urls_crawled": 198,
"date_created": "2018-7-25 19:0:54",
"date_completed": "",
"date_started": "2018-7-25 19:0:54"
}

If you keep sending this request, you should notice 

depth
 and  urls_crawled  gradually increasing. At some point,  status  will change to  COMPLETED . That's how you know the crawl has finished
running.

6. Download results
After the crawl finishes, you'll want to download the result files. Result files are logs of all the data scraped during the crawl.
In Postman, navigate to Secured Endpoints > Results > Get Results from a Crawl. Replace 

:name
 with your crawl's name. E.g.,  testCrawl . Click the blue "Send" button. You'll get a response similar to:

JSON

[
"http://datafiniti-voltron-results.s3.amazonaws.com/abcdefghijklmnopqrstuvwxyz012345/123456_1.txt?AWSAccessKeyId=AKIAIELL2XADVPVJZ4
]

Depending on how many URLs you crawl, and how much data you scrape from each URL, you'll see one or more links to result files in your
results response. 80legs will create a results file for every 100 MB of data you scrape, which means result files can post while your crawl is
running.

For very large crawls that take more than 7 days to run, we recommend checking your available results on a weekly basis. Result files will expire
7 days after they are created.

7. Process the results


After you've download the result files, you'll want to process them so you can make use of the data. A result file will have a structure similar to
this:

JSON
[
{
"url": "https://www.80legs.com",
"result": "...."
},
{
"url": "https://www.datafiniti.co",
"result": "...."
},
...
]

Note that the file is a large JSON object. Specifically, it's an array of objects, where each object consists of a 

url
 field and a  result  field. The  result  field will contain a string related to the data you've scraped, which, if you remember, is determined by
your 80app.

In order to process these results files, we recommend using a programming language. We have examples for how to do this in our other
guides.

You might also like