Ever wondered about the possibility of having your component render fully on the server? No client-side JS. The component offers this capability, allowing you to render parts of your application on the server. Learn more about it in this blog post.
Get notified when we release new tutorials, lessons, and other expert Nuxt content.
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:
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:
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>
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.
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.
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.
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.
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.