Как реализовать серверный рендеринг без Nuxt.js

Ответ

Для SSR без Nuxt.js можно использовать Express + React/Vue с рендерингом на сервере. Основные шаги:

  1. Настроить Express сервер:
const express = require('express');
const ReactDOMServer = require('react-dom/server');
const app = express();

app.get('*', (req, res) => {
  const html = ReactDOMServer.renderToString(<App />);
  res.send(`
    <!DOCTYPE html>
    <html>
      <head><title>SSR App</title></head>
      <body>
        <div id="root">${html}</div>
        <script src="/client.js"></script>
      </body>
    </html>
  `);
});
  1. Для Vue аналогично использовать vue-server-renderer:
const renderer = require('vue-server-renderer').createRenderer();
renderer.renderToString(app, (err, html) => {
  // отправить html
});
  1. Собрать клиентский бандл с гидратацией:
ReactDOM.hydrate(<App />, document.getElementById('root'));

Ключевые моменты:

  • Сервер генерирует HTML при первом запросе
  • Клиентский JS "оживляет" (гидратирует) приложение
  • Нужно настраивать Webpack для серверного и клиентского бандлов
  • Для маршрутизации использовать StaticRouter (React) или vue-router в SSR-режиме

Это базовый подход, в реальных проектах стоит добавить кэширование, обработку данных и ошибок.

Ответ 18+ 🔞

А, ну это ж классика, блядь! Слушай, сейчас я тебе на пальцах объясню, как эту SSR-хуйню без этого твоего заморского Nuxt.js на коленке собрать. Ёпта, ну что за детский сад, внатуре.

Так, смотри сюда. Берёшь ты голый Express, как мужик, и на нём всё строишь. Для React'а это выглядит примерно так, пиздец просто:

const express = require('express');
const ReactDOMServer = require('react-dom/server');
const app = express();

app.get('*', (req, res) => {
  const html = ReactDOMServer.renderToString(<App />);
  res.send(`
    <!DOCTYPE html>
    <html>
      <head><title>SSR App</title></head>
      <body>
        <div id="root">${html}</div>
        <script src="/client.js"></script>
      </body>
    </html>
  `);
});

Видишь? Сервер, сука, взял твой компонент <App />, превратил его в строку с HTML и плюнул её в браузер. Всё, приехали. А для Vue, там та же песня, только с другим названием пакета, ядрёна вошь:

const renderer = require('vue-server-renderer').createRenderer();
renderer.renderToString(app, (err, html) => {
  // отправить html
});

Ну и главный фокус, блядь, чтобы не было стыдно! На клиенте ты этот высранный сервером HTML не выбрасываешь, а «оживляешь». Гидратация, мать её. Вот так:

ReactDOM.hydrate(<App />, document.getElementById('root'));

Клиентский скрипт смотрит на уже готовую разметку и говорит: «О, сука, да тут всё уже есть!» — и просто навешивает на неё свои обработчики, не перерисовывая заново. Красота, ёпта!

Но это, конечно, база, на которой потом вырастает овердохуища проблем. Надо два отдельных сборщика — один для серверного бандла, другой для клиентского. Маршрутизатор на сервере через StaticRouter прогонять, а на клиенте — обычный. Данные подтягивать, кэшировать, ошибки ловить... В общем, веселье на неделю, если не на месяц.

Короче, Nuxt.js — это когда тебе лень эту всю хуйню самому паять. А если охота приключений на свою жопу — дерзай, чувак.