Nuxt Islands

Ever wondered about the possibility of having your component render fully on the server? No client-side JS. The <NuxtIsland> component offers this capability, allowing you to render parts of your application on the server. Learn more about it in this blog post.

Charles Allotey
Nuxt 3

Mastering Nuxt 3 course is here!

Get notified when we release new tutorials, lessons, and other expert Nuxt content.

Click here to view the Nuxt 3 course

Have you ever wondered about the possibility of having your component render fully on the server? No client-side JS😅. Well in Nuxt 3.9, we have an option for that. How’s it possible?

Let me introduce you to NuxtIslands (aka server components). It is currently experimental in Nuxt 3 but still offers a lot of awesome capabilities.

NuxtIslands or Server components are a way to render parts of your application on the server. They offer a special built-in component that allows you to render the component entirely on the server, meaning no client-side JavaScript is served to the browser. This can improve the performance of your app by reducing the amount of JavaScript that needs to be downloaded by the client.

Now the question is when and why would you want to use server components or NuxtIslands? Well, when you have components with complex logic or heavy computations that aren't essential for interactivity, server components can make a significant difference. By rendering them on the server, you eliminate unnecessary code from the client-side bundle, resulting in faster initial page loads and a smoother user experience.

Examples include:

  • Syntax highlighters
  • Markdown parsers
  • Complex data fetching and manipulation that doesn't require constant client-side updates

Nuxt Server Components are different from React Server Components. In Nuxt server components are opt-in, meaning you have to choose which components you want to render only on the server.

There are several benefits to using Nuxt server components, including a lower bundle size, improved SEO, and more secure secrets.

Now let’s look into seeing NuxtIslands in action:

Getting Started

Setting up the <NuxtIsland> component in Nuxt, you need to make sure you are using Nuxt 3.6 or higher and Node 18 or higher.

Server components are currently experimental and to use them, you need to enable the 'component islands' feature in your nuxt.config:

// nuxt.config.ts
export default defineNuxtConfig({
  experimental: {
    componentIslands: true
  }
})

Once you have enabled component Islands, you can create a server component by renaming the file to server.vue. You can then use slots to add interactivity to your server components.

Let’s explore an example using NuxtIslands in our project.

// components/hello.vue
<script setup>
import markdownit from 'markdown-it'
const md = markdownit()
const content = await md.render(`# Hello World!
how are you?`)
</script>

<template>
    <div>
        <div v-html="content"></div>
    </div>
</template>

// app.vue
<template>
  <div>
    <Hello />
  </div>
</template>

Screenshot 2024-04-22 at 6.49.50 AM.png

In our above block, we have a hello.vue component which utilizes markdown-it to convert markdown to HTML. Our hello.vue is rendered on the client side. Let’s explore our app behavior with our devtools.

Examining our network requests, we notice that the component-related client-side script is downloaded by the browser.

Screenshot 2024-04-21 at 11.57.28 PM.png

4 kBytes isn’t a big deal. But let’s remember that our example application is quite small compared to a real-world application.

Furthermore, our markdown-it library contains a substantial amount of data that also needs to be downloaded by our client.

Screenshot 2024-04-23 at 3.56.21 AM.png

Let’s now convert hello.vue to a <NuxtIsland> component and review that as well. Let’s first rename our hello.vue component to hello.server.vue.

Now let’s create our <NuxtIsland> component.

// app.vue
<template>
  <NuxtIsland name="Hello" />
</template>

The <NuxtIsland> component takes some props. name which is a required field for our component name. You can explore more on these props here.

Let’s observe our network requests again.

Screenshot 2024-04-22 at 6.36.07 AM.png

Screenshot 2024-04-23 at 4.00.02 AM.png

No hello.vue and markdown-it.js scripts downloaded by the client. Awesome. 223kB saved from your app Bundle size 🚀

Let's take it a step further. Suppose we want to add a bit of interactivity without still relying on component’s client-side JavaScript. What if we decided to change the displayed message dynamically by passing props?

Here's our updated code:

<script setup>
const message = ref(``)
</script>

<template>
    <textarea id="message" v-model="message" cols="30" rows="10"></textarea>
 <NuxtIsland name="Hello" :props="{message}"/>
</template>

We've added a textarea element to make our message dynamic. The <NuxtIsland> component provides a props prop, allowing us to attach props to our server components. We pass the message value as props to our server components.

Now, let's examine our devtools.

Screenshot 2024-04-23 at 4.49.12 AM.png

We observe that there's still no client-side JavaScript running. However, something different happens: our network tab records a fetch request with props as a JSON file. This request triggers a rerender of our client with the new data. 🤯

How it works is that Nuxt asynchronously returns to the server to retrieve the rendered HTML and then injects it into the page.

Overall, <NuxtIsland> Component is a promising new feature that can improve the performance and security of your Nuxt.js applications.

Also with the current updates to Nuxt Server components, you can now have a hydrated component nested inside a server-only component. This allows you to optimize your application's performance by loading data on the server while still taking advantage of client-side reactivity. Embrace the best of both worlds.

However, it is important to be aware that this feature is currently experimental and may not be recommended for use in your large-scale production applications right away.

You can read more about NuxtIsland and Nuxt server components here and here.

Charles Allotey
Charles is a Frontend Developer at Vueschool. Has a passion for building great experiences and products using Vue.js and Nuxt.

Follow MasteringNuxt on