前端 SSR:别让你的网站变成 SEO 黑洞
前端 SSR:别让你的网站变成 SEO 黑洞
毒舌时刻
这网站做得跟黑洞似的,搜索引擎根本爬不进去。
各位前端同行,咱们今天聊聊前端 SSR(服务端渲染)。别告诉我你还在使用纯客户端渲染,那感觉就像在没有窗户的房间里生活——能住,但看不见外面的世界。
为什么你需要 SSR
最近看到一个项目,纯客户端渲染,SEO 排名倒数,用户体验差。我就想问:你是在做网站还是在做内部工具?
反面教材
// 反面教材:纯客户端渲染 // App.jsx import React, { useState, useEffect } from 'react'; function App() { const [data, setData] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchData() { setLoading(true); try { const response = await fetch('/api/data'); const result = await response.json(); setData(result); } catch (error) { console.error('Error fetching data:', error); } finally { setLoading(false); } } fetchData(); }, []); return ( <div> <h1>我的网站</h1> {loading ? <div>加载中...</div> : ( <div> {data.map(item => ( <div key={item.id}> <h2>{item.title}</h2> <p>{item.content}</p> </div> ))} </div> )} </div> ); } export default App; 毒舌点评:这代码,就像在黑暗中摸索,搜索引擎根本找不到你的内容。
正确姿势
1. Next.js SSR
// 正确姿势:Next.js SSR // 1. 安装依赖 // npx create-next-app@latest // 2. 页面组件 // pages/index.js import React from 'react'; export async function getServerSideProps() { // 服务端获取数据 const res = await fetch('https://api.example.com/data'); const data = await res.json(); return { props: { data } }; } export default function Home({ data }) { return ( <div> <h1>我的网站</h1> <div> {data.map(item => ( <div key={item.id}> <h2>{item.title}</h2> <p>{item.content}</p> </div> ))} </div> </div> ); } 2. Nuxt.js SSR
// 正确姿势:Nuxt.js SSR // 1. 安装依赖 // npx create-nuxt-app@latest // 2. 页面组件 // pages/index.vue <template> <div> <h1>我的网站</h1> <div> <div v-for="item in data" :key="item.id"> <h2>{{ item.title }}</h2> <p>{{ item.content }}</p> </div> </div> </div> </template> <script> export default { async asyncData({ $axios }) { // 服务端获取数据 const { data } = await $axios.get('https://api.example.com/data'); return { data }; } }; </script> 3. Remix SSR
// 正确姿势:Remix SSR // 1. 安装依赖 // npx create-remix@latest // 2. 路由组件 // app/routes/index.jsx import { json } from '@remix-run/node'; export async function loader() { // 服务端获取数据 const response = await fetch('https://api.example.com/data'); const data = await response.json(); return json({ data }); } export default function Home() { const { data } = useLoaderData(); return ( <div> <h1>我的网站</h1> <div> {data.map(item => ( <div key={item.id}> <h2>{item.title}</h2> <p>{item.content}</p> </div> ))} </div> </div> ); } 4. React 18 SSR
// 正确姿势:React 18 SSR // 1. 安装依赖 // npm install react react-dom express // 2. 服务端代码 // server.js import express from 'express'; import React from 'react'; import { renderToString } from 'react-dom/server'; import App from './App'; const app = express(); app.get('*', async (req, res) => { // 服务端获取数据 const response = await fetch('https://api.example.com/data'); const data = await response.json(); const html = renderToString(<App data={data} />); res.send(` <!DOCTYPE html> <html> <head> <title>我的网站</title> </head> <body> <div>${html}</div> <script> window.__INITIAL_DATA__ = ${JSON.stringify(data)}; </script> <script src="/bundle.js"></script> </body> </html> `); }); app.listen(3000, () => { console.log('Server is running on port 3000'); }); // 3. 客户端代码 // App.jsx import React from 'react'; function App({ data }) { return ( <div> <h1>我的网站</h1> <div> {data.map(item => ( <div key={item.id}> <h2>{item.title}</h2> <p>{item.content}</p> </div> ))} </div> </div> ); } export default App; // 4. 客户端入口 // client.js import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <App data={window.__INITIAL_DATA__} /> </React.StrictMode> ); 毒舌点评:这才叫前端 SSR,服务端渲染内容,搜索引擎友好,用户体验好,再也不用担心 SEO 问题了。