Fix: nuxt-client Only Supported with Experimental Config

Error message:
The `nuxt-client` attribute and client components within islands are only supported when `experimental.componentIslands.selectiveClient` is enabled.
ssr 2025-01-25

What Causes This Error?

This warning appears when you try to use the nuxt-client attribute on components within server components (islands) without enabling the required experimental feature.

The Problem

<!-- components/MyIsland.server.vue -->
<template>
  <div>
    <p>Server rendered content</p>
    <!-- ❌ This won't work without config -->
    <InteractiveButton nuxt-client />
  </div>
</template>

The Fix

Enable the experimental feature in your Nuxt config:

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

Or if you just need basic islands:

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

Understanding Component Islands

Component islands allow you to render components on the server while hydrating specific parts on the client.

Server Component (Island)

<!-- components/HeavyContent.server.vue -->
<template>
  <div>
    <h1>{{ title }}</h1>
    <p>This is rendered on the server only</p>

    <!-- This button needs client-side JS -->
    <MyButton nuxt-client @click="handleClick" />
  </div>
</template>

Usage

<!-- pages/index.vue -->
<template>
  <div>
    <HeavyContent title="Hello" />
  </div>
</template>

When to Use nuxt-client

Use nuxt-client when you need interactivity inside a server component:

<!-- components/ProductCard.server.vue -->
<template>
  <div class="product-card">
    <!-- Static content - server rendered -->
    <img :src="product.image" />
    <h3>{{ product.name }}</h3>
    <p>{{ product.description }}</p>

    <!-- Interactive - needs client JS -->
    <AddToCartButton nuxt-client :product-id="product.id" />
    <QuantitySelector nuxt-client />
  </div>
</template>

Alternative: Separate Client Components

Instead of nuxt-client, you can use .client.vue suffix:

<!-- components/AddToCart.client.vue -->
<template>
  <button @click="addToCart">Add to Cart</button>
</template>

<script setup>
const addToCart = () => {
  // Client-side logic
}
</script>

Vite Requirement

Note: This feature requires Vite as the builder:

The `nuxt-client` attribute and client components within islands
are only supported with Vite.

If you’re using Webpack, you’ll need to switch to Vite or use a different approach.

Full Configuration Example

// nuxt.config.ts
export default defineNuxtConfig({
  // Required for nuxt-client
  experimental: {
    componentIslands: {
      selectiveClient: true
    }
  },

  // Vite is the default, but ensure it's not overridden
  builder: 'vite'
})

Debugging Islands

Check if islands are working:

<script setup>
// This will only run on client if using nuxt-client
console.log('Running on:', process.server ? 'server' : 'client')
</script>

Common Patterns

Lazy Loading Interactive Parts

<!-- components/Dashboard.server.vue -->
<template>
  <div>
    <StaticStats :data="stats" />

    <!-- Only load charts on client -->
    <LazyChartComponent nuxt-client :data="chartData" />
  </div>
</template>

Form in Server Component

<!-- components/ContactSection.server.vue -->
<template>
  <section>
    <h2>Contact Us</h2>
    <p>Server-rendered description...</p>

    <!-- Form needs client interactivity -->
    <ContactForm nuxt-client />
  </section>
</template>

Quick Checklist

  • Enable experimental.componentIslands.selectiveClient
  • Using Vite as builder (not Webpack)
  • Server component has .server.vue suffix
  • Client components marked with nuxt-client attribute
  • Restart dev server after config changes