Skip to content

Leveraging the Power of GraphQL and NuxtJS

Leveraging the Power of GraphQL and NuxtJS

This article was written over 18 months ago and may contain information that is out of date. Some content may be relevant but please refer to the relevant official documentation or available resources for the latest information.

Leveraging the power of GraphQL and NuxtJS

In this post, we will be exploring some of the ways GraphQL queries can be used with NuxtJS to build performant applications for different industries.

GraphQL and NuxtJS are probably the technologies with the most buzz in the tech world today.

GraphQL

When working with REST APIs, data is taken from specific endpoints. Each endpoint has a clearly defined structure of the information that it returns. This means that the data requirements of a client is determined by the API they connect to. GraphQL APIs are game changing because they allow the client to be completely flexible in deciding the type of data they actually require and typically only expose a single endpoint.

Some core concepts in GraphQL include:

  • Queries: This is the information sent to the server that describes the information the client needs.

  • Mutations: This is just like the query but they are used to perform action that requires data changing like updating, deleting and creating.

Other concepts include subscriptions, fragments, arguments and variables.

NuxtJS

Nuxt is based on a powerful modular architecture that can be used to build applications that are optimized out of the box while providing the best developer experience (from the NuxtJS website). This main buzz about NuxtJS is that it allows you build either spa or ssr apps easily, and this is very cool.

Installation

Let's set up our NuxtJS project. Run the following in your terminal:

yarn create nuxt-app <project-name>

Then:

cd <project-name>

Now let's run:

yarn dev

We should see our app running - (default localhost:3000).

Next, let's add the apollo plugin to our application:

yarn add @nuxtjs/apollo

Letโ€™s import the @nuxtjs/apollo into our nuxt.config.js file:

  modules: [
   ["@nuxtjs/apollo"]
 ]

Adding Apollo Configuration

Next, let's set up our apollo configuration inside the nuxt.config.js file.

 apollo: {
   tokenName: "nuxt-apollo", // specify token name
   cookieAttributes: {
     expires: 7 // optional, default: 7 (days)
   },
   defaultOptions: {
     $query: {
       fetchPolicy: "network-only",
       errorPolicy: "all"
     }
   },
   watchLoading: "@/apollo/loadingHandler.js",
   errorHandler: "@/apollo/errorHandler.js",
   clientConfigs: {
     default: {
       httpEndpoint: process.env.BASE_URL
     }
   }
 },
  • tokenName: This is the cookie name if your app is browser based and you are using cookies for login and session management.

  • cookieAttributes: This holds the properties of the cookies you are saving to the users' browser. Expires: this is how long you want the cookies to be alive for.

  • defaultOptions: This holds properties you want to define globally for your apollo calls. An example is $query.

  • fetchPolicy: Depending on if you want to set up caching for your application, this can be used to specify which caching policy you want to use.

  • errorPolicy: This allows you to control how GraphQL errors from the server are sent to your UI code. By default, the error policy treats GraphQL errors as network errors and ends the request chain. errorPolicy can be set to none, ignore or all.

  • clientConfigs: It is used to configure endpoint, authentication and other parameters as well.

  • httpEndpoint: This is used to specify the GraphQL endpoint your app will use.

  • watchLoading(isLoading, countModifier) is a hook called when the loading state of the query changes. The countModifier parameter is either equal to 1 when the query is loading, or -1 when the query is no longer loading.

  • errorhandler(graphQLErrors, networkError, operation, forward) is a hook called when an error occurs.

Let's create a folder apollo then create loadingHandler.js and add it to our nuxt.config.js file:

export default (isLoading, countModifier) => {
 console.log("Global loading handler");
 console.log(isLoading, countModifier);
};

Let's create errorHandler.js. inside our apollo folder:

export default (
 { graphQLErrors, networkError, operation, forward },
 nuxtContext
) => {
 console.log("Global error handler");
 console.log(graphQLErrors, networkError, operation, forward);
 console.log(nuxtContext);
};

Making GraphQL Queries

Let's make a Query to pull users based on id.

First, create a fetchuser.gql file inside a query folder in apollo:

query user($id: ID!) {
 user(id: $id) {
   id
   firstname
   age
 }
}

Inside Index.vue file, letโ€™s import fetchuser.gql

  import usersGql from "~/apollo/queries/fetchuser.gql";

Now, let's make our first query to pull users and specify prefecth as true.

prefetch is either a boolean or a function that helps determine if the query should be prefetched (fetched before mount). Using prefetch as true is a great way to use ssr to improve SEO.

 apollo: {
   user: {
     prefetch: true,
     query: usersGql,
     variables() {
       return { id: 1 };
     },
     update(data) {
       return data.user;
     },
   },
}

We can call user inside template to see the user information.

