Repensando las Estrategias de Agrupación

Rate this content
Bookmark
Damos un vistazo a diferentes desafíos y decisiones al agrupar código para aplicaciones web. Observamos cómo se resuelven comúnmente estos y por qué necesitamos repensarlos.

This talk has been presented at React Day Berlin 2023, check out the latest edition of this React Conference.

FAQ

Tobias Cobbers es el creador de Webpack, una herramienta que desarrolló hace aproximadamente 11 o 12 años. Hace unos años, se unió al equipo de Vessel y trabajó en mejorar Webpack para Next.js. Actualmente, trabaja en TurboPack e integra Next.js con TurboPack.

El almacenamiento en caché a largo plazo se refiere al uso de la caché del navegador para almacenar recursos, especialmente entre implementaciones, con el objetivo de mejorar la carga de las páginas y reducir la cantidad de datos que se deben descargar en visitas sucesivas.

Los tres niveles de almacenamiento en caché en el navegador son: almacenamiento en caché máximo, donde los recursos son válidos por un tiempo determinado sin revalidación; almacenamiento en caché e-tech, que utiliza un hash del contenido para revalidar los recursos; y almacenamiento en caché inmutable, donde los recursos pueden ser almacenados indefinidamente sin revalidación usando URLs únicas.

Webpack maneja este problema utilizando un manifiesto que contiene los hashes de contenido de todos los recursos. Esto permite que cualquier cambio en un recurso solo afecte al archivo de manifiesto y no a todos los demás recursos, manteniendo así la caché de los fragmentos no relacionados.

La sacudida de árbol es una técnica de optimización utilizada para eliminar código no utilizado de las aplicaciones. Webpack implementa esta técnica en varias etapas, identificando primero todas las exportaciones que se utilizan y luego eliminando los módulos que no tienen efectos secundarios y no se utilizan.

Tobias Cobbers ve a TurboPack como un sucesor de Webpack, pero no como una nueva versión del mismo. TurboPack está diseñado específicamente para trabajar bien con Next.js y tiene un enfoque y un conjunto de APIs diferentes, lo que lo hace distinto a Webpack aunque comparten propósitos similares en el tratamiento de los módulos.

Tobias Koppers
Tobias Koppers
32 min
08 Dec, 2023

Comments

Sign in or register to post your comment.

Video Summary and Transcription

La charla discute sobre repensar las estrategias de agrupación, enfocándose en desafíos como el almacenamiento en caché a largo plazo y la mejora del estado de Next.js y Webpack. Explora el manejo del almacenamiento en caché inmutable y los hashes de contenido, optimizando las referencias de activos y los manifiestos de página, y abordando problemas con la navegación del lado del cliente y el almacenamiento en caché a largo plazo. La charla también cubre la eliminación de árboles y la optimización, optimizando los fragmentos de módulo y la ubicación del código, y el uso y la relación de TurboPack con Webpack. Además, toca la personalización de la configuración y los riesgos de hash, las importaciones de barril y la división de código, y los puntos de entrada y las heurísticas de fragmentación.
Available in English: Rethinking Bundling Strategies

1. Replanteando Estrategias de Agrupación

Short description:

Soy Tobias Cobbers, el creador de Webpack. Hoy quiero hablar sobre replanteando estrategias de agrupación, centrándome en dos desafíos en la escritura de agrupadores. El primer desafío es el almacenamiento en caché a largo plazo, aprovechando la caché del navegador para almacenar recursos entre implementaciones. El segundo desafío implica mejorar el estado actual de Next.js y Webpack. Vamos a sumergirnos en estos desafíos y explorar cómo podemos hacerlo mejor.

Gracias. Sí, en realidad estoy hablando de replanteando estrategias de agrupación hoy, y mi nombre es Tobias Cobbers. Creé Webpack hace 11 años o 12 años, y hace dos años, o hace tres años, me uní a Vessel y trabajé un poco en Next.js, mejorando Webpack para Next.js.

