Skip to content

Nuxt 3 Demo App with Prerender and SSR

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.

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.

<script setup>
import { ref } from 'vue'

const data = ref(null)

async function fetchData() {
  const response = await fetch('https://api.example.com/data')
  const jsonData = await response.json()
  data.value = jsonData
}

fetchData()
</script>

<template>
  <div>
    <h1>Data fetched from the server</h1>
    <pre>{{ data }}</pre>
  </div>
</template>

In this example, the fetchData function fetches the data before rendering the page. The data then gets displayed within the <pre> tag.

Sidenote, if you wanted to disable SSR in your Nuxt application, you would do so in your nuxt.config.ts file:

export default defineNuxtConfig({
  ssr: false # this usually defaults to true
})

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:

export default defineNuxtConfig({
  nitro: {
    prerender: {
      routes: ['/route1', '/route2', '/route3']
    }
  }
})

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:

<script setup>
import { ref } from 'vue'

const users = ref([])

async function fetchUsers() {
  const response = await fetch('https://api.example.com/users')
  const userJson = await response.json()
  users.value = userJson
}

fetchUsers()
</script>

<template>
  <div>
    <h1>Users</h1>
    <ul>
      <li v-for="user in users" :key="user.id">
        {{ user.name }}
      </li>
    </ul>
  </div>
</template>

In the nuxt.config.ts, include the users' route for pre-rendering:

export default defineNuxtConfig({
  nitro: {
    prerender: {
      routes: ['/users']
    }
  }
})

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!

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

JavaScript Marathon: Exploring Nuxt 3 and Composition API cover image

JavaScript Marathon: Exploring Nuxt 3 and Composition API

Wrapping up our week of free live trainings, @temitopedavid_ walked us through setting up and using Nuxt 3 with the composition API. It's pretty in-depth and for the sake of this wrap-up, I will direct you to the repo itself so you can look through it and see how it works. The event is also available on Youtube for you to watch as well. Nuxt 3 is a very powerful hybrid Vue framework. If you'd like to learn more, check out the documentation....

How to Style Using SCSS in Nuxt cover image

How to Style Using SCSS in Nuxt

Introduction SASS makes working on large projects more organized. It allows you to use variables, nested rules, mixins, and functions. The preferred styling method in Nuxt is component file styling, and integrating SASS into your project can make your component file styling appear more understandable. How to Import SASS in Nuxt To add SASS after setting up your Nuxt application, we will first install SASS and sass-loader. Let's run either of these commands depending on our package manager. ` Component File Styling With SASS and sass-loader installed in our project, we can now write SCSS in our component file. Lets see an example: ` In the example above, all we need to specify is lang="scss" on the style tag, and we can now write scss in that component. Global File Import and Variables To import SCSS files that are global, like variables and mixins files, we need to install style-resources: ` Next, we can update our nuxt.config.js file by adding the module we just installed to the buildModules. ` Next, let's create a global variables.scss file in our assets/style folder. Add a single variable inside: ` Next, we need to import this file inside the nuxt.config file: ` Now we have the variables in our variables.scss available in all our components for use. Next, let's test it out by updating our button component. ` We have updated our button variant color to be our global SCSS variable ($primary and $white). Mixins Mixins in SASS are used to write styles that can be reused in other parts of the code. Let's create a sample mixin to center an item. ` Next, we need to import our mixin in Nuxt config: ` Now, let's update our button component with our mixin: ` Functions Functions in SASS are used to write complex operations or behaviours that can be reused in other parts of the code. Let's create a function to handle a media query for our application. ` This is a basic example of what a function can be used for. More complex cases, like calculating percentage, can also be done. Let's import our mixin in Nuxt config: ` Let's update our button component with our function: ` We have been able to add SASS to our Nuxt project, and also looked at some ways in which SASS can make our codebase look cleaner. I hope this article has been helpful to you. If you encounter any issues, you can reach out to me on Twitter or Github....