<template>
 <div class="container">
   <div>
     <h4 class="title">{{ user }}</h4>
   </div>
 </div>
</template>

Let's set prefetch as false, then show the status of the process using โ€œ$apollo.queries.user.loadingโ€ where user is the name of the query.

<template>
 <div class="container">
   <div>
     <h4 class="title">
       <template v-if="$apollo.queries.user.loading">I am still loading</template>
       <template v-else>{{ user }}</template>
     </h4>
   </div>
 </div>

Letโ€™s try making use of nuxtServerInit to make a GraphQL query.

nuxt-lifecycle

According to the official NuxtJS Website:

If the action nuxtServerInit is defined in the store and the mode is universal, Nuxt.js will call it with the context (only from the server-side). It's useful when we have some data on the server we want to give directly to the client-side.

Letโ€™s import fetchuser.gql inside store (index.js)

import get_user_query from "~/apollo/queries/fetchusers.gql";

Then we make our query in nuxtServerInit:

export const state = () => ({
  user: {}
});

export const mutations = {
  set_user: function(state, user) {
    state.user = user;
  }
};

nuxtServerInit({ commit }, { error }) {
   const clientApollo = this.app.apolloProvider.defaultClient;
   return new Promise((resolve, reject) => {
     clientApollo
       .query({
         query: get_user_query,
         variables: {
           id: 3
         }
       })
       .then(resp => {
         commit("set_user", resp.data.user);
         resolve(resp);
       })
       .catch(err => {
         resolve(err);
       });
   });
 }

Now let's make use of the user data on our page:

import { mapState } from "vuex";

export default {
 data() {
   return {
   };
 },
 computed: {
   ...mapState({
     user: (state) => state.user
   }),
 },
}
<template>
 <div class="container">
   <div>
     <h4 class="title">{{ user }}</h4>
   </div>
 </div>
</template>

Yay! I hope you now understand how to make GraphQL queries in NuxtJS. You can explore more advanced features like saving cookies when the user logs in and using nuxtServerInit to check for a user session. If you have any questions or run into any trouble, feel free to reach out on Twitter or Github.

This Dot is a consultancy dedicated to guiding companies through their modernization and digital transformation journeys. Specializing in replatforming, modernizing, and launching new initiatives, we stand out by taking true ownership of your engineering projects.

We love helping teams with projects that have missed their deadlines or helping keep your strategic digital initiatives on course. Check out our case studies and our clients that trust us with their engineering.

You might also like

Nuxt 3 Demo App with Prerender and SSR cover image

Nuxt 3 Demo App with Prerender and SSR

Introduction The quest for an optimal web application involves numerous factors, such as performance, user experience, and search engine optimization (SEO). Nuxt 3 provides excellent features out-of-the-box that can help you tackle these aspects efficiently. This article will guide you in creating a Nuxt 3 application using Server Side Rendering (SSR) and pre-rendering capabilities. We'll craft an application that offers a seamless user experience, superior performance, and improved SEO. Server Side Rendering in Nuxt 3 Enhancing User Experience and SEO with SSR In the world of web development, Server Side Rendering (SSR) has gained significant traction. It refers to the server rendering the webpage upon each request rather than the client. With SSR, your web page arrives fully formed at the client's doorstep, reducing the time for the first painting. The advantage of SSR extends beyond just performance and user experience. It's also a darling of search engine crawlers, which find it easier to index your website with fully formed page content at the time of their crawl. In simple terms, it's like providing a tour guide to lead the search engine around your website, ensuring they get all the spots! The Power of SSR in Nuxt 3 Nuxt 3 has built-in support for SSR by default. It allows you to optimize your application by loading the data before rendering the page. To take advantage of SSR, you simply build your application as you usually would. In this case, using the fetch() method to load some. ` In this example, the fetchData function fetches the data before rendering the page. The data then gets displayed within the tag. Sidenote, if you wanted to disable SSR in your Nuxt application, you would do so in your nuxt.config.ts file: `` More details on how this works can be found in the rendering modes section in the official Nuxt 3 documentation. Pre-rendering in Nuxt 3 Amplifying Application Performance with Pre-rendering While SSR has its advantages, another superhero in our story is pre-rendering. Pre-rendering refers to the process of generating the static HTML pages of a site in advance. It's like preparing a feast before the guests arrive so you can serve them promptly. Like SSR, pre-rendering enhances SEO, as search engines can index fully rendered pages. Especially for content-heavy applications, pre-rendering can give a turbo boost to performance, leading to better user engagement and retention. Leverage Pre-rendering with Nuxt 3 Nuxt 3 supports SSR and Static Site Generation (SSG), including pre-rendering. To enable prerendering, you need to export your routes in nuxt.config.ts: ` These routes will be pre-rendered during the build phase, allowing for swift navigation. Let's update our application to pre-render the users' list: ` In the nuxt.config.ts, include the users' route for pre-rendering: ` Going beyond with Nuxt 3 While SSR and pre-rendering are significant for performance and SEO, Nuxt 3 offers more advanced features like hot module replacement, Vue 3 integration, improved error handling, and more. Nuxt 3 also has different kinds of rendering modes for different applications; in our SSR case, we used the default Universal rendering mode. Leveraging these features allows you to develop robust, high-performance, and user-friendly applications. Conclusion In this article, we delved into the concepts of SSR and pre-rendering in Nuxt 3. We explored how these techniques contribute to enhancing performance, user experience, and SEO. You can create exceptional web applications by integrating Vue 3's capabilities with Nuxt 3's robust features. A well-structured, performant, and SEO-friendly application not only attract users but also retains them. Embrace the power of Nuxt 3 and Vue 3 in your development journey. Happy coding!...