Ahora estoy trabajando en TurboPack e integrando Next.js con TurboPack. Mi charla es en realidad un poco más general, así que quiero hablar de algunas cosas. Quiero ver dos desafíos diferentes en la escritura de agrupadores. En realidad estamos mirando la magia en los agrupadores. Así que agarré dos temas para eso, dos desafíos que actualmente o en el futuro enfrentaré con la construcción de TurboPack. Y quiero profundizar un poco en eso porque creo que aprender esta magia de bundler puede ser importante, incluso si técnicamente no deberías enfrentarte a ella en tu trabajo diario. El bundler debería hacerlo transparente y no debería enfrentarte con todos estos desafíos. Debería resolverlo mágicamente. Pero creo que todavía es útil saberlo, y obtienes una visión profunda de eso, y puede ayudarte en algunos casos extremos.

Primero, quiero presentar estos dos desafíos, y luego entrar en el estado actual con Next.js y Webpack para eso. Y después de eso, quiero dedicar un poco de tiempo a repensar eso y cómo podemos mejorar en eso, qué podemos hacer mejor en el futuro, y qué queremos hacer en TurboPack con estos desafíos. Un pequeño descargo de responsabilidad primero, principalmente trabajo con Next.js, Webpack, y TurboPack, así que todo es desde la perspectiva de estas herramientas. Y todavía hay otras herramientas afuera, y tienen cosas similares, diferentes implementaciones. Y aunque la mayoría de las ideas no son realmente nuevas, están más inspiradas por otras herramientas y sí. Así que el primer tema es principalmente sobre el almacenamiento en caché a largo plazo, que realmente no es muy conocido por muchas personas. ¿Y qué es el almacenamiento en caché a largo plazo en absoluto? Así que el almacenamiento en caché a largo plazo significa que queremos aprovechar la caché del navegador, por lo que la memoria caché en el navegador para almacenar nuestros recursos, y especialmente entre implementaciones. Así que básicamente hay tres niveles, o tres niveles prácticos de aprovechamiento de la caché del navegador. El primero es el almacenamiento en caché máximo, donde simplemente especificas que mis recursos son válidos para dos horas, y no tienes que verificar eso de nuevo, y puedes usar la caché para dos horas. Pero en la práctica, es bastante inadecuado para nuestro caso de aplicación, porque podríamos tener una corrección de error crítica para solucionar, y queremos implementar algo, y no queremos esperar dos horas hasta que el usuario realmente obtenga una corrección de error. Así que no queremos usar eso en absoluto. Y lo que queremos usar es como el almacenamiento en caché e-tech, por ejemplo. Y el almacenamiento en caché e-tech significa básicamente que cuando el servidor responde con el recurso, envía un encabezado especial, e-tech, que generalmente contiene un hash del contenido, y luego el navegador almacena eso en su caché, y básicamente, en la caché. Y también quieres especificar tres fechas válidas, así que la próxima vez que el navegador quiera usar el recurso, simplemente hace una nueva solicitud para eso, pero incluye un encabezado especial si-no-coincide que incluye el e-tech, por lo que el hash del contenido, y luego el servidor podría, si el recurso no cambió en el ínterin, podría responder con un código de estado especial, como, no ha cambiado, puedes usar la caché, y no necesitas descargarlo de nuevo. Y eso básicamente siempre funciona, eso es genial. Pero siempre también revalida la solicitud. Así que básicamente envía una nueva solicitud, tienes que pagar el viaje de ida y vuelta, pero no tienes que pagar el costo de descarga. Así que es bueno, pero puedes hacerlo mejor.

2. Manejo de Caché Inmutable y Hashes de Contenido

Short description:

La mejor manera de manejar el almacenamiento en caché para recursos estáticos es a través del almacenamiento en caché inmutable, donde el navegador puede almacenar en caché los recursos indefinidamente. Para garantizar la consistencia, se utiliza una URL única con un hash de contenido, lo que permite realizar actualizaciones fácilmente sin romper la caché. Para lograr compilaciones deterministas, el agrupador debe generar la misma salida para la misma aplicación, al tiempo que garantiza que los pequeños cambios resulten en pequeños cambios de salida. Sin embargo, el manejo de los hashes de contenido se vuelve más complejo cuando hay referencias entre diferentes partes de la aplicación. Webpack y Next.js han avanzado en la solución de estos desafíos, pero el problema de los hashes de contenido persiste.

