My question is, what's the point of setting up Vuex for the server when the state will be overwritten when the client side hydration takes place?
I have some data (Helm env variables) that I want to store in the vuex store for later use.
These variables is only available to me on the server, so I started trying to add them to the store in my createApp script when running on the server.
The store state however is reset when the client side hydration kicks in, so no env variables left.
Google told me I should use like window.INITIAL_DATA to set the state again on the client:
store.replaceState(window.INITIAL_DATA)
But if have to use the window object to pass store data to the client, what's the point of using Vuex on the server at all?
Isn't it better to skip Vuex overhead on the server and just use Vuex on the client and populate it with INITIAL_DATA?
I'm probably missing something..
https://ssr.vuejs.org/guide/data.html#data-store
During SSR, we are essentially rendering a "snapshot" of our app. The asynchronous data from our components needs to be available before we mount the client side app - otherwise the client app would render using different state and the hydration would fail.
To address this, the fetched data needs to live outside the view components, in a dedicated data store, or a "state container". On the server, we can pre-fetch and fill data into the store while rendering. In addition, we will serialize and inline the state in the HTML after the app has finished rendering. The client-side store can directly pick up the inlined state before we mount the app.
Also to mention:
The data you access while SSR in any Component needs to come from somewhere if you want to share information across Components, this is what Vuex is there for.
Related
Is it necessary that the store functions will be executed only client side or is there any case where the store functions can be invoked by Nuxt server too?
Store functions can absolutely be executed server side. For example, serverInit. They can also potentially be called in lifecycle hooks that happen serverside, like created and beforeCreate.
However, it's exceedingly rare that you should be worried about this. Generally, store actions or mutations are committed once on page load, and from then on as a result of user interaction which always happens client side.
So rather than using process.server checks everywhere, simply code your data fetching in your mounted hooks.
Good afternoon.
I have an interesting problem at the moment. We have a third party server that offer translations for static html content. I need to fetch this content via Ajax and display it in my Vue components.
The current situation
These translations are fetched via a dictionary-like data structure, i.e. via a category and a key. We have incorporated a Vue plugin to load these into our components via a function t, like this:
<template>
<section>
<h1>{{ t('CommonHeaders', 'HomePage') }}</h1>
<p v-html="t('Articles', 'SiteDescription')"></p>
</section>
</template>
At the moment these translations are shipped to the browser by embedding them in the HTML, after which our client-side hydration mechanism reads them and adds them to the Vuex store. The t function then looks up the translations and displays them where needed. These translations are reactive and accept data parameters to format translations.
We use Vue SFC to render user flows in an SPA-like fashion, although the site is not yet an SPA.
The problem
In order for this to work the translations required for a page have to be listed in the back-end controller methods in a dictionary.
This has become un-maintainable and much more data is shipped to the front-end than what is necessary. Additionally, the back-end system has no definitive end-point when a page is built before being shipped to the browser that we can hook into in order to add the translations to the HTML and content often end up being duplicated.
The back-end system was built using DotNet MVC 4, so we have no SSR capabilities at this point.
The solution (hopefully)
In order to better maintain our code I would like to utilise the 't' function from the plugin to load translations via an AJAX call before the vue engine has rendered the template, i.e. via the beforeCreate or created hook. The problem is that the Vue instance will have to know about translations required in child component templates before the AJAX call can be fired, and I have no idea how to accomplish this.
On a side note, delaying rendering like this goes against all my instincts but it doesn't look like we have a choice at this point.
I am planning to cache the translations client side with a content hash in case they get updated, so the ajax calls will hopefully not be required very often, only on first load.
The site is gradually being converted into an SPA, at which point I will be able to split off the FE and utilise SSR via node. Up until that point though this is the best idea I could come up with.
Any help will be greatly appreciated.
I have been thinking about this my self as at the moment I just send an entire cached json to the client on App Init with a loading screen, is not bad at the moment since there is not a lot to translate but was considering the following approach otherwise:
Have an array in the translation vuex module store a list of keys that need to translate (array).
Have t() push the keys to translate if not already in translated store and return either empty string or a placeholder until the translation is re-actively available.
On mounted dispatch a fetch method on the store to perform the ajax call and set the translation state and clear out the translate list when complete.
Vue should by default it's behavior re-render upon the VUEX state being changed and cause t() in the template body to be recalled and return matching values on nextTick instead of placeholder value previously returned.
Just trying to get my head around Vuex / Nuxt , also quite new to nodejs.
Given that nuxt is a server side rendering app , Where does Vuex "reside" . In standard Vue , Vuex is a client side store. How does it work in Nuxt? Is it still a client side store but just rendered on the server first?
If it stays on the server , then I am just wondering how it handles per user data - or is it somehow shared. thank you.
SSR and rehydration:
Both client and server hold the state. When the client makes the first request to load the initial page the state is usually passed through the html document inside a script, something like:
<script type="text/javascript" defer>window.__NUXT__={"data":[{"name":"server"}],"error":null,"serverRendered":true}</script>
Then when the application js load it has to pickup the state, this processed is known as rehydration. From this point the client will maintain the server state in sync.
Nuxt specifics:
Interesting parts of Nuxt documentation:
https://nuxtjs.org/guide/async-data
https://nuxtjs.org/guide/vuex-store
Nuxt Vuex Demo:
https://nuxtjs.org/examples/vuex-store
Vue SSR:
In addition take a look into vue ssr documentation, it's very detailed and it does a better job explaining how everything fits in:
https://ssr.vuejs.org/en/hydration.html
https://ssr.vuejs.org/en/data.html
we will serialize and inline the state in the HTML. The client-side store can directly pick up the inlined state before we mount the app.
I currently have a Vue.js 2 SPA using Vuex for inter-component communication and Vuex-persisted state to persist my shared state.
However, I want to persist a component's local private data.
I tried the package vue-persist and it persists the component data fine, however, the variables are not namespaced and therefore shared between all component instances. I want to persist each component's data separately.
Does anyone know how I can achieve these 2 things in my Vue.js 2.x app?
1) Persistence of my local data (so it survives a browser refresh).
2) The persisted data is not shared with other components (perhaps name-spaced for each component instance?).
Thanks!
I'm not familiar with vue-persist, but it looks like you can pass a store name as the second argument to $persist. Choose a unique store name for the component instance (this will vary depending on the component).
e.g.
created() {
this.$persist(['foo'], 'my-comp:' + this.id);
}
Imagine this simple case. You have a Vue JS application in which users can create lists of tasks and sort them. These lists should be stored in a database by the server. Let's assume we have a ListComponent which does the bulk of the UX.
My question is, which pattern should I use to handle front-end and back-end data synchronisation?
A) Go through vuex: Store the active lists (those being shown, edited or created) in the vuex store. The ListComponent will change the store and then, the changes made to a list will be sent to the backend through an API.
B) Go directly to the server: Read and write directly from the ListComponent to the server every time a list is shown, edited or created.
If following A, what architecture should the store have? How and when should I kick a synchronisation? How can I keep track of what has changed and what has not?
Both can be correct depending on your use case. The application I'm currently building uses both.
When to use B: Go Directly to the server
Use B if the data is very important to save. In this case you may want to go directly to the server and serve up the response to verify it was committed to the DB. We use this process for Admin type changes. Note that you can also update Vuex after the server response and still use Vuex to serve up your data.
When to use A: Go Through Vuex
Use A if you require faster experience, since there's no waiting for the server. You must be okay with optimistically displaying changes before actually saving. The other benefit is you can sync Vuex to localStorage. We use this for user preferences that are used to customize views. Its a poor experience to slow down the page just to wait on fetching those.
How to use A: Go through Vuex
There's a couple ways to do this. Here's one pattern:
Dispatch Vuex Action 1 from component
Commit Vuex Mutation from Action that updates state - this is an optimistic update as you're assuming it'll go through
Dispatch another Vuex Action 2 from Action 1 - This assumes you'll reuse this Action in multiple Actions, otherwise it can all go in Action 1
Action 2 sends data to server
Upon promise return, Action 2 commits mutation to update Vuex state
Mutation needs to handle any discrepancies (or errors)
Count the cost of Vuex
Like your comment shows, its good to count the cost if you need to use Vuex at all because it does add a lot of overhead and complexity. The ideal is to write your components in such a way as to contain all interactions with one type of data (such as 'Lists') so you do not have to share state through Vuex.