How to access vuex, vue-router, pinia etc. outside of Vue components in SSR-friendly manner? - vue.js

I'm trying to write SSR-friendly code, keeping in mind a potential migration of my app from SPA to SSR. One of the principles of such code is to avoid statefull singletons which can cause cross request state pollution
The problem comes when I need to use an instance of Vuex, Vue-router, Vue-i18n etc. outside of Vue component. Because the solution in all the respective SO answers is... You guessed it. To create and export a statefull singleton in a separate js file and then import it all over the app:
Vue-router: https://stackoverflow.com/a/43562210/11208064
Vuex: https://stackoverflow.com/a/47575742/11208064
Vue-i18n: https://stackoverflow.com/a/66695008/11208064
A simple example
// store.js
export default new Vuex.Store() {} // this is a singleton
// someOtherModule.js
import { store } from './store.js'
Pinia has covered the issue in the docs. They recommend to access the pinia instance via app.$pinia. However they don't specify how do I access the app instance itself.
Also the problem is not limited to these libraries. We write our own modules which work in a similar manner.
Researching the issue I came across this article. It suggests to wipe module cache, so each time you require it all the code is executed again, making it fresh and stateless. Sounds pretty sophisticated, but maybe this is the way? And if not, what is the recommended solution?

Related

Ignite React Native Boilerplate Mobx State Tree initialize state

I am coming from redux and would like to change to the ignite boilerplate.
I have a boilerplate specific question: How do I initiliaze a store with an initialstate in Mobx?
I know how it conceptually works with creating an instance, but can't see a way to integrate it into the boilerplate. All I can see is the 'rehydration' from a saved state
Thanks a lot for your help!
https://github.com/infinitered/ignite/tree/master/boilerplate/app/models
#Tholle did a good job of answering this. If I could turn his comment into an answer, I would.
Ignite will initialize the rootStore instance with what is stored in AsyncStorage. You could e.g. modify the setupRootStore function to take in an optional initial state.
https://github.com/infinitered/ignite/blob/8b6ae0bc096d2d6d5d19e3151ada66455915b104/boilerplate/app/models/root-store/setup-root-store.ts#L27-L55

Should we convert mixins to the class-based component definition syntax in Vue 3?

After reading the plan for Vue 3, I noticed that the statement mixins will still be supported. However, Should I convert all of mixins components to class-based-components in case that Vue stops supporting mixins in the future?
mixins:
export default class MyComponent extends mixins(A, B, C) {
}
The class API that was originally planned for Vue 3 has been dropped and replaced with the composition API. While mixins will still be supported, composition functions have a number of advantages, such as avoiding namespace clashing, making it clearer where properties come from, and playing friendlier with Typescript.
Once Vue 3 is released I would recommend not writing more mixins but using Composition Functions. It'll be up to you to consider whether you rewrite old mixins - it will depend on whether you think the benefits of composition functions outweigh the initial cost of rewriting old mixins.

Vue. Global vs local distribution of reusable options

As far as i understand there are two main ways to reuse options in different components.
Global registration of plugin or mixin making the desired options to be available all over application.
Vue.use(VuePlugin)
Or register them locally in every component where needed.
var Component = Vue.extend({ mixins: [VueMixin] })
Obviously the first method makes your code cleaner and easier to maintain. But which one is more efficient in terms of bundle size and overall application efficiency?

How to make vuex modules $store references in .vue components

Summary: Can Vuex modules be made $store references in .vue components (instead of referring to the Global Store as it is now after Vue.use(Vuex)) ?
Details:
I read this: vuex modules and I get that the global store can be composed as a bunch of vuex modules.
This is great but is there also a way to make these vuex modules the $store references within vue components instead of $store pointing to the global store (as it is now ?).
This will be mighty useful (IMO) since vue components then have to only be aware of its local store's references (or their own vuex modules); and, how they compose the global store.
Please advise.

Do vuex modules still require namespacing?

I have set up a rather large Vuex project with multiple modules.
https://vuex.vuejs.org/en/modules.html
To grab the example of a getter a getter from a search module could be addressed like so:
computed: {
filters() {
return this.$store.state.search.filters;
}
}
Because I need to access the state of the module by referencing the search property in my property chain do I still need to namespace my module?
The documentation states the following:
By default, actions, mutations and getters inside modules are still
registered under the global namespace - this allows multiple modules
to react to the same mutation/action type.
https://vuex.vuejs.org/en/modules.html#namespacing
But if the module is under its own property in the store isn't the only conflict that could happen between modules themselves, which can easily be prevented by a simple naming convention of the files?
What am I missing here?
But if the module is under its own property in the store isn't the only conflict that could happen between modules themselves, which can easily be prevented by a simple naming convention of the files?
No, you misunderstand. The state itself is properly namespaced, but mutations, actions and getters are still collected on a global level so you can e.g. dispatch one Action and several actions from different modules react to it.
That's the default behavior, but the good news is, that there's an option to namespace mutations, actions and getters: "namespaced: true".
it's documented here: https://vuex.vuejs.org/en/modules.html#
Scroll down to the "Namespacing" section.