El mejor, creo, al menos para recursos estáticos y para ese tipo de cosas, es el almacenamiento en caché inmutable, lo que significa que envías control de caché inmutable y algunos otros encabezados, y eso significa que el navegador puede almacenarlo en caché para siempre, nunca tiene que hacer un viaje de ida y vuelta, nunca tiene que solicitarlo de nuevo, simplemente puede almacenarlo para siempre, generalmente un año o algo así.

Pero solo funciona, básicamente, si lo almacena sin revalidar para siempre, básicamente no puedes cambiar el contenido del recurso, porque si lo cambias, entonces podría ser inconsistente, y los navegadores podrían tenerlo aún en caché, no funciona.

Entonces, generalmente abordas eso haciendo que la URL de eso sea única de tal manera que nunca cambie. Entonces, generalmente la cosa es que simplemente agregas un hash de contenido a la URL, podrías haber visto eso con nombres de archivos que tienen este hash adjunto, y eso hace que la URL sea tan única que nunca cambiará y si implementas una nueva versión, simplemente obtendrá una nueva URL con un nuevo hash.

Sí, ese sería el mejor. Entonces, ¿cómo enfrentamos eso desde un nivel de agrupador? Entonces, el desafío se puede resolver con algunas técnicas diferentes. Entonces, una cosa es que queremos hacer que el bundler de tal manera que esté generando compilaciones deterministas. Entonces, una compilación debería, si compilas la misma aplicación, simplemente debería generar el mismo activo de salida para que la caché pueda ser utilizada realmente. Si generaras diferentes activos de salida, entonces no puedes usar la caché. Pero también quieres otra propiedad. Quieres esta propiedad de que incluso si haces un pequeño cambio en tu aplicación, que usualmente haces, como en cada solicitud de extracción o lo que sea, quieres una propiedad que un pequeño cambio resulte en un pequeño cambio de salida. Si solo cambias un módulo, podrías esperar que solo uno o pocos fragmentos cambien en el paquete de salida. Y sí, esa es la forma en que podemos usar generalmente nuestra caché del navegador. Ahora queremos usar esta cosa de almacenamiento en caché inmutable, por lo que solo queremos poner un hash de contenido en cada fuente o cada nombre de archivo que emitimos desde el bundler. Suena bastante fácil. Simplemente haces un hash del contenido, lo agregas al nombre del archivo. Pero se vuelve un poco complicado porque en realidad hay referencias entre las diferentes cosas en tu aplicación. Entonces, como un ejemplo, HTML hace referencia a tus fragmentos, los fragmentos se refieren entre sí, tal vez para carga asíncrona y esas cosas. Y los fragmentos también hacen referencia a los activos, como imágenes, fuentes, esas cosas. Y ahí es donde entra el problema. Entonces, sí, básicamente resolvimos estas primeras cosas con Webpack en el estado actual con Next.js. Entonces, para hacer compilaciones deterministas, simplemente tenemos cuidado al implementar eso y tratamos de evitar partes absolutas, básicamente evitamos partes absolutas. Y para hacerlo independiente de estos cambios donde clonas tu repositorio en un directorio diferente y todas esas cosas. Y eso es bastante fácil, en realidad. Y el más difícil es esta propiedad de pequeño cambio de entrada, pequeño cambio de salida, donde tienes que considerar cada algoritmo para hacerlo realmente sin tener este efecto de toda la aplicación. Como los ID de módulo, realmente no podemos numerarlos uno por uno, tenemos que... Porque si los numeras uno por uno, insertar un módulo al principio renombraría todos los modules no a la propiedad que queremos. Entonces, haciendo uso de hashes para generar ID de módulos, y también para dividir tus modules en fragmentos, tienes que hacerlo determinista de tal manera que los pequeños cambios se conviertan en pequeños cambios de salida. También es relevante para las optimizaciones, como la ofuscación y esas cosas. En general, resolvimos algunas cosas, pero veamos este problema de los hashes de contenido.