Leveraging GraphQL Scalars to Enhance Your Schema cover image

Leveraging GraphQL Scalars to Enhance Your Schema

Introduction GraphQL has revolutionized the way developers approach application data and API layers, gaining well-deserved momentum in the tech world. Yet, for all its prowess, there's room for enhancement, especially when it comes to its scalar types. By default, GraphQL offers a limited set of these primitives โ€” Int, Float, String, Boolean, and ID โ€” that underpin every schema. While these types serve most use cases, there are scenarios where they fall short, leading developers to yearn for more specificity in their schemas. Enter graphql-scalars, a library designed to bridge this gap. By supplementing GraphQL with a richer set of scalar types, this tool allows for greater precision and flexibility in data representation. In this post, we'll unpack the potential of enhanced Scalars, delve into the extended capabilities provided by graphql-scalars, and demonstrate its transformative power using an existing starter project. Prepare to redefine the boundaries of what your GraphQL schema can achieve. Benefits of Using Scalars GraphQL hinges on the concept of "types." Scalars, being the foundational units of GraphQL's type system, play a pivotal role. While the default Scalars โ€” Int, Float, String, Boolean, and ID โ€” serve many use cases, there's an evident need for more specialized types in intricate web development scenarios. 1. Precision: Using default Scalars can sometimes lack specificity. Consider representing a date or time in your application with a String; this might lead to ambiguities in format interpretation and potential inconsistencies. 2. Validation: Specialized scalar types introduce inherent validation. Instead of using a String for an email or a URL, for example, distinct types ensure the data meets expected formats at the query level itself. 3. Expressiveness: Advanced Scalars provide clearer intentions. They eliminate ambiguity inherent in generic types, making the schema more transparent and self-explanatory. Acknowledging the limitations of the default Scalars, tools like graphql-scalars have emerged. By broadening the range of available data types, graphql-scalars allows developers to describe their data with greater precision and nuance. Demonstrating Scalars in Action with Our Starter Project To truly grasp the transformative power of enhanced Scalars, seeing them in action is pivotal. For this, we'll leverage a popular starter kit: the Serverless framework with Apollo and Contentful. This kit elegantly blends the efficiency of serverless functions with the power of Apollo's GraphQL and Contentful's content management capabilities. Setting Up the Starter: 1. Initialize the Project: ` 2. When prompted, name your project enhance-with-graphql-scalars. ` 3. For a detailed setup, including integrating with Contentful and deploying your serverless functions, please follow the comprehensive guide provided in the starter kit here. 4. And we add the graphql-scalars package ` Enhancing with graphql-scalars: Dive into the technology.typedefs.ts file, which is the beating heart of our GraphQL type definitions for the project. Initially, these are the definitions we encounter: ` Our enhancement strategy is straightforward: * Convert the url field from a String to the URL scalar type, bolstering field validation to adhere strictly to the URL format. Post-integration of graphql-scalars, and with our adjustments, the revised type definition emerges as: ` To cap it off, we integrate the URL type definition along with its resolvers (sourced from graphql-scalars) in the schema/index.ts file: ` This facelift doesn't just refine our GraphQL schema but infuses it with innate validation, acting as a beacon for consistent and accurate data. Testing in the GraphQL Sandbox Time to witness our changes in action within the GraphQL sandbox. Ensure your local server is humming along nicely. Kick off with verifying the list query: ` Output: ` Success! Each url in our dataset adheres to the pristine URL format. Any deviation would've slapped us with a format error. Now, let's court danger. Attempt to update the url field with a _wonky_ format: ` As anticipated, the API throws up a validation roadblock: ` For the final act, re-run the initial query to reassure ourselves that the original dataset remains untarnished. Conclusion Enhancing your GraphQL schemas with custom scalars not only amplifies the robustness of your data structures but also streamlines validation and transformation processes. By setting foundational standards at the schema level, we ensure error-free, consistent, and meaningful data exchanges right from the start. The graphql-scalars library offers an array of scalars that address common challenges developers face. Beyond the URL scalar we explored, consider diving into other commonly used scalars such as: * DateTime: Represents date and time in the ISO 8601 format. * Email: Validates strings as email addresses. * PositiveInt: Ensures integer values are positive. * NonNegativeFloat: Guarantees float values are non-negative. As a potential next step, consider crafting your own custom scalars tailored to your project's specific requirements. Building a custom scalar not only offers unparalleled flexibility but also provides deeper insights into GraphQL's inner workings and its extensibility. Remember, while GraphQL is inherently powerful, the granular enhancements like scalars truly elevate the data-fetching experience for developers and users alike. Always evaluate your project's needs and lean into enhancements that bring the most value. To richer and more intuitive GraphQL schemas!...

