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:
<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:
ssr: true,
routeRules: {
'/Faq': { prerender: true },
},
nitro: {
prerender: {
crawlLinks: true,
routes: ['/Faq'], // explicitly list pages
},
},
My FAQ page component includes the following structure:
<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?
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
- Configuration Fixes
- Component Structure Optimization
- Advanced Prerendering Techniques
- Verification and Troubleshooting
- Common Pitfalls to Avoid
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:
// 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:
// 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:
<!-- 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:
<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:
// 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:
// 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:
npx nuxi clean npx nuxt generate
2. Check Generated Files
Verify the output in .output/public:
# 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:
// 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:
- Set
target: 'static'in your configuration for proper static generation - Explicitly define routes in both
routeRulesandnitro.prerender.routes - Clean and regenerate after each configuration change
- Verify output by checking generated HTML files for actual content
- 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.