Resumen

Lograr que tu entorno de desarrollo sea tan fluido como el de Create React App, pero sobre un servidor Express con server side rendering, es uno de los pasos más satisfactorios al construir tu propio motor de renderizado. Aquí se configura webpack para compilar en tiempo real, abrir el navegador automáticamente y recargar cambios al instante gracias al Hot Module Replacement.

¿Qué dependencias necesitas para activar el modo desarrollo?

Antes de tocar cualquier archivo, es necesario instalar tres paquetes en modo desarrollo [00:47]:

  • webpack-hot-middleware: habilita el Hot Module Replacement (HMR), es decir, la recarga instantánea de módulos sin refrescar toda la página.
  • webpack-dev-middleware: conecta el compilador de webpack directamente al servidor Express, eliminando la necesidad de ejecutar builds manuales.
  • react-dev-utils: proporciona utilidades que usa internamente Create React App, como un error overlay que muestra errores en pantalla y una función llamada openBrowser que abre el navegador automáticamente al iniciar el servidor.

Con estas tres piezas, el servidor detecta cambios en el código fuente, recompila solo lo necesario y actualiza el navegador de forma casi inmediata.

¿Cómo se construye el middleware de webpack?

Dentro de la carpeta del servidor se crea un directorio llamado middlewares y un archivo webpack-middleware.ts [01:22]. Un middleware es una función que intercepta una petición antes de que llegue al manejador final del servidor. En este caso, se interpone para activar el entorno de desarrollo.

El archivo importa las dependencias instaladas y la configuración de webpack del cliente:

typescript import webpack from 'webpack'; import WHM from 'webpack-hot-middleware'; import devMiddleware from 'webpack-dev-middleware'; import errorOverlay from 'react-dev-utils/errorOverlayMiddleware'; import openBrowser from 'react-dev-utils/openBrowser'; import webpackClientConfig from '../../webpack.config.client.js';

Lo primero que ejecuta es openBrowser apuntando a la URL configurada con el puerto del servidor [02:52]. Después crea el compilador de webpack pasándole la configuración del cliente. Este compilador expone hooks que permiten reaccionar cuando la compilación termina o falla.

¿Qué opciones recibe el Hot Module Replacement?

Al configurar webpack-hot-middleware se le pasan tres opciones clave [04:15]:

  • log: se asigna console.log como logger.
  • path: la ruta donde se expone el servicio HMR, típicamente /__webpack_hmr.
  • heartbeat: cada cuántos milisegundos el servidor verifica la conexión con el cliente, en este caso 200 ms.

Para el webpack-dev-middleware las opciones son más directas: se activa serverSideRender en true y writeToDisk también en true, aprovechando las optimizaciones que trae webpack 5 para compilaciones en desarrollo [04:55].

¿Qué ajustes requiere la configuración de webpack del cliente?

Dentro del archivo de configuración del cliente se necesitan dos cambios importantes [05:38]:

  • Agregar el HotModuleReplacementPlugin: solo en modo desarrollo se hace push de new webpack.HotModuleReplacementPlugin() al arreglo de plugins.
  • Modificar las entradas: se usa entries.unshift() para agregar al inicio la cadena que indica a webpack dónde escuchar el HMR, incluyendo el path, el timeout y si debe recargar. Esta cadena viene documentada en la página oficial de webpack-hot-middleware [06:52].

El unshift garantiza que la entrada del HMR se cargue antes que el código de la aplicación.

¿Cómo se integra todo en el servidor Express?

En el archivo principal del servidor se importa el middleware recién creado y se aplica de forma condicional [08:00]:

typescript const isDev = process.env.NODE_ENV !== 'production';

if (isDev) { app.use(webpackMiddleware); } else { // Sirve archivos estáticos del build de producción }

Cuando el entorno no es producción, webpack compila directamente desde el servidor, haciendo innecesario correr un build manual previo. En producción se siguen sirviendo los archivos estáticos generados por el build tradicional.

Al ejecutar yarn dev, el servidor arranca, abre el navegador y muestra en consola el mensaje Hot Module Replacement Connected [08:38]. Cualquier cambio en un componente, por ejemplo modificar el texto dentro del componente Hero, se refleja instantáneamente sin recargar la página completa [08:52].

Con esta configuración se completa un ciclo donde el proyecto pasa de enviar HTML como template, a agregar JavaScript con renderizado completo, implementar prefetching y finalmente activar el HMR. El resultado es un clon funcional de lo que hace Next.js, con control total sobre cada capa del server side rendering. ¿Has construido tu propio motor de SSR o prefieres usar frameworks como Next.js? Comparte tu experiencia.