NeuroAgent

Fix Nuxt.js Prerendering: HTML Content Not Generated

Resolve Nuxt.js prerendering issues where HTML content isn't generated properly during static site generation. Learn configuration fixes and troubleshooting steps for proper SEO rendering.

Question

Nuxt.js SEO Prerendering Issue: HTML Content Not Generated Properly

I’m experiencing an issue with Nuxt.js prerendering for SEO. When I run npx nuxt generate, the generated HTML files for my index, FAQ, and Blog pages don’t contain the expected HTML content like h1 tags. Instead, I only see JavaScript links and scripts in the source code.

Here’s what I’m seeing in the generated HTML:

html
<link rel="prefetch" as="script" crossorigin href="/_nuxt/Bw2zdLH.js">
<link rel="prefetch" as="script" crossorigin href="/_nuxt/oD232mV.js">

<script type="text/javascript">
              window.dataLayer = window.dataLayer || [];
              function gtag(){dataLayer.push(arguments);}
              gtag('js', new Date());
              gtag('config', 'G-XRRWFSF76');
            </script>
<script type="module" src="/_nuxt/BKRWMQOr.js" crossorigin></script></head><body><div id="__nuxt">

I’ve added the following prerender settings to my Nuxt configuration:

javascript
ssr: true,
routeRules: {
  '/Faq': { prerender: true },
},
nitro: {
  prerender: {
    crawlLinks: true,
    routes: ['/Faq'], // explicitly list pages
  },
},

My FAQ page component includes the following structure:

html
<template> //Container component
  <div class="max-w-screen-xl mx-auto px-5">
    <slot />
  </div>
</template>

<template> //Faq page
  <LandingContainer>
    <div class="md:mt-0">
      <h2 class="text-4xl lg:text-5xl font-bold lg:tracking-tight">
        Check out our FAQ section
      </h2>
      <p class="text-lg mt-4 text-slate-600">
        Most common questions answered here.
      </p>
    </div>
    <div class="mt-8">
      <!-- More content here -->
    </div>
  </LandingContainer>
</template>

How can I properly configure Nuxt.js to prerender my pages with the actual HTML content instead of just JavaScript?

NeuroAgent

When using nuxt generate, the generated HTML files should contain the actual rendered content, not just JavaScript links. The issue you’re experiencing typically occurs due to configuration mismatches between SSR and static generation modes. Here’s how to resolve this:

Contents


Understanding the Root Cause

The HTML-only-with-JS-links issue typically stems from a render mode conflict between SSR and static generation. When you have ssr: true but run nuxt generate, Nuxt may not be properly transitioning from SSR to static rendering modes.

Key indicators of this problem:

  • Generated HTML contains <div id="__nuxt"> but no actual page content
  • Only JavaScript links and scripts are present in the output
  • Content appears to be client-side rendered rather than pre-rendered

Configuration Fixes

1. Update Your Nuxt Configuration

Modify your nuxt.config.ts to ensure proper static generation settings:

javascript
// nuxt.config.ts
export default defineNuxtConfig({
  // For static generation, ensure proper render mode
  nitro: {
    prerender: {
      crawlLinks: true,
      routes: ['/Faq', '/Blog', '/'],
      // Add more routes as needed
    }
  },
  
  // Use routeRules for prerendering
  routeRules: {
    '/Faq': { prerender: true },
    '/Blog': { prerender: true },
    '/': { prerender: true }
  },
  
  // Set to universal for better compatibility
  render: {
    resourceHints: false
  }
})

2. Add Target Configuration

Ensure you’re targeting the correct output:

javascript
// nuxt.config.ts
export default defineNuxtConfig({
  target: 'static', // Explicitly set for static generation
  // ... rest of your config
})

Component Structure Optimization

1. Ensure Proper SEO Components

Your FAQ page component should be optimized for static rendering:

vue
<!-- components/FAQPage.vue -->
<template>
  <div class="max-w-screen-xl mx-auto px-5">
    <div class="md:mt-0">
      <h1 class="text-4xl lg:text-5xl font-bold lg:tracking-tight">
        Check out our FAQ section
      </h1>
      <p class="text-lg mt-4 text-slate-600">
        Most common questions answered here.
      </p>
    </div>
    <div class="mt-8">
      <!-- FAQ content here -->
    </div>
  </div>
</template>

2. Use Head for SEO Content

Add proper head tags for better SEO:

vue
<script setup>
useHead({
  title: 'FAQ - Your Site Name',
  meta: [
    { name: 'description', content: 'Find answers to frequently asked questions about our services.' }
  ]
})
</script>

Advanced Prerendering Techniques

1. Manual Prerendering with Nitro

For more control, use Nitro’s prerender capabilities:

javascript
// nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    prerender: {
      crawlLinks: true,
      routes: [
        '/',
        '/Faq',
        '/Blog',
        // Add other dynamic routes if needed
      ],
      // Add custom settings
      parallel: true,
      failOnError: false
    }
  }
})

2. Dynamic Route Prerendering

If you have dynamic routes, configure them properly:

javascript
// nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    prerender: {
      routes: [
        '/',
        '/Faq',
        '/Blog',
        // Add dynamic routes with parameters
        '/blog/[slug]',
        // Or generate multiple routes programmatically
        ...Array.from({ length: 10 }, (_, i) => `/blog/post-${i}`)
      ]
    }
  }
})

Verification and Troubleshooting

1. Clean Generation Process

Always clean before regenerating:

bash
npx nuxi clean
npx nuxt generate

2. Check Generated Files

Verify the output in .output/public:

bash
# Check specific files
cat .output/public/Faq/index.html | head -20

Look for your actual HTML content in the generated files.

3. Use Prerender Verification Tools

Add debugging to verify prerendering:

javascript
// nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    prerender: {
      routes: [
        '/',
        '/Faq',
        '/Blog'
      ],
      // Add debugging
      captureTimeout: 30000,
      retry: 3
    }
  }
})

Common Pitfalls to Avoid

1. SSR vs Static Generation Conflicts

Problem: Mixing SSR settings with static generation
Solution: Use target: 'static' when generating static sites

2. Missing Route Definitions

Problem: Not explicitly defining routes for prerendering
Solution: Always include routes in both routeRules and nitro.prerender.routes

3. Client-Side Only Components

Problem: Using components that only work on the client side
Solution: Ensure all critical content is server-side rendered

4. Async Data Loading Issues

Problem: Async data not loading during prerendering
Solution: Use proper async data loading with error handling

5. JavaScript-Dependent Content

Problem: Content that requires JavaScript to render
Solution: Ensure all important content is available in initial HTML


Conclusion

The key to resolving Nuxt.js prerendering issues lies in proper configuration between SSR and static generation modes. Here are the essential steps:

  1. Set target: 'static' in your configuration for proper static generation
  2. Explicitly define routes in both routeRules and nitro.prerender.routes
  3. Clean and regenerate after each configuration change
  4. Verify output by checking generated HTML files for actual content
  5. Use proper head tags and SEO components for better search engine visibility

If you continue to experience issues, consider checking your Nuxt version compatibility and ensuring all dependencies are properly installed. Modern Nuxt versions (3.x+) have significantly improved prerendering capabilities that should resolve most of the classic SSR-to-static generation conflicts.

Sources

  1. Nuxt.js Official Documentation - Static Site Generation
  2. Nuxt.js Nitro Prerendering Guide
  3. Nuxt.js Route Rules Configuration
  4. Nuxt.js SSR vs Static Generation Best Practices