Código de reacción dividido en 2019

¡Es 2019! Todos piensan que conocen la división de código. Entonces, ¡revisemos dos veces!



¬ŅQu√© significa la divisi√≥n de c√≥digo?


En resumen, la división de código consiste en no cargar todo. Entonces estás leyendo esta página, no tienes que cargar un sitio completo. Cuando selecciona una sola fila de una base de datos, no tiene que tomar todo.
Obvio? La división del código también es bastante obvia, no solo sobre sus datos, sino sobre su código.


¬ŅQui√©n (¬ŅQu√©?) ¬ŅEst√° dividiendo el c√≥digo?


React.lazy ? No, solo lo usa. La divisi√≥n de c√≥digo se realiza en un nivel de paquete: paquete web, parcela o simplemente su sistema de archivos en el caso de m√≥dulos esm "nativos". La divisi√≥n de c√≥digo es solo archivos, archivos que puede cargar en alg√ļn lugar "m√°s tarde". Entonces, a las preguntas " ¬ŅQu√© es la divisi√≥n de c√≥digo de alimentaci√≥n? ", La respuesta es: un "paquete".


¬ŅQui√©n (Qu√©) est√° usando la divisi√≥n de c√≥digo?


React.lazy está usando. Simplemente usando la división de código de su paquete. Simplemente llamando a import cuando se procesó. Y eso es todo.


¬ŅQu√© hay de React-loadable?


React.lazy reemplazó. Y proporcionó más funciones, como Suspense para controlar el estado de carga. Entonces, use React.Lazy en React.Lazy lugar.


Sí, eso es todo. Gracias por leer y que tengas un buen día.

¬ŅPor qu√© el art√≠culo no est√° terminado?


Bueno Hay algunas zonas grises sobre React.lazy y la división de código que olvidé mencionar.


Zona gris 1 - prueba


No es fácil probar React.lazy debido a su asincronía . Estaría simplemente "vacío", siempre y cuando todavía no esté cargado (incluso si lo está): Promises e devoluciones de import , y acepta perezosamente, promesas , que siempre se ejecutaron en el siguiente tic .