QnA

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Construyendo el Generador de Código de Widgets de Figma
React Advanced Conference 2022React Advanced Conference 2022
19 min
Construyendo el Generador de Código de Widgets de Figma
This Talk introduces Figma's Widget Code Generator and demonstrates how to build a FigJam widget using it. The speaker discusses the implementation of voting functionality, avatar functionality, and remove vote functionality. They also explain how the Widget Code Generator plugin works and how to access properties and modify names using the Figma plugin API.
Comienza a Construir tus Propias Herramientas de JavaScript
JSNation 2023JSNation 2023
22 min
Comienza a Construir tus Propias Herramientas de JavaScript
[♪ music ♪ by The Illuminati plays)] I see a common thread across any project I work on. Different developers are making the same mistake and we have preferred ways of doing things. Preventing mistakes and sharing best practices are great reasons to look at tools like linters and in particular ESLint. Let's write our first rule together. We're just scratching the surface of building our own tools, which can have a massive impact on improving the developer experience.
Reglas avanzadas de linting con ESLint
TypeScript Congress 2023TypeScript Congress 2023
10 min
Reglas avanzadas de linting con ESLint
Tibor Blanesy from Sonar presents advanced techniques for linting with ESLint, including the use of ControlFlowGraph to detect errors in code. The algorithm is based on liveness analysis, which identifies live variables at any point in the program. Additionally, the talk covers the computation of block sets using the difference between outset and kill set unionized with genset.
Cómo no(!) construir aplicaciones en tiempo real
Node Congress 2024Node Congress 2024
10 min
Cómo no(!) construir aplicaciones en tiempo real
Today's Talk discusses different approaches for implementing real-time updates in server-side applications, including application-level updates and polling. The drawbacks of polling include inefficiency and complexity at scale. Adding extra infrastructure, like messaging systems, can ensure scalability but introduces operational overhead. Prisma Pulse is a system that simplifies change data capture, providing an easy setup for subscribing to database changes and solving scalability issues.
Construyendo una Pila de Red para nuestra Extensión de Navegador
Node Congress 2024Node Congress 2024
19 min
Construyendo una Pila de Red para nuestra Extensión de Navegador
The Talk discusses the development of the Jam browser extension, which is a bug reporting tool. It explores the challenges of messaging between different execution environments within a browser and the need for message chunking to overcome size constraints. The Talk also explains how the development team rebuilt the system using a TCP/IP network stack approach, which allowed them to solve messaging difficulties similar to networking problems. The benefits of this approach include a smoother rollout, simpler debugging, and a focus on feature development without worrying about messaging constraints.

Workshops on related topic

Construye aplicaciones similares a React para herramientas internas 10 veces más rápido con Retool
JSNation Live 2021JSNation Live 2021
86 min
Construye aplicaciones similares a React para herramientas internas 10 veces más rápido con Retool
Workshop
Chris Smith
Chris Smith
La mayoría de las empresas tienen que construir software personalizado e interfaces a medida para sus datos con el fin de impulsar procesos internos como extensiones de prueba de usuario, reembolsos, gestión de inventario, administración de usuarios, etc. Estas aplicaciones tienen requisitos únicos y a menudo, resolver el problema rápidamente es más importante que la apariencia. Retool facilita a los desarrolladores de JavaScript construir rápidamente aplicaciones similares a React para herramientas internas utilizando interfaces de API y base de datos preconstruidas, así como componentes de interfaz de usuario reutilizables. En este masterclass, repasaremos cómo algunas de las empresas de más rápido crecimiento están haciendo herramientas internas y construiremos algunas aplicaciones simples para explicar cómo Retool funciona a partir de tus conocimientos existentes de JavaScript y ReactJS para permitir la construcción rápida de herramientas.
Prerrequisitos:Una cuenta de prueba gratuita en Retool.comAlgunos conocimientos básicos de JavaScript y bases de datos SQL/NoSQL
Enlace útil de Retool: https://docs.retool.com/docs