script para setResponse
<script>
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\u003c')}
</script>```
Conocimientos necesarios para aplicar SSR
Lo que aprenderás sobre server side render
Presentación del proyecto del curso y sus herramientas
¿Qué es Server Side Rendering?
Preparando entorno para aplicar SSR
Actualizando dependencias en NPM
Creación del servidor en Express
Usando Nodemon y Dotenv
Integración de Webpack con Express
Integración de Express con React
Servir React con Express
Abstrayendo React Router, creando history y haciendo initialState más accesible
Aplicar Server Side Rendering
Definición de la función principal para realizar el renderizado desde el servidor
Assets require hook
Hydrate y estado de Redux desde Express
Trabaja con entornos de desarrollo y producción
Configurando nuestro servidor para producción
Configurando webpack para producción
Optimización del Build
Aplicar hashes al nombre de nuestros builds
Buenas prácticas de Server Side Render
Vendorfiles en Webpack: definiendo cacheGroups
Vendorfiles en Webpack: generando el vendorfile
Configuración de ESLint
Alternativas al SSR con Express
Cómo implementar Next.js
Cómo usar Gatsby.js
Cuando usar cada una de las herramientas presentadas
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Aportes 26
Preguntas 5
script para setResponse
<script>
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\u003c')}
</script>```
Gran manera de resumir renderToString e hydrate, definitivamente todo queda más claro 😄
En este punto, la aplicación ya esta siendo servida mediante SSR pero de una manera ineficiente. Actualmente se están realizando dos renderizados: uno en el servidor que carga solamente el html y css (sin eventos asociados) para ser servido como respuesta y luego otro en el browser (como normalmente lo haría). Para solventar esto, se debe configurar la aplicación desde el front para que hidrate (complemente) lo que viene precargado como respuesta del servidor.
En el index de la carpeta frontend se debe reemplazar la funcion render de ReactDOM por hydrate:
ReactDOM.hydrate(
<Provider store={store}>
<Router history={history}>
<App />
</Router>
</Provider>,
document.getElementById('app'),
);
El initialState de la aplicación esta siendo declarado 2 veces, siendo esto una forma ineficiente de utilizarlo. Para optimizar esta situacion se debe definir un estado base (preloadedState) en la funcion que inicializa el store y crea el string renderizado de la app. Luego se debe enviar como parametro ese estado a la funcion setResponse para que esta lo incluya dentro del cuerpo de la respuesta del servidor.
const renderApp = (req, res) => {
const store = createStore(reducer, initialState);
const preloadedState = store.getState();
const html = renderToString(
<Provider store={store}>
<StaticRouter location={req.url} context={{}}>
{renderRoutes(serverRoutes)}
</StaticRouter>
</Provider>,
);
res.send(setResponse(html, preloadedState));
};
Para poder enviar el estado base (preloadedState) en la respuesta, se debe guardar de la siguiente forma:
const setResponse = (html, preloadedState) => {
return (`
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="assets/app.css" type="text/css">
<title>Platzi Video</title>
</head>
<body>
<div id="app">${html}</div>
<script>
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\u003c')}
</script>
<script src="assets/app.js" type="text/javascript"></script>
</body>
</html>
`);
};
Ahora en el archivo index.js de la carpeta frontend se debe eliminar la referencia al initialState: import initialState from './initialState';
y luego se llama al preloadedState definido desde el servidor. Con ese mismo estado precargado se debe crear el store y luego por temas de seguridad ha de ser eliminado:
const preloadedState = window.__PRELOADED_STATE__;
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer, preloadedState, composeEnhancers());
delete window.__PRELOADED_STATE__;
Si alguien de pronto tuvo un error al desplegar el JS recuerden que SIEMPRE debe ir primero el script que trae el state, antes del script con el css y el JS de la siguiente forma.
Estaba pasándolo al revés y por eso la pasé bastante con un error pendejillo jeje 😄
Gran analogía :V
Me esta saliendo este error alguien que me pueda decir porque sale Gracias
react-dom.development.js:88 Warning: Expected server HTML to contain a matching <div> in <div>.
in div (created by Layout)
in Layout (created by App)
in Router (created by BrowserRouter)
in BrowserRouter (created by App)
in App
in Router
in Provider
si tengo puesto el “hydrate” no me carga algunas imagenes ni esyilos, cuando recargo la pagina.
solo con el “render” :c
Primero se envía un string con html y css, después se hidrata con javascript y el preloaded state? de ésta forma el cliente puede ver el html y css antes de tener la pagina totalmente interactiva. Estoy bien?
Hola Devs:
Aqui tienen la lectura del ReactDOM.hydrate(): Click Aqui
wow todo mas claro la verdad.
Hydrate para evitar el doble render y luego window.preload_state para de pre-cargar el estado del que se alimenta el redux.
Me surge la duda al momento de eliminar el PREALOADED_STATE del window. ¿Realmente lo hacemos bien de esta forma? si hago una búsqueda en el código y pongo un punto de ruptura antes de eliminarlo puedo inspeccionar el initialState. ¿o al enviar a producción o en unas clases siguientes hay más pasos que evitan que esto pueda hacerse?
Me fascina cuando dice la frase "Vamos a hacer una recapitulacion’, Excelent Teacher!!!
Después de mucho luchar se pudo estabilizar el proyecto, todos los errores eran por las librerías de babel las actualice todas y se solucionó el problema
mind blowing
✌
Es la tercera vez que veo el curso y apenas le estoy entendiendo
Excelente clase! Super explicado. Así es como deberían de ser todas las clases en los cursos de Platzi. A mi parecer, este profesor explica mucho mejor que el del curso anterior de la ruta de JS. La neta.
Te amo un poquito Sampol
excelente clase
Osea que a esta altura ya tendrían que funcionar los eventos con el JavaScript desactivado?
Hola, hice todo al pie de la letra, pero cuando quiero ir a otras rutas de la app, me aparece el siguiente error en consola: “Uncaught SyntaxError: Unexpected token ‘<’” y muestra el html plano de app.js como referencia de la linea. A alguien le pasó algo así? Estoy trabado hace varios dias con esto
Ahora si se puso bueno 😄
Ayuda, alguién sabe como manejar el combinereducer de redux desde el lado del servidor?
complejo
Que gran clase, aquí quedó mucho más claro lo que estabamos realizando.
Un poco complejo
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?
o inicia sesión.