别再纠结CSR和SSR了!用Node.js + jsdom手撸一个服务端渲染的猫咪图站(附完整代码)
2026/6/1 14:38:27 网站建设 项目流程

用Node.js + jsdom打造服务端渲染的猫咪图站:从理论到实战

每次打开一个网页,你有没有想过这些图片和文字是怎么出现在你面前的?对于开发者来说,理解页面渲染的底层原理至关重要。今天,我们就来动手实现一个服务端渲染(SSR)的猫咪图片展示站,用最直观的方式理解SSR与CSR的区别。

这个项目特别适合已经掌握Node.js基础,想深入理解现代Web渲染原理的开发者。我们将使用jsdom这个神奇的库,它能在Node.js环境中模拟浏览器环境,让我们可以在服务端完成传统上只能在浏览器中进行的DOM操作。

1. 项目准备与环境搭建

在开始编码前,我们需要明确几个关键概念。服务端渲染(SSR)意味着HTML内容在服务器上就已经生成完成,客户端收到的是可以直接展示的完整页面。与之相对的客户端渲染(CSR)则是服务器只提供基本HTML框架,真正的页面内容由浏览器中的JavaScript动态生成。

首先创建项目目录并初始化:

mkdir cat-ssr-demo && cd cat-ssr-demo npm init -y npm install jsdom node-fetch

这里我们安装了两个关键依赖:

  • jsdom:模拟浏览器环境的Node.js库
  • node-fetch:Node.js版的fetch API,用于获取远程数据

创建一个基础项目结构:

/cat-ssr-demo ├── /src │ ├── server.js # 主服务文件 │ └── template.html # HTML模板 ├── /public # 生成的静态文件 └── package.json

2. 核心实现:用jsdom模拟浏览器环境

jsdom的神奇之处在于它能在Node.js环境中完整模拟浏览器环境。让我们看看如何利用它来实现SSR:

const fs = require('fs'); const { JSDOM } = require('jsdom'); const fetch = require('node-fetch'); async function generateCatPage() { // 1. 创建模拟的DOM环境 const dom = new JSDOM(`<!DOCTYPE html> <html> <head> <title>猫咪图站</title> <style> .cat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; padding: 20px; } .cat-img { width: 100%; height: 200px; object-fit: cover; border-radius: 8px; } </style> </head> <body> <h1>可爱猫咪合集</h1> <div id="app" class="cat-grid"></div> </body> </html>`); const { document } = dom.window; // 2. 获取猫咪图片数据 const response = await fetch('https://api.thecatapi.com/v1/images/search?limit=9'); const cats = await response.json(); // 3. 动态构建DOM const app = document.getElementById('app'); cats.forEach(cat => { const img = document.createElement('img'); img.src = cat.url; img.alt = '可爱猫咪'; img.className = 'cat-img'; app.appendChild(img); }); // 4. 生成静态HTML文件 fs.writeFileSync('./public/index.html', dom.serialize()); console.log('SSR页面生成完成!'); } generateCatPage();

这段代码做了几件关键事情:

  1. 创建了一个完整的HTML文档结构
  2. 从猫咪API获取了9张猫咪图片的数据
  3. 动态创建img元素并插入到DOM中
  4. 将最终生成的HTML保存为静态文件

3. SSR与CSR的深度对比

理解这两种渲染方式的区别,对选择合适的技术方案至关重要。让我们通过一个对比表格来直观展示:

特性SSR (服务端渲染)CSR (客户端渲染)
首次加载速度快 - 返回完整HTML慢 - 需要下载JS后再渲染
SEO友好度高 - 爬虫直接获取完整内容低 - 初始HTML内容少
服务器负载高 - 每次请求都需要渲染低 - 静态文件托管即可
交互体验页面切换需要整页刷新局部更新,体验流畅
开发复杂度需要考虑服务端兼容性只需关注浏览器环境
适用场景内容型网站(新闻、博客)交互型应用(后台管理系统)

在实际项目中,我们经常会采用混合模式(SSR+CSR),比如:

  • 首屏使用SSR保证加载速度和SEO
  • 后续交互采用CSR提升用户体验
  • Next.js和Nuxt.js等框架就是基于这种理念

4. 项目优化与扩展

基础功能完成后,我们可以考虑以下几个优化方向:

4.1 添加页面缓存

频繁调用API会拖慢响应速度,我们可以添加简单的缓存机制:

let cachedCats = null; let lastFetchTime = 0; async function getCatData() { const now = Date.now(); // 缓存1小时 if (!cachedCats || now - lastFetchTime > 3600000) { const response = await fetch('https://api.thecatapi.com/v1/images/search?limit=9'); cachedCats = await response.json(); lastFetchTime = now; } return cachedCats; }

4.2 支持分页加载

扩展我们的API调用,支持分页参数:

async function generateCatPage(page = 1) { // ... const response = await fetch( `https://api.thecatapi.com/v1/images/search?limit=9&page=${page}` ); // ... // 添加分页导航 const pagination = document.createElement('div'); pagination.className = 'pagination'; for (let i = 1; i <= 3; i++) { const link = document.createElement('a'); link.href = `/page-${i}.html`; link.textContent = i; if (i === page) link.className = 'active'; pagination.appendChild(link); } document.body.appendChild(pagination); }

4.3 添加响应式设计

通过媒体查询确保在不同设备上都有良好显示:

<style> .cat-grid { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); } @media (max-width: 768px) { .cat-grid { grid-template-columns: 1fr; } } </style>

5. 部署与实战建议

完成开发后,部署这个SSR应用非常简单,因为最终生成的是静态HTML文件。你可以:

  1. 直接托管在GitHub Pages、Netlify或Vercel等静态托管服务上
  2. 使用Node.js服务器动态生成(适合需要实时数据的场景)
const http = require('http'); const server = http.createServer(async (req, res) => { if (req.url === '/') { await generateCatPage(); const html = fs.readFileSync('./public/index.html'); res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(html); } }); server.listen(3000, () => { console.log('Server running at http://localhost:3000'); });

在实际项目中,还需要考虑以下因素:

  • 错误处理:API请求失败时的回退方案
  • 加载状态:在生成页面时显示加载指示器
  • 渐进增强:确保JS禁用时基础功能仍可用

这个项目虽然简单,但涵盖了SSR的核心概念。通过动手实践,你应该对服务端渲染有了更直观的理解。下次当你使用Next.js或Nuxt.js时,就会更清楚它们底层是如何工作的了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询