Repository nuxt.js

Pass the component definition as second argument to `asyncData` (and `fetch`)

antoinerey
0
antoinerey
commented 10 days ago

What problem does this feature solve?

First, a bit of background.

I'm building a Nuxt application but reorganized the whole directory structure to use self contained modules. I find it easier to maintain in the long run, and modules can be reused/shared with other applications easily.

These modules may include routes, components, configurations… but also Vuex modules. And to keep the application performances as high as possible, I'm splitting those modules into different chunks.

Basically, I got :

  • A main chunk, the application core (router, store, layout…)
  • A chunk for each route (layout, components, configuration, store module…)

A basic module looks like this :

  • A routes.js file
  • A store.js file
  • A Layout.vue file
  • Pages components

At the moment, the Layout component is responsible of lazy loading the store module. That way, the Vuex store is initialized with only the required modules. I'm achieving this by doing :

// Layout.vue

import module from './store.js'

export default {
  asyncData ({ store }) {
    if (!store.state.namespace) {
      store.registerModule('namespace', module)
    }
  }
}

The second step has been to move this logic into a custom mixin (while creating a custom Vue options merge strategy) :

// mixins/index.js

export const withStore = (namespace, module) => ({
  asyncData ({ store }) {
    if (!store.state[namespace]) {
      store.registerModule(namespace, module)
    }
  }
})
// Layout.vue

import module from './store.js'
import { withStore } from '@/mixins'

export default {
  mixins: [
    withStore('namespace', module)
  ]
}

This is better, but I'd like to go even further by adding a custom component options, and applying the mixin globally :

// mixins/index.js

export const withStore = {
  asyncData ({ store }) {
    const { namespace, module } = ... // <---- This is where I need more informations

    if (!store.state[namespace]) {
      store.registerModule(namespace, module)
    }
  }
}
// plugins/index.js

import Vue from 'vue'
import { withStore } from '@/mixins' 

Vue.mixin(withStore)
// Layout.vue

import module from './store.js'

export default {
  store: {
    namespace: 'namespace',
    module: module
  }
}

That's what causing me issues.

I'd like to access to the component options from the asyncData method.

What does the proposed changes look like?

As far as I understand, we can't access the component options from the asyncData method (Note: I'm not trying to access the component instance but the component options, which are statically defined).

My proposal is to pass the component definition as second argument to asyncData (and fetch to keep the same signature).

So, my previous mixin would be written as :

// mixins/index.js

export const withStore = {
  asyncData ({ store }, Component) {
    const { namespace, module } = Component.options.store

    if (!store.state[namespace]) {
      store.registerModule(namespace, module)
    }
  }
}

On one hand, this would solve my issue, and allow people to use component methods (this would still be undefined though). But on the other hand, this would still be undefined and most methods would crash. So, we may pass a subset of the component definition instead of passing the whole object.

What do you think about it ? Is there any other solution I didn't think of ?

I'd be happy to contribute and make a PR if this proposal is accepted. 😺

idea
0
Informations
Feature RequestOpen
#c7531 - Created 10 days ago