📗 My cheat sheet for nuxt most basic stuff
Nuxt.js is a higher-level framework that builds on top of Vue. It simplifies the development of universal or single page Vue apps. Nuxt.js is not a server side framework. It runs on the servers. It renders the first page and after the first page is renderd, the Vue.js app takes over.
- pre rendering - app is rendered or generated upfront. Pre rendering is not the same as SSR because you don't need a server because the app is rendered in static html files.
- client side rendering - javascript - side effects like blinking, load time etc.
Useful links:
- Creating a nuxt app + documentation
- Awesome nuxt
- Axios for nuxt - interceptors, headers...
- Using env variables in nuxt
+------------------+
| |
+----------+ VUE APP |
| | |
| +---------+--------+
| ^
| |
| |
v +
INDEX.HTML
+--------------+ <------------------- +--------------+
| | | |
| CLIENT | | SERVER |
| | REQ | |
+--------------+ --------------------> +--------------+
- pages - contains your Application Views and Routes. The framework reads all the .vue files inside this directory and creates the application router.
- Static routes (the name is known) will be named
index.html
in its corresponding folder (folder structure) - Dynamic routes (path is dynamic) need to have prefixes (e.g.:
_id.vue
) - Access route object via
$route
- use
nuxt-link
to navigate between pages, so an extra request to the server call won't be sent
- Static routes (the name is known) will be named
- components - reusable components. You can't use either asyncData or fetch in these components.
- layouts - includes your application layouts
There is no router.js
file. Routes are automatically generated from the files placed in the pages
directory.
- Static routes will be separated in their directories and named
index.html
. - Dynamic routes are placed in their folders and must have an underscore prefix.
- Nested routes will be named just as their parent directory (e.g.: Blog.vue). Don't forget to include inside the parent component (.vue file).
Prerendering dynamic routes - explaination cah be found here
Nuxt.js lets you define a validator method inside your dynamic route component. Nuxt.js will automatically load the 404 error page or 500 error page in case of an error. More details here
export default {
validate ({ params }) {
// Must be a number
return /^\d+$/.test(params.id)
}
}
Data will be ready before the page is served to the client. Using the asyncData object in pages:
export default {
async asyncData ({ params }) {
let { data } = await axios.get(`https://my-api/posts/${params.id}`)
return { title: data.title } // title is a variable in our component data
}
}
You do NOT have access of the component instance through this inside asyncData because it is called before initiating the component.
The fetch method is used to fill the store before rendering the page, it's like the asyncData
method except it doesn't set the component data. API calls take place on the server side.
// posts.js in the store
export const state = () => ({
all: []
})
export const actions = {
async fetchAllPosts({commit}) {
let posts = await this.$axios.$get('posts')
commit('setPosts', posts)
}
}
export const mutations = {
setPosts (state, posts) {
state.all = posts
}
}
// index.vue in the posts directory of the pages
async fetch ({store}) {
await store.dispatch('posts/fetchAllPosts')
},
computed: {
posts() {
return this.$store.state.posts.all
}
}
- Create a list of 301 redirections in a json file at project root:
// 301.json
[
{ "from": "/old", "to": "/new" },
{ "from": "/veryold.html", "to": "/verynew" },
{ "from": "/realy/too-old.html", "to": "/new" }
]
- Create a server middleware for 301 redirect
// middleware/seo.js
const redirects = require('../301.json')
module.exports = function (req, res, next) {
const redirect = redirects.find(r => r.from === req.url)
if (redirect) {
console.log(`redirect: ${redirect.from} => ${redirect.to}`)
res.writeHead(301, { Location: redirect.to })
res.end()
} else {
next()
}
}
- Add the server middleware in your config file:
// nuxt.config.js
module.exports = {
serverMiddleware: [
'~/middleware/seo.js'
],
...
}
- Create an error.vue file and place it into the layouts folder.
// layouts/error.vue
<template>
<div class="nuxt-error">
<component :is="errorPage" :error="error" />
</div>
</template>
<script>
import error404 from '~/pages/404.vue'
export default {
name: 'Error',
layout: 'default',
props: {
error: {
type: Object,
default: () => {}
}
},
computed: {
errorPage() {
if (this.error.statusCode === 404) {
return error404
}
// catch everything else
return error500
},
}
}
</script>
- Create a 404.vue file in the pages folder. Style this file as desired. Placing a 404.vue file into the pages folder will override the 404.html file generated by default, which is a blank screen with a loader.
// pages/404.vue
<template>
<div>
<h1>This page doesn’t exist</h1>
<p>The link you clicked on may be broken or no longer exist.</p>
</div>
</template>
<script>
export default {
name: 'Error404',
props: {
error: {
type: Object,
default: () => {},
},
},
};
</script>
- Make sure that nuxt generates a 404.html file instead of /404/index.html file automatically by editing your nuxt.config.js file.
// nuxt.config.js
module.exports = {
generate: {
/*routes: ['404']*/
//fallback: "404.html"
//subFolders: false,
fallback: true
},
...
}
Use process.browser
or process.server
to be sure you're on the client side.
if (process.browser) {
let current = localStorage.getItem('subheader') || 1;
localStorage.setItem('subheader', (current % 3) + 1);
this.currentSubheader = (current % 3) + 1;
}
// plugins/after-each.js:
export default async ({ app }) => {
app.router.afterEach((to, from) => {
// Do something
});
}
And then reference it in nuxt.config.js:
plugins: [ { src: '~/plugins/after-each.js', mode: 'client' } ]
If you have custom components like buttons, modals etc., you would want to register them globally to avoid importing them in every component. First of all, make a .js
file in the plugins
directory:
// globalComponentImport.js
/* eslint-disable */
import Vue from 'vue';
const requireComponent = require.context(
// The relative path of the components folder
'../components',
// Whether or not to look in subfolders
true,
// The regular expression used to match base component filenames (Ts prefix)
/Ts[a-zA-Z0-9]\w+\.(vue|js)$/
)
requireComponent.keys().forEach(function (fileName) {
// Get component config
// Look for the component options on `.default`, which will
// exist if the component was exported with `export default`,
// otherwise fall back to module's root.
let baseComponentConfig = requireComponent(fileName)
baseComponentConfig = baseComponentConfig.default || baseComponentConfig
// Get component name
const baseComponentName =
baseComponentConfig.name ||
fileName.replace(/^.+\//, '').replace(/\.\w+$/, '')
// Register component globally
Vue.component(baseComponentName, baseComponentConfig)
})
Load the plugin in the nuxt.config.js
:
plugins: [
{
src: '~/plugins/globalComponentImport.js',
ssr: true
}
]