Improving the Performance of Vue 3 Applications Using v-memo and KeepAlive cover image

Improving the Performance of Vue 3 Applications Using v-memo and KeepAlive

Introduction When building a Vue application, you will encounter performance issues as your app grows, causing it to run slower than it should. Most performance problems in web apps arise from performing tasks repeatedly, even when there is no need to. For example, if you had a list of thousands of items, and had to re-render all items when a single thing changed, you'd quickly encounter performance problems. The ideal solution would be to update only what changes. For the most part, VueJS does this well, and Vue 3 came with many performance improvements out of the box. However, in more complex applications, we may need more fine-grained control over what gets re-rendered and what does not. In this article, we are going to look at how we can use v-memo, and KeepAlive as solutions to performance problems in Vue applications. Two leading solutions to performance problems in Vue JS Memoization Memoization is like a superpower that helps your app remember things without having to constantly redo the same calculations, or processes over and over again. This allows the applications to perform faster and more efficiently, which is the ultimate goal for any web developer. Think about it; when you were a kid, your teachers always taught you to memorize things to save time. The same is valid for web applications. With memoization, they can remember the results of a calculation or process, so they don't have to waste time recalculating it every time they need the same result. For example, imagine you have a website that requires users to enter their birthdates to access certain content. If a user enters their birthdate for the first time, the application will calculate their age. With memoization, the next time the user comes to the website and enters their birthdate, the application can use the previously computed result instead of recalculating it from scratch. That's the beauty of memoization! It saves time and resources, and gives the user a faster and smoother experience. Try memoization if you want your web application to perform at its best. You'll be amazed at how much of a difference it makes! To take advantage of this in Vue, we'll be using the v-memo directive. More on this shortly. Caching Caching works by storing a copy of frequently used data and resources so that the application can access them quickly without having to go through the entire process of rendering and fetching the data from scratch. Think of it like this. When you visit a website for the first time, the browser has to fetch all the resources needed to display the page. But if you see the same website again, the browser can use the cached data, resulting in a faster and smoother experience for the user. We can take advantage of caching in our Vue applications using KeepAlive. Using v-memo V-memo was added in Vue 3.2 and, as far as I am aware, will not be back-ported to Vue 2. You can use v-memo by passing the directive to the element/component whose dependencies you want to memoize. In this case, this would be an element/component that would be computationally expensive to re-render each time a dependency changed. Here's an example of how you could use the v-memo directive: ` Note that it accepts an array of dependency values. And if every value in the array is the same as the last render, updates for the entire sub-tree will be skipped. The dependency values are those that's changes you'd like to be checked and memoized anytime they change. You can learn more about how v-memo works from the official Vue JS documentation. In this case, if the value of dependencyA or dependencyB changed, we would re-render the children of the div. However, if neither dependencyA nor dependencyB changed, we would skip the re-rendering process. This means that any computationally intensive tasks that were needed to occur in the re-render would not be triggered, and as a result, our application would perform better. Using KeepAlive Another alternative solution to performance issues is caching, where the KeepAlive option comes in. KeepAlive is a built-in vue component that allows us to cache component instances when dynamically switching between multiple components conditionally. Using KeepAlive in Vue 3 is straightforward. You can wrap the components you want to cache inside a KeepAlive component. Here's a sample code: ` In this example, we use the KeepAlive component to conditionally cache the ComponentA and ComponentB instances, which are dynamically switched using the currentComponent reactive property. With the KeepAlive component, we can maintain the state of these components even when they are not active, which can lead to improved performance. Conclusion In this article, we talked about how we can improve the performance of our VueJS applications using memoization and caching. In the case of memoization, we can use the v-memo VueJS directive that was introduced in Vue 3.2. Alternatively, when we want to cache component instances, we can use the built-in Vue KeepAlive component. By utilizing both v-memo and KeepAlive, you can optimize the performance of your Vue 3 applications, resulting in faster and smoother user experiences. That being said, if you are looking to start a new Vue JS project and need help with how to structure your project, feel free to check out our Vue JS starter.dev GitHub showcases, which showcase (no kidding) a mini-GitHub clone application built using Vue in different ways (e.g., using Nuxt, Quasar], Vite, etc.). Alternatively, if you are looking to start a new project without worrying about all the config required, you can check out the [Vue JS starter kit instead. Thanks for checking this out!...

The Quirks And Gotchas of PHP cover image

The Quirks And Gotchas of PHP

The Quirks And Gotchas of PHP If you come from a JavaScript background, you'll likely be familiar with some of its famous quirks, such as 1 + "1" equaling "11". Well, PHP has its own set of quirks and gotchas, too. Some are oddly similar to JavaScript's, while others can surprise a JavaScript developer. Let's start with the more familiar ones. 1. Type Juggling and Loose Comparisons Like JavaScript, PHP has two types of comparison operators: strict and loose. The loose comparison operator in PHP uses ==, while the strict comparison operator uses ===. Here's an example of a loose vs. strict comparison in PHP: ` PHP is a loosely typed language, meaning it will automatically convert variables from one type to another when necessary, just like JavaScript. This is not only when doing comparisons but also, for example, when doing numeric operations. Such conversions can lead to some unexpected results if you're not careful: ` As you can see, the type system has gotten a bit stricter in PHP 8, so it won't let you commit some of the "atrocities" that were possible in earlier versions, throwing a TypeError instead. PHP 8 introduced many changes that aim to eliminate some of the unpredictable behavior; we will cover some of them throughout this article. 1.1. Truthiness of Strings This is such a common gotcha in PHP that it deserves its own heading. By default, PHP considers an empty string as false and a non-empty string as true: ` But wait, there's more! PHP also considers the string "0" as false: ` You might think we're done here, but no! Try comparing a string such as "php" to 0: ` Until PHP7, any non-numeric string was converted to 0 when cast to an integer to compare it to the other integer. That's why this example will be evaluated as true. This quirk has been fixed in PHP 8. For a comprehensive comparison table of PHP's truthiness, check out the PHP documentation. 1.2. Switch Statements Switch statements in PHP use loose comparisons, so don't be surprised if you see some unexpected behavior when using them: ` The New Match Expression in PHP 8 PHP 8 introduced the match expression, which is similar to switch but uses strict comparisons (i.e., === under the hood) and returns a value: ` Unlike switch, there is no "fall-through" behavior in match, and each branch must return a value, making match a great alternative when you need a more precise or concise form of branching—especially if you want to avoid the loose comparisons of a traditional switch. 1.3 String to Number Conversion In earlier versions of PHP, string-to-number conversions were often done silently, even if the string wasn’t strictly numeric (like '123abc'). In PHP 7, this would typically result in 123 plus a Notice: ` In PHP 8, you’ll still get int(123), but now with a Warning, and in other scenarios (like extremely malformed strings), you might see a TypeError. This stricter behavior can reveal hidden bugs in code that relied on implicit type juggling. Stricter Type Checks & Warnings in PHP 8 - Performing arithmetic on non-numeric strings: As noted, in older versions, something like "123abc" + 0 would silently drop the non-numeric part, often producing 123 plus a PHP Notice. In PHP 8, such operations throw a more visible Warning or TypeError, depending on the exact scenario. - Null to Non-Nullable Internal Arguments: Passing null to a function parameter that’s internally declared as non-nullable will trigger a TypeError in PHP 8. Previously, this might have been silently accepted or triggered only a warning. - Internal Function Parameter Names: PHP 8 introduced named arguments but also made internal parameter names part of the public API. If you use named arguments with built-in functions, be aware that renaming or reordering parameters in future releases might break your code. Always match official parameter names as documented in the PHP manual. Union Types & Mixed Since PHP 8.0, we can declare union types, which allows you to specify that a parameter or return value can be one of multiple types. For example: ` Specifying the union of types your function accepts can help clarify your code’s intent and reveal incompatibilities if your existing code relies on looser type checking, preventing some of the conversion quirks we’ve discussed. 2. Operator Precedence and Associativity Operator precedence can lead to confusing situations if you’re not careful with parentheses. For instance, the . operator (string concatenation similar to + in JavaScript) has left-to-right associativity, but certain logical operators have lower precedence than assignment or concatenation, leading to puzzling results in PHP 7 and earlier: ` PHP 8 has fixed this issue by making the + and - operators take a higher precedence. 3. Variable Variables and Variable Functions Now, we're getting into unfamiliar territory as JavaScript Developers. PHP allows you to define variable variables and variable functions. This can be a powerful feature, but it can also lead to some confusing code: ` In this example, the variable $varName contains the string 'hello'. By using $$varName, we're creating a new variable with the name 'hello' and assigning it the value 'world'. Similarly, you can create variable functions: ` 4. Passing Variables by Reference You can pass variables by reference using the & operator in PHP. This means that any changes made to the variable inside the function will be reflected outside the function: ` While this example is straightforward, not knowing the pass-by-reference feature can lead to some confusion, and bugs can arise when you inadvertently pass variables by reference. 5. Array Handling PHP arrays are a bit different from JavaScript arrays. They can be used as both arrays and dictionaries, and they have some quirks that can catch you off guard. For example, if you try to access an element that doesn't exist in an array, PHP will return null instead of throwing an error: ` Furthermore, PHP arrays can contain both numerical and string keys at the same time, but numeric string keys can sometimes convert to integers, depending on the context> ` In this example: - "1" (string) and 1 (integer) collide, resulting in the array effectively having only one key: 1. - true is also cast to 1 as an integer, so it overwrites the same key. And last, but not least, let's go back to the topic of passing variables by reference. You can assign an array element by reference, which can feel quite unintuitive: ` 6 Checking for Variable Truthiness (isset, empty, and nullsafe operator) In PHP, you can use the empty() function to check if a variable is empty. But what does "empty" mean in PHP? The mental model of what's considered "empty" in PHP might differ from what you're used to in JavaScript. Let's clarify this: The following values are considered empty by the empty() function: - "" (an empty string) - 0 (0 as an integer) - 0.0 (0 as a float) - "0" (0 as a string) - null - false - [] (an empty array) This means that the following values are not considered empty: - "0" (a string containing "0") - " " (a string containing a space) - 0.0 (0 as a float) - new stdClass() (an empty object) Keep this in mind when using empty() in your code, otherwise, you might end up debugging some unexpected behavior. Undefined Variables and isset() Another little gotcha is that you might expect empty() to return true for undefined variables too - they contain nothing after all, right? Unfortunately, empty() will throw a notice in such case. To account for undefined variables, you may want to use the isset() function, which checks if a variable is set and not null: ` The Nullsafe Operator If you have a chain of properties or methods that you want to access, you may tend to check each step with isset() to avoid errors: ` In fact, because isset() is a special language construct and it doesn't fully evaluate an undefined part of the chain, it can be used to evaluate the whole chain at once: ` That's much nicer! However, it could be even more elegant with the nullsafe operator (?->) introduced in PHP 8: ` If you’ve used optional chaining in JavaScript or other languages, this should look familiar. It returns null if any part of the chain is null, which is handy but can also hide potential logic mistakes — if your application logic expects objects to exist, silently returning null may lead to subtle bugs. Conclusion While PHP shares a few loose typing quirks with JavaScript, it also has its own distinctive behaviors around type juggling, operator precedence, passing by reference, and array handling. Becoming familiar with these nuances — and with the newer, more predictable features in PHP 8 — will help you avoid subtle bugs and write clearer, more robust code. PHP continues to evolve, so always consult the official documentation to stay current on best practices and language changes....

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