Back in July 2018, I listed 7 Tips for Building a Large Nuxt App. After that article, I ended up getting even more involved with the Nuxt project. A lot has evolved in Nuxt since then. With the 2.7 release just out the door, it's time to revisit the advice I've given before, point by point, to see what's still a good idea.

1. Use a custom routes index file

This remains a quick, useful hack. I say hack because I learned the proper way to do it is by using Nuxt's router module. Still, if you don't need full access to VueRouter's features, extendRoutes() gets the job done.

2. Stateful loading components

Tying Nuxt's loading component to HTTP request activity is probably not as efficient as simply disabling it on individual pages and manually controlling it with start() and finish() . The ability to set the loading property to false in order to disable it in a page came in the 2.0 release and was my very first contribution to the project:

export default { loading: false, async mounted() { await this.$http.$post('/init') this.$nuxt.$loading.finish() } }

In this example, setting loading to false would keep the Nuxt loading component active upon entering the page, giving you the chance to manually stop it. This is, of course, assuming it was already started by a previous route, automatically or manually via the start() method. That is to say, if you set loading to false on a page, you will also have to manually start() the Nuxt loading component before navigating to a different route.

Another pattern I've seen myself using frequently is updating the Vuex store with the status of the Nuxt loading component. This way I can easily use it to update specific pieces of the UI that may complement it visually.

export default { computed: { loading: { get() { return this.$store.state.loading }, set(status) { this.$store.commit('updateLoadingStatus', status) } } }, methods: { start() { if (this.loading) { return } this.loading = true }, finish() { if (!this.loading) { return } this.loading = false } } }

3. Passing data from Koa's context

I no longer recommend using Nuxt as Koa middleware. I have learned Nuxt's built-in HTTP server is more than capable for the same type of workloads you would expect Koa to handle. If you're using different processes for your backend API and Nuxt application code (recommended) and still want to use a Node-based API server, I'd look at hapi, polka or micro. We're also releasing @nuxt/metal soon, which builds on connect.

When using Nuxt server middleware, the same technique of adding things to the req or res objects that are passed to a middleware handler applies.

Are You Ready For Vue 3? Join our free four-part email course to learn the key changes in Vue 3 that you need to be aware of! My Vue experience is... Beginner Intermediate/Advanced This subscription also includes Vue.js Developers promotional emails. You can opt-out at any time. View our privacy policy .

4. Use a Vuex store factory function

I've stopped doing this altogether. Nuxt now allows you to break down Vuex store modules in separate files like state.js, actions.js, and mutations.js. It'll recognize all files that match these expected Vuex properties (including getters ) and use them to build a store module. This makes code organization a lot easier and natural.

You probably want to check out unholy though, a Nuxt module I wrote that changes Vuex's default commit() behavior to accept a single parameter: an object to be deeply merged with the root state. A source close to the Vue core team has hinted a similar feature might be added to Vuex itself.

5. Generating extra files with extend()

You're probably better off using the build.templates configuration option. They allow you to add a list of Nuxt template files (that are automatically preprocessed by lodash.template ). Instead of manually using writeFileSync() , you can just specify source, destination and an object with options (template variables), as follows:

export default { build: { templates: [{ options: { api: getAPITree() }, src: './src/api.js.template', dst: `../src/api.js` }] } }

6. Initializing global client code

I've changed the setup for this. Instead of using my old utility-based approach, I now use a client-side plugin to add an onNuxtReady handler. I usually import it from src/ready as follows:

import ready from '~/ready' window.onNuxtReady(ready)

You can have this in a file named ready.client.js and list it under the plugins configuration option. Nuxt will understand that this is a plugin to be run client-side only, sparing you from having to check for process.client every time.

7. Axios Request Interceptors

As I've covered towards the end of my article, Nuxt: The Hard Parts, there's an upcoming @nuxtjs/axios alternative: @nuxt/http (not fully stable yet, so use with caution). The API for interceptors using @nuxt/http is similar and remains a feature used in every one of my Nuxt projects.

The main difference when using @nuxt/http interceptors is that you're required to use the set(key, value) method of a preexisting config.headers object, instead of simply assigning keys to it. Here's the updated example:

export default function ({ $http }) { $http.onRequest((config) => { config.headers.set('Authorization', `Bearer ${token}`) return config }) }

⁂

In the past year, Nuxt has surpassed 20k+ GitHub stars and grown to a 9-people core team and 190 contributors, with steady patch and minor releases. With a vibrant and welcoming community, it's easily one of the safest and most productive options to build your Vue.js web applications with.