Data Fetching

Data fetching is a crucial part of any frontend application. In the blökkli starterkit we made the data fetching from Drupal as easy as possible while still providing the flexibility to fetch data from any source.

Initial Page vs per Route Data fetching

To make the frontend as fast as possible, we split the data fetching into two parts: initData and routeQuery.

InitData

The initData is usually fetched during the server-side rendering (SSR) of the initial page load and the payload is then handed over to the client. page.pngData fetched:

  • Navigation / Header / Footer
  • Translations Strings
  • Global configuration

The data is shared across all subsequent client request. To simplify the process, there is a initData()composable that can be used in any component.

Route Query

The routeQuery is called for each route and fetches the data for a specific page. The data is then passed to the components as props.

content.png

  • Page content / paragraphs
  • Translations per page
  • Alias / redirects per page

You can find more information about the routing in the dedicated section.

GraphQL fragments

To make the queries more readable and maintainable, we use fragments. Each fragment is a small part of the query that can be reused in multiple queries.

Fragments for each component are stored in its own folder. All fragments are automatically imported and registered with the help of the Nuxt GraphQL Middleware module.

Nuxt GraphQL Middleware

This module exposes GraphQL queries and mutations as fully typed API endpoints. It hides your GraphQL server from public access and prevents bundling large queries.

To make development easier, the module detects changes in GraphQL files and automatically reloads the schema.

middleware.png Learn more about the Nuxt GraphQL Middleware.

Data fetching for a specific page

To fetch data for a specific page, use the route query described in the Routing section.

The route query returns all the data for a given path in a single GraphQL query. The data is then passed to the components as props. The route query is in fact a large graph / tree of fragments.

Page

pages/[...slug
query route($path: String!) {
  ...routeQuery

  route(path: $path) {
    ... on EntityUrl {
      entity {
        ...nodePage
      }
    }
  }
}

Node Page Component

components/Node/Page/fragment.graphql
fragment nodePage on NodePage {
  uuid
  title
  lead: fieldLead
  hero: fieldHeroImage {
    ...mediaImage
  }
  canEdit: accessCheck(operation: "update")
  paragraphs: fieldParagraphs {
    ...paragraphsFieldItem
    props {
      ...paragraph
    }
  }
}

TextImage Paragraph Component

fragment paragraphTextImage on ParagraphTextImage {
  title: fieldTitle
  text: fieldText
  image: fieldImage {
    ...mediaImage
  }
}

Component Props

The component only needs the paragraphTextImage fragment to fetch the data. The other fragments are shared across all paragraphs components and not duplicated in each component. The data fetched by the route query is passed to the component as props. The components only need to define the props using typed fragment.

components/paragraphs/TextImage/index.vue

<template>
  <div>
    ...
  </div>
</template>

<script lang="ts" setup>
  import type { ParagraphTextImageFragment } from '#graphql-operations'

  defineProps<{
    title?: string
    text?: string
    image: ParagraphTextImageFragment['image']
  }>()

</script>