¬ŅSoluci√≥n propuesta? No lo creer√≠a, pero la soluci√≥n propuesta es utilizar thenables sincr√≥nicos: consulte la solicitud de extracci√≥n . Entonces, ¬°hagamos que nuestras imports SINCR√ďNICAS! (para solucionar un problema vago para las pruebas o cualquier otro caso del lado del servidor)


 const LazyText = lazy(() => ({ then(cb) { cb({default: Text}); // this is "sync" thenable }, })); const root = ReactTestRenderer.create( <Suspense fallback={<Text text="Loading..." />}> <LazyText text="Hi" /> // this lazy is not very lazy </Suspense>, ); 

No es difícil convertir la función de importación en una función sincronizable memorizable.


 const syncImport = (importFn) => { let preloaded = undefined; const promise = importFn().then(module => preloaded = module); // ^ "auto" import and "cache" promise return () => preloaded ? { then: () => preloaded } : promise; // ^ return sync thenable then possible } const lazyImport = isNode ? syncImport : a => a; // ^ sync for node, async for browser const LazyComponent = React.lazy(lazyImport(() => import('./file')); 

Zona gris 2 - SSR


Si NO necesita SSR, ¬°contin√ļe leyendo el art√≠culo!

React.lazy es React.lazy SSR. Pero requiere Suspense para funcionar, y Suspenso NO es amigable con el servidor .


Hay 2 soluciones:


  • Reemplace Suspenso con Fragmento, por ejemplo, a trav√©s de la burla. Luego, use la versi√≥n alterada de import with synchronous para hacer que la perezosa tambi√©n se comporte sincr√≥nicamente.
     import React from 'react'; const realLazy = React.lazy; React.lazy = importer => realLazy(syncImport(importer)); React.Suspense = React.Fragment; // :P // ^ React SSR just got fixed :D 

Esta es una buena opción, pero no sería del todo amigable para el cliente. Por qué Definamos la segunda solución posible:


  • Use una biblioteca especializada para rastrear los scripts, fragmentos y estilos usados, y c√°rguelos en el lado del cliente (¬°especialmente los estilos!) Antes de reaccionar la hidrataci√≥n. O bien, representar√≠a agujeros vac√≠os en lugar de sus componentes divididos en c√≥digo. Una vez m√°s, no carg√≥ el c√≥digo que acaba de dividir, por lo que no puede procesar nada de lo que va a hacer.

He aquí las bibliotecas de división de código


  • Componente universal : la biblioteca m√°s antigua y a√ļn mantenible. "Invent√≥" la divisi√≥n de c√≥digo en t√©rminos de Webpack ense√Īado a la divisi√≥n de c√≥digo.
  • Cargable por reacci√≥n : muy popular, pero una biblioteca sin mantenimiento. Hizo que el c√≥digo escupiera algo popular. Los problemas est√°n cerrados, por lo que no hay comunidad alrededor.
  • Componentes cargables : una biblioteca completa de funciones, es un placer usarla, con la comunidad m√°s activa.
  • Componente importado : una biblioteca √ļnica, no vinculada a Webpack, es decir, capaz de manejar parcela o esm.
  • Componente React-async : biblioteca ya muerta (pero popular), que tuvo un impacto significativo en todo lo relacionado con la divisi√≥n de c√≥digo, el recorrido personalizado del √°rbol React y la SSR.
  • Otra biblioteca, hab√≠a muchas bibliotecas, muchas de las cuales no sobrevivieron a la evoluci√≥n de Webpack o React 16, no las he enumerado aqu√≠, pero si conoces a un buen candidato, solo env√≠ame un mensaje.

¬ŅQu√© biblioteca elegir?


Es fácil, no reacciona cargable , es pesado, sin mantenimiento y obsoleto, incluso si todavía es mega popular. (y gracias por popularizar la división de código, una vez más)


Componentes cargables : puede ser una muy buena opción. Está muy bien escrito, se mantiene activamente y admite todo de forma inmediata. Admite "importaciones dinámicas completas", lo que le permite importar archivos dependiendo de los accesorios proporcionados, pero por lo tanto no se pueden tipificar. Admite suspenso, por lo que podría reemplazar React.lazy.


Componente universal , en realidad "inventores" de importaciones dinámicas completas, lo implementaron en Webpack. Y muchas otras cosas a bajo nivel, lo hicieron. Yo diría que esta biblioteca es un poco dura y un poco menos fácil de usar. La documentación de los componentes cargables es inmejorable. Vale la pena si no usa esta biblioteca, luego lea la documentación: hay tantos detalles que debe saber ...


Componente importado por reacci√≥n : es un poco extra√Īo. Es independiente del paquete, por lo que nunca se romper√≠a (no hay nada que romper), funcionar√≠a con Webpack 5 y 55, pero eso tiene un costo. Mientras que las bibliotecas anteriores durante SSR agregar√≠an todas las secuencias de comandos utilizadas al cuerpo de la p√°gina, y podr√° cargar todas las secuencias de comandos en paralelo: los nombres de archivos no conocidos importados y llamar√°n a las "importaciones" originales (por eso paquete independiente) para cargar fragmentos usados, pero solo puede realizar llamadas desde el paquete principal, por lo que todos los scripts adicionales se cargar√°n solo despu√©s de que se descargue y ejecute el principal. No admite importaciones din√°micas completas, como React.lazy y, como resultado, puede escribirse. Tambi√©n es compatible con suspenso. Utiliza thenables sincr√≥nicos en SSR. Tambi√©n tiene un enfoque absolutamente diferente para CSS y un soporte perfecto para la representaci√≥n de secuencias.


No hay diferencia en calidad o popularidad entre las bibliotecas que figuran en la lista, y todos somos buenos amigos, así que elige de todo corazón.


Zona gris 3 - render híbrido


SSR es algo bueno, pero, ya sabes, dif√≠cil. Los proyectos peque√Īos pueden querer tener un SSR, hay muchas razones para tenerlo, pero es posible que no quieran configurarlo y mantenerlo.


SSR podría ser realmente, REALMENTE difícil. Prueba razzle o ve con Next.js si quieres una victoria rápida.

Por lo tanto, la solución más fácil para SSR, especialmente para un SPA simple, sería la representación previa. Como abrir su SPA en un navegador y presionar el botón "Guardar". Como:


  • React-snap : utiliza el titiritero (tambi√©n conocido como Chrome sin cabeza) para representar su p√°gina en un "navegador" y guarda un resultado como una p√°gina HTML est√°tica.
  • Rendertron : que hace lo mismo, pero de una manera diferente (en la nube ).

La representación previa es "SSR" sin "Servidor". Es SSR usando un Cliente. Magia! Y trabajando fuera de la caja ... ... ... pero no para escupir código.
Entonces, acabas de renderizar tu página en un navegador, guardaste HTML y pediste cargar las mismas cosas. Pero no se usó el código específico del lado del servidor (para recopilar todos los fragmentos usados), ¡porque NO HAY SERVIDOR !



En la parte anterior, he se√Īalado las bibliotecas que est√°n vinculadas a webpack en t√©rminos de recopilaci√≥n de informaci√≥n sobre fragmentos usados: no pod√≠an manejar el renderizado h√≠brido en absoluto.


La versión 2 de componentes cargables (incompatible con la versión 5 actual) fue parcialmente compatible con react-snap. El apoyo se ha ido.

El componente importado por reacción podría manejar este caso, siempre y cuando no esté unido al paquete / lado, por lo que no hay diferencia para SSR o híbrido, sino solo para reacción instantánea, siempre que sea compatible con la "hidratación del estado", mientras que el rendertron no.


Esta capacidad de reaccionar-componente importado se encontró durante la redacción de este artículo, no se conocía antes - ver ejemplo Es muy facil.

Y aquí debe usar otra solución, que es perpendicular a todas las demás bibliotecas.


Componente de reacción previa


Esta biblioteca fue creada para una hidrataci√≥n parcial y podr√≠a rehidratar parcialmente su aplicaci√≥n, manteniendo el resto a√ļn deshidratado. Y funciona para renderizadores SSR e h√≠bridos sin ninguna diferencia.
La idea es simple:


  • durante SSR: renderice el componente, envuelto con un <div />
  • en el cliente: busque ese div y use innerHTML hasta que Component est√© listo para reemplazar HTML muerto.
  • no tiene que cargar, y espere un trozo con un componente dividido antes de hydrate para NO generar un agujero blanco en su lugar , solo use HTML pre-renderizado, que es absolutamente igual al que representar√≠a un componente real , y que ya existe: viene con una respuesta de servidor (o hidrid).

Es por eso que tenemos que esperar a que se carguen todos los fragmentos antes de hidratarse, para que coincida con el HTML renderizado por el servidor. Es por eso que podríamos usar piezas de HTML renderizado por el servidor hasta que el cliente no esté listo: es igual al que solo vamos a producir.

 import {PrerenderedComponent} from 'react-prerendered-component'; const importer = memoizeOne(() => import('./Component')); // ^ it's very important to keep the "one" promise const Component = React.lazy(importer); // or use any other library with ".prefetch" support // all libraries has it (more or less) const App = () => ( <PrerenderedComponent live={importer()}> {/* ^ shall return the same promise */ } <Component /> {/* ^ would be rendered when a component goes "live" */ } </PrerenderedComponent> ); 

Hay otro art√≠culo sobre esta tecnolog√≠a , puede leer. Pero lo principal aqu√≠ es que resuelve "Flash de contenido descargado" en otro, no es una forma com√ļn de bibliotecas de divisi√≥n de c√≥digo . Est√© abierto a nuevas soluciones.


TLDR?


  • no use react-loadable, no agregar√≠a ning√ļn valor valioso
  • React.lazy es bueno, pero demasiado simple todav√≠a.
  • SSR es algo dif√≠cil, y debes saberlo
  • El renderizado h√≠brido dirigido por titiriteros es una cosa. A veces algo a√ļn m√°s dif√≠cil.

Source: https://habr.com/ru/post/444402/


All Articles