What is SSR?

👨‍💻 Frontend Developer 🟠 May come up 🎚️ Medium
#React #Next.js #SSR

Brief Answer

SSR (Server-Side Rendering) is a technology for rendering web pages on the server with sending ready HTML to the client:

  1. Server rendering — HTML is generated before sending 🖥️
  2. Fast loading — content is visible immediately ⚡
  3. SEO optimization — search engines see ready content 🔍
  4. Hydration — React connects to ready markup 💧
  5. Improved performance — especially on slow devices 📱
  6. Better UX — users see content faster 👁️
// Component renders on server
function HomePage({ posts }) {
  return (
    <div>
      <h1>Blog</h1>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.excerpt}</p>
        </article>
      ))}
    </div>
  );
}

Full Answer

SSR is like a ready meal served in a restaurant, not ingredients for self-cooking! The server prepares HTML in advance and sends it to the browser. 🍽️

How SSR works

// 1. Request comes to server
app.get('/', async (req, res) => {
  // 2. Fetch data
  const posts = await fetchPosts();
  
  // 3. Render component to HTML
  const html = renderToString(
    <HomePage posts={posts} />
  );
  
  // 4. Send ready HTML
  res.send(`
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root">${html}</div>
        <script src="/bundle.js"></script>
      </body>
    </html>
  `);
});

SSR vs CSR (Client-Side Rendering)

// CSR - client-side rendering
function App() {
  const [posts, setPosts] = useState([]);
  
  useEffect(() => {
    // Data loads after render
    fetchPosts().then(setPosts);
  }, []);
  
  return (
    <div>
      {posts.length ? (
        posts.map(post => <Post key={post.id} {...post} />)
      ) : (
        <div>Loading...</div>
      )}
    </div>
  );
}
 
// SSR - data is already available
function App({ posts }) {
  // Content is ready immediately
  return (
    <div>
      {posts.map(post => (
        <Post key={post.id} {...post} />
      ))}
    </div>
  );
}

Hydration

// On server
const html = renderToString(<App data={data} />);
 
// On client - hydration
import { hydrateRoot } from 'react-dom/client';
 
hydrateRoot(
  document.getElementById('root'),
  <App data={window.__INITIAL_DATA__} />
);
// pages/index.js
export default function Home({ posts }) {
  return (
    <div>
      <h1>Home Page</h1>
      {posts.map(post => (
        <div key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.content}</p>
        </div>
      ))}
    </div>
  );
}
 
// Function runs on server
export async function getServerSideProps() {
  const posts = await fetch('https://api.example.com/posts')
    .then(res => res.json());
  
  return {
    props: { posts }
  };
}

Static Site Generation (SSG)

// Generation at build time
export async function getStaticProps() {
  const posts = await fetchPosts();
  
  return {
    props: { posts },
    revalidate: 60 // Update every 60 seconds
  };
}
 
// Dynamic routes
export async function getStaticPaths() {
  const posts = await fetchPosts();
  
  return {
    paths: posts.map(post => ({
      params: { id: post.id.toString() }
    })),
    fallback: 'blocking'
  };
}

SSR Advantages

  1. Fast First Contentful Paint
  2. Better SEO — search engines see content 🔍
  3. Social media — proper previews 📱
  4. Performance on weak devices 📲
  5. Accessibility — works without JavaScript 👥
// SEO-friendly component
function ProductPage({ product }) {
  return (
    <>
      <Head>
        <title>{product.name} - Store</title>
        <meta name="description" content={product.description} />
        <meta property="og:title" content={product.name} />
        <meta property="og:image" content={product.image} />
      </Head>
      
      <main>
        <h1>{product.name}</h1>
        <img src={product.image} alt={product.name} />
        <p>{product.description}</p>
        <span>Price: ${product.price}</span>
      </main>
    </>
  );
}

SSR Disadvantages

  1. Server complexity — need server infrastructure 🖥️
  2. Response time — server must process request ⏱️
  3. Server load — each request requires rendering 💪
  4. Caching complexity — dynamic content 🗄️

Rendering Strategies

// 1. Full SSR
export async function getServerSideProps(context) {
  const data = await fetchUserData(context.req);
  return { props: { data } };
}
 
// 2. Static generation
export async function getStaticProps() {
  const data = await fetchStaticData();
  return { 
    props: { data },
    revalidate: 3600 // ISR
  };
}
 
// 3. Hybrid approach
function Page({ staticData }) {
  const [dynamicData, setDynamicData] = useState(null);
  
  useEffect(() => {
    fetchDynamicData().then(setDynamicData);
  }, []);
  
  return (
    <div>
      <StaticContent data={staticData} />
      {dynamicData && <DynamicContent data={dynamicData} />}
    </div>
  );
}

SSR Optimization

// Caching
import { cache } from 'react';
 
const fetchPosts = cache(async () => {
  const response = await fetch('/api/posts');
  return response.json();
});
 
// Streaming rendering
import { renderToPipeableStream } from 'react-dom/server';
 
app.get('/', (req, res) => {
  const stream = renderToPipeableStream(
    <App />,
    {
      onShellReady() {
        res.setHeader('Content-Type', 'text/html');
        stream.pipe(res);
      }
    }
  );
});

Best Practices

  1. Use caching for static content 🗄️
  2. Optimize database queries 🚀
  3. Implement streaming rendering for large pages 🌊
  4. Separate static and dynamic content ⚖️

Common Mistakes

Wrong:

// Using browser-only API
function Component() {
  const width = window.innerWidth; // Error on server
  return <div>Width: {width}</div>;
}

Correct:

function Component() {
  const [width, setWidth] = useState(0);
  
  useEffect(() => {
    setWidth(window.innerWidth);
  }, []);
  
  return <div>Width: {width || 'Loading...'}</div>;
}

Conclusion

SSR is a powerful technology for improving performance and SEO:

  • Fast loading — content is visible immediately
  • SEO optimization — search engines index content
  • Better UX — especially on slow connections
  • Flexibility — can be combined with CSR

Choose SSR for content sites, blogs and e-commerce! 🎯