Testing Vue Composables with Jest cover image

Testing Vue Composables with Jest

In this post, we will take a look at how to test Vue composables with Jest. What Are Composables? When developing large scale frontend applications, we reuse logic for repetitive tasks. With composables, we are able to resuse logic in a stateful manner with the help of the composition API. Testing For this example, we create a composable to handle changes in screen size. Depending on how complex your composable is, you can simply test the reactivity directly or load it into a wrapper component, and then test the wrapper component. ` Let's write the following tests for this composable. - check currect value of screen size - check currect value of screen size after resize event is fired To test that the resize event changes the current value when fired, we need to load our composable in a component. ` From the implementation we completed above, the core logic of our breakpoint method is in an external function called "composable", and we can simply reuse it across our frontend code. Any manipulation to the state of a composable should be done directly within the composable to avoid bugs and make it easier to read. I hope this article has been helpful. If you have any questions or run into any trouble, feel free to reach out on Twitter or Github....

What does it actually look like to build software with AI today? Not in theory, but in practice. cover image

What does it actually look like to build software with AI today? Not in theory, but in practice.

What does it actually look like to build software with AI today? Not in theory, but in practice. At the Leadership Exchange, this was the question at the center of the Developer Panel, where leaders from across the industry unpacked whatโ€™s really changing inside engineering teams and what organizations need to do right now to keep up. The Developer Panel at the Leadership Exchange explored the cutting edge of AI in software engineering and examined what organizations should focus on today to prepare for the future. Moderated by Jeff Cross, Co-Founder & CEO at Nx, the panel featured Victor Savkin, Cofounder & CTO at Nx, Alex Sover, Vice President of Engineering at OpenAP, Brent Zucker, Senior Director of Engineering at Visa, and Jonathan Fontanez, AI Engineering Lead at This Dot Labs. Panelists shared insights into how AI is transforming the software development lifecycle and how teams can adopt tools effectively while preparing for organizational change. Panelists discussed emerging workflows, including CI-in-the-loop, agentic healing, and context engineering. They examined how validation, code reviews, and PRDs are evolving alongside AI capabilities and how teams are integrating external sources such as production traces to improve quality and reliability. The discussion also covered what the next generation of agentic tools might look like and how these capabilities will shape engineering practices in the near future. Adoption of AI comes with challenges. Teams often rely on plugins or extensions without foundational understanding, and individual contributors may fear displacement. Panelists emphasized that education, governance, and skill-building are essential for teams to manage AI agents effectively while maintaining quality. They also highlighted the need to standardize workflows and ensure organizational alignment to fully leverage AI capabilities. The conversation extended beyond technical challenges to organizational implications. Panelists discussed how teams can avoid issues like Conwayโ€™s Law, manage distributed teams effectively, and evolve engineering practices alongside AI adoption. Leadership and management strategies play a crucial role in ensuring that AI integration delivers meaningful outcomes while maintaining efficiency and alignment with business objectives. Key Takeaways - AI workflows require both technical and organizational preparation. - Education, governance, and skill development are essential for successful implementation. - Forward-looking teams are rethinking validation, CI pipelines, and context management to fully leverage agentic AI. The discussion highlighted that adopting AI at the cutting edge is not just about new tools - it is about rethinking processes, workflows, and organizational culture. Companies that embrace this holistic approach are most likely to succeed in leveraging AI to its full potential. Are you interested in more conversations like this? Message us for an invite to the next, or for a private discussion around these topics. Tracy can be reached at tlee@thisdot.co....

Let's innovate together!

We're ready to be your trusted technical partners in your digital innovation journey.

Whether it's modernization or custom software solutions, our team of experts can guide you through best practices and how to build scalable, performant software that lasts.

Prefer email? hi@thisdot.co