Developing Electron Apps

Misc

PreFetch Feature

The PreFetch is a feature available when using Quasar CLI that allows a way for the components picked up by Vue Router (defined in /src/router/routes.js) to:

pre-fetch data

validate the route

redirect to another route should some conditions are not met (like user should be logged in)

can help in initializing the Store state

All the above will run before the actual route component gets to be rendered.

It is designed to work with all Quasar modes (SPA, PWA, SSR, Cordova, Electron), but it is especially useful for SSR builds.

Installation

// quasar.conf.jsreturn { preFetch: true}

When you use it to pre-fetch data, you are required to use a Vuex Store, so make sure your project folder has the /src/store folder when you create your project, otherwise generate a new project and copy the store folder contents to your current project.

How It Helps SSR Mode

This feature is especially useful for the SSR mode (but not limited to it only). During SSR, we are essentially rendering a “snapshot” of our app, so if the app relies on some asynchronous data, these data need to be pre-fetched and resolved before we start the rendering process.

Another concern is that on the client, the same data 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 before rendering. The client-side store will directly pick up the server state before we mount the app.

When It Gets Activated

The preFetch hook (described in next sections) is determined by the route visited - which also determines what components are rendered. In fact, the data needed for a given route is also the data needed by the components rendered at that route. So it is natural (and also required) to place the hook logic inside route components. This includes /src/App.vue, which in this case will run only once at the app bootup.

Let’s take an example in order to understand when the hook is being called. Let’s say we have these routes and we’ve written preFetch hooks for all these components:

Now, let’s see how the hooks are called when user visits these routes in the order specified below, one after another.

Route being visited

Hooks called from

Observations

/

App.vue then LandingPage

App.vue hook is called since our app boots up.

/shop/all

ShopLayout then ShopAll

-

/shop/new

ShopNew

ShopNew is a child of ShopLayout, and ShopLayout is already rendered, so ShopLayout isn’t called again.

/shop/product/pijamas

ShopProduct

-

/shop/product/shoes

ShopProduct

Quasar notices the same component is already rendered, but the route has been updated and it has route params, so it calls the hook again.

/shop/product/shoes/overview

ShopProduct then ShopProductOverview

ShopProduct has route params so it is called even though it’s already rendered.

/

LandingPage

-

Usage

The hook is defined as a custom static function called preFetch on our route components. Note that because this function will be called before the components are instantiated, it doesn’t have access to this.

Redirecting Example

Example of redirecting the user under some circumstances, like when they try to access a page that only an authenticated user should see.

// We assume here we already wrote the authentication logic// in the Vuex Store, so take as a high-level example only.preFetch ({ store, redirect }) {if (!store.state.authenticated) {// IMPORTANT! Always use the String form of a// route if also building for SSR. The Object form// won't work on SSR builds. redirect('/login') }}

If redirect(false) is called (supported only on client-side!), it aborts the current route navigation. Note that if you use it like this in src/App.vue it will halt the app bootup, which is undesirable.

Using preFetch to Initialize the Store

The preFetch hook runs only once, when the app boots up, so you can use this opportunity to initialize the Vuex Store here.

Store Code Splitting

In a large application, your 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:

// src/store/foo.js// we've merged everything into one file here;// an initialized Quasar project splits every component of a Vuex module// into separate files, but for the sake of the example// here in the docs, we show this module as a single fileexportdefault { namespaced: true,// IMPORTANT: state must be a function so the module can be// instantiated multiple times state: () => ({ count: 0 }), actions: { inc: ({ commit }) => commit('inc') }, mutations: { inc: state => state.count++ }}

Now, we can use store.registerModule() to lazy-register this module in a route component’s preFetch() hook: