Warning Node Has Slots In Importing State

# 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.

Slots

We will be using the official state management library Vuex for this purpose. Let's create a store.js file, with some mocked logic for fetching an item based on an id:

Variant 1: Drop support for Node.js ≤ 4.4.x and 5.0.0 — 5.9.x. This is the recommended solution nowadays that would imply only minimal overhead. The Node.js 5.x release line has been unsupported since July 2016, and the Node.js 4.x release line reaches its End of Life in April 2018 (→ Schedule). I'd say you should encapsulate as much of your code as possible into functions and classes, limiting the global state when possible. This serves two purposes - the first is that it improves debugging (by limiting the odds that something unintentionally alters global state) and readability (by making it easier to understand what everything does).

WARNING

Most of the time, you should wrap state in a function, so that it will not leak into the next server-side runs.More info

And update app.js:

# Logic Collocation with Components

So, where do we place the code that dispatches the on async data during the rendering process.

TIP

You can use serverPrefetch in any component, not just the route-level components.

Here is an example Item.vue component that is rendered at the '/item/:id' route. Since the component instance is already created at this point, it has access to this:

WARNING

You should check if the component was server-side rendered in the mounted hook to avoid executing the logic twice.

TIP

You may find the same fetchItem() logic repeated multiple times (in serverPrefetch, mounted and watch callbacks) in each component - it is recommended to create your own abstraction (e.g. a mixin or a plugin) to simplify such code.

Warning Node Has Slots In Importing Staten Island

Warning node has slots in importing staten island

# Final State Injection

Now we know that the rendering process will wait for data fetching in our components, how do we know when it is 'done'? In order to do that, we need to attach a rendered callback to the render context (also new in 2.6), which the server renderer will call when the entire rendering process is finished. At this moment, the store should have been filled with the final state. We can then inject it on to the context in that callback:

When using template, context.state will automatically be embedded in the final HTML as window.__INITIAL_STATE__ state. On the client, the store should pick up the state before mounting the application:

Node

# Store Code Splitting

In a large application, our Vuex store will likely be split into multiple modules. Of course, it is also possible to code-split these modules into corresponding route component chunks. Suppose we have the following store module:

Warning Node Has Slots In Importing Statement

We can use store.registerModule to lazy-register this module in a route component's serverPrefetch hook:

Because the module is now a dependency of the route component, it will be moved into the route component's async chunk by webpack.

WARNING

Importing

Don't forget to use the preserveState: true option for registerModule so we keep the state injected by the server.