Nuxt.js: How to properly initialize app under SPA mode?

Created on 22 Jan 2018  路  7Comments  路  Source: nuxt/nuxt.js

Also posted there: https://github.com/nuxt/nuxt.js/issues/1768#issuecomment-358845534

I have an initialization issue using Nuxt on SPA mode.

Context

I have initialization in layout default.vue and pageindex.vue. In default.vue, I load from the server all the global information used by all pages, then each page should load its own specific information.

The thing is that index.vue page needs the data from default.vue loaded before loading itself.
On SPA mode, the ways to load I am aware of are the following:

  1. middleware (executes on each routing AND first load (SPA mode specificity))
  2. plugins (execute once before app loads)
  3. fetch (to init $store with server data, has to be on a page, called before Vue creates the component)
  4. asyncData (to init data with server data, has to be on a page, called before Vue creates the component)

That's it. Correct me if I am wrong.

Question

How do I load global app data FIRST and specific page data THEN?

Now the problem is:

  1. I don't want to load my app global information on each routing obviously, so out of my way.
  2. Yes that should work! But I feel weird loading store global information from here... Isn't it supposed to be used for external libraries? Caution: Actually doesn't work, plugins are called before middlewares. I have an auth middleware, so no server call goes through in my plugins.
  3. Yes, but no. It would work if I could fetch on default.vue(layout) and use beforeCreate on pages, but it's exactly the opposite of what is available. I can only call fetch on a page, not on a layout. And I need a global load for each page, whatever which page is requested first by the user (F5 use case). So I need something above the page load, to get application state and page state.
  4. Nop, I want to load the store initial states.

More (After some trials and thoughts)

I first thought that under universal mode (instead of SPA), you'd use a middleware to load your data on the server side. And it seems like under spa mode, plugins comes first to mind...

The problem with this idea: I want to load once and for all. A middleware is going to be executed on each routing, for SPA or universal mode. How am I supposed to load only once my store initial state? Specify the middleware on a page? Yes, but that doesn't work! I need something before any page loads and for any first load, whichever the page requested.

Maybe I am doing too many things in my layout and I should load everything outside of it. I don't really use layouts. I only have the two default ones: default.vue and error.vue. I'm not a fan of it, I feel it is an unnecessary layer that is only useful to avoid repeating the Navbar component on every page.

I am thinking of storing any store action promises in the store so that I can do something like: this.$store.state.auth.onLoad.then(), so I can wait for a Vuex module to be loaded before loading more. Or init the app on a global middleware and each store module should have a boolean alreadyLoaded...
But I am thinking Nuxt should have a solution to this.

Maybe I am misunderstanding something.
Any help/thoughts is appreciated ! :wink:

This question is available on Nuxt.js community (#c2316)

All 7 comments

Hi @Elfayer, do you use middleware and plugin in functional way ?

Actually, middleware is imported before plugin, but executed after plugin, so if you use them like:

// middleware
console.log('middleware')

// plugin
console.log('plugin')

plugin is printed after middleware, but if like:

// middleware
export default ({ app, store }) => {
  console.log('middleware')
}

// plugin
export default ({ app, store }) => {
  console.log('plugin')
}

plugin will be showed before middleware

@clarkdo My bad it's a typo (fixed), I wrote:

Caution: Actually doesn't work, plugins are called after middlewares.

You're right, Plugins are executed before Middlewares. Which is what I meant. Then any call inside plugins to the server requiring authentication will not work since my authentication middleware wasn't called.

Since I can't wait for an answer here, I went with a middleware that should be executed after the auth middleware (nuxt.config.js):

router: {
  middleware: ['auth', 'init-store'],
},

I use a boolean in my middleware/init-store.js to ensure it is only called once for all routings:

import axios from 'axios';

let alreadyDone = false;

export default function (context) {
  if (alreadyDone) {
    return null;
  }
  alreadyDone = true;
  /* ... */
  return axios.all(/* ... */);
}

That's the solution I went for.
I am still thinking there is a design issue here or I misunderstand how to use Nuxt.

You can take a look at https://github.com/nuxt-community/auth-module, it combined plugin and middleware.

@Elfayer I'm struggle with simmiliar problem. Your solution last wrote is enough for me right now(Thank you), but may be did you found better solution...?

@coding8282 I don't. And I have another issue with it, without doing anything, my middleware is called every few minutes, reinitialized because the alreadyDone is reset to false.

My better solution: to not use nuxt. That's the first and the last project I do using nuxt, I'll go for vue-cli which v3 looks awesome. I think the number of issues to this repo tells a lot about the project's state.

Edit: You make me realize how bothersome it is to use actually I'll probably migrate to vue-cli from my current project too.

Hi @Elfayer

Actually when I want to do this I use nuxtServerInit action, but because you are in SPA mode, you need to have a plugin that will call an action (you can call it nuxtClientInit) so it could load all the data you need.

The layouts may disappear in a future version of Nuxt as we found not as useful as planned as well.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

danieloprado picture danieloprado  路  3Comments

o-alexandrov picture o-alexandrov  路  3Comments

pehbehbeh picture pehbehbeh  路  3Comments

gary149 picture gary149  路  3Comments

VincentLoy picture VincentLoy  路  3Comments