00:00:00(música animada) - Bien, gracias a todos, hola.
00:00:07Mi nombre es Luke Sandberg.
00:00:09Soy ingeniero de software en Vercel,
00:00:10trabajando en Turbo Pack.
00:00:12Llevo unos seis meses en Vercel,
00:00:14lo que me ha dado tiempo suficiente para subir al escenario y hablarles de todo el gran trabajo que no hice.
00:00:23Antes de Vercel,
00:00:24estuve en Google,
00:00:25donde trabajé en nuestras cadenas de herramientas web internas e hice cosas raras como construir un compilador de TSX a bytecode de Java y trabajar en el compilador Closure.
00:00:37Así que cuando llegué a Vercel,
00:00:40fue como pisar otro planeta,
00:00:43todo era diferente.
00:00:45Y me sorprendieron bastante todas las cosas que hicimos en el equipo y los objetivos que teníamos.
00:00:50Hoy voy a compartir algunas de las decisiones de diseño que tomamos en Turbo Pack y cómo creo que nos permitirán seguir construyendo sobre el fantástico rendimiento que ya tenemos.
00:01:01Para motivar eso,
00:01:02este es nuestro objetivo de diseño general.
00:01:06De esto,
00:01:06pueden inferir inmediatamente que probablemente tomamos algunas decisiones difíciles.
00:01:14Entonces, ¿qué pasa con las compilaciones en frío?
00:01:17Son importantes,
00:01:18pero una de nuestras ideas es que no deberían experimentarlas en absoluto.
00:01:22Y en eso se va a centrar esta charla.
00:01:24En la presentación principal,
00:01:26escucharon un poco sobre cómo aprovechamos la incrementalidad para mejorar el rendimiento del empaquetado.
00:01:31Una idea clave que tenemos para la incrementalidad es el almacenamiento en caché.
00:01:35Queremos que cada cosa que haga el empaquetador sea cacheable,
00:01:38de modo que cada vez que hagan un cambio,
00:01:40solo tengamos que rehacer el trabajo relacionado con ese cambio.
00:01:43O,
00:01:43quizás,
00:01:44dicho de otra manera,
00:01:45el costo de su compilación debería escalar con el tamaño o la complejidad de su cambio,
00:01:50en lugar de con el tamaño o la complejidad de su aplicación.
00:01:53Y así es como podemos asegurarnos de que Turbo Pack seguirá ofreciendo a los desarrolladores un buen rendimiento,
00:01:59sin importar cuántas bibliotecas de iconos importen.
00:02:01Para ayudar a entender y motivar esa idea,
00:02:04imaginemos el empaquetador más simple del mundo,
00:02:07que quizás se vea así.
00:02:09Aquí está nuestro empaquetador
00:02:12Y esto quizás sea demasiado código para una diapositiva,
00:02:15pero va a empeorar.
00:02:17Aquí analizamos cada punto de entrada.
00:02:20Seguimos sus importaciones,
00:02:21resolvemos sus referencias,
00:02:23de forma recursiva en toda la aplicación para encontrar todo de lo que dependen.
00:02:28Luego,
00:02:28al final,
00:02:29simplemente recopilamos todo lo que depende de cada punto de entrada y lo colocamos en un archivo de salida.
00:02:35¡Así que, hurra, tenemos un empaquetador
00:02:38Obviamente esto es ingenuo,
00:02:40pero si lo pensamos desde una perspectiva incremental,
00:02:43ninguna parte de esto es incremental.
00:02:45Así que definitivamente analizaremos ciertos archivos varias veces,
00:02:49quizás dependiendo de cuántas veces los importen,
00:02:52eso es terrible.
00:02:53Definitivamente resolveremos la importación de React cientos o miles de veces.
00:02:57Así que, saben, ¡ay!
00:03:01Así que si queremos que esto sea al menos un poco más incremental,
00:03:04necesitamos encontrar una forma de evitar el trabajo redundante.
00:03:08Así que, añadamos una caché.
00:03:10Podrían imaginar que esta es nuestra función de análisis.
00:03:15Es bastante simple.
00:03:15Y probablemente sea el
00:03:19Saben, muy simple.
00:03:19Leemos el contenido del archivo,
00:03:22se lo pasamos a SWC para que nos dé un AST.
00:03:25Así que, añadamos una caché.
00:03:27Bien, esto es claramente una buena y simple victoria.
00:03:31Pero,
00:03:32saben,
00:03:32estoy seguro de que algunos de ustedes han escrito código de caché antes.
00:03:36Quizás haya algunos problemas aquí.
00:03:38Como, saben, ¿qué pasa si el archivo cambia?
00:03:41Esto es claramente algo que nos importa.
00:03:46Y,
00:03:46saben,
00:03:47¿qué pasa si el archivo no es realmente un archivo,
00:03:50sino tres enlaces simbólicos disfrazados?
00:03:52Muchos gestores de paquetes organizan las dependencias así.
00:03:55Y estamos usando el nombre del archivo como clave de caché.
00:03:59¿Es suficiente?
00:04:00Como,
00:04:00saben,
00:04:01estamos empaquetando para el cliente y el servidor.
00:04:03Los mismos archivos terminan en ambos.
00:04:04¿Funciona eso?
00:04:05También estamos almacenando el AST y devolviéndolo.
00:04:08Así que ahora tenemos que preocuparnos por las mutaciones.
00:04:11Entonces,
00:04:11saben,
00:04:12y finalmente,
00:04:13¿no es esta una forma realmente ingenua de analizar?
00:04:16Sé que todos tienen configuraciones masivas para el compilador.
00:04:21Como, algo de eso tiene que entrar aquí.
00:04:23Así que, sí, todo esto es una gran retroalimentación.
00:04:27Y este es un enfoque muy ingenuo.
00:04:32Y a eso, por supuesto, diría, sí, esto no funcionará.
00:04:36Entonces, ¿qué hacemos para solucionar estos problemas?
00:04:39Por favor, arréglenlo y no cometan errores.
00:04:44Así que, bien.
00:04:46Así que quizás esto sea un poco mejor.
00:04:49Saben, pueden ver aquí que tenemos algunas transformaciones.
00:04:52Necesitamos hacer cosas personalizadas para cada archivo,
00:04:55como quizás bajar de nivel o implementar el uso de caché.
00:04:58También tenemos alguna configuración.
00:05:00Y así,
00:05:01por supuesto,
00:05:01necesitamos incluir eso en nuestra clave para nuestra caché.
00:05:04Pero quizás de inmediato sospechen.
00:05:08Como, ¿es esto correcto?
00:05:09Como,
00:05:10¿es realmente suficiente identificar una transformación basándose en el nombre?
00:05:13No sé, quizás eso tenga su propia configuración complicada.
00:05:16Y,
00:05:17bien,
00:05:17y como,
00:05:18¿este valor JSON va a capturar realmente todo lo que nos importa?
00:05:24¿Lo mantendrán los desarrolladores?
00:05:26¿Qué tan grandes serán estas claves de caché?
00:05:29¿Cuántas copias de la configuración tendremos?
00:05:31Así que,
00:05:32personalmente he visto código exactamente así,
00:05:34y me resulta casi imposible de entender.
00:05:37Bien,
00:05:37también intentamos solucionar este otro problema relacionado con las invalidaciones.
00:05:43Así que añadimos una API de callback para leer archivos.
00:05:46Esto es genial,
00:05:47así que si el archivo cambia,
00:05:49podemos simplemente eliminarlo de la caché,
00:05:52para no seguir sirviendo contenido obsoleto.
00:05:55Bien,
00:05:55pero esto es bastante ingenuo,
00:05:56porque,
00:05:57claro,
00:05:57necesitamos eliminar nuestra caché,
00:05:59pero nuestro llamador también necesita saber que necesita obtener una nueva copia.
00:06:03Así que, bien, empecemos a encadenar callbacks.
00:06:06Bien, lo hicimos.
00:06:09Encadenamos callbacks a través de la pila.
00:06:12Pueden ver aquí que permitimos a nuestro llamador suscribirse a los cambios.
00:06:16Podemos simplemente volver a ejecutar todo el paquete si algo cambia,
00:06:20y si un archivo cambia,
00:06:21lo llamamos.
00:06:22Genial, tenemos un empaquetador reactivo.
00:06:25Pero esto sigue siendo apenas incremental.
00:06:28Así que si un archivo cambia,
00:06:30necesitamos recorrer todos los módulos de nuevo y producir todos los archivos de salida.
00:06:37Así que,
00:06:38saben,
00:06:38ahorramos mucho trabajo al tener nuestra caché de análisis,
00:06:43pero esto no es realmente suficiente.
00:06:45Y luego, finalmente, hay todo este otro trabajo redundante.
00:06:49Como, definitivamente queremos cachear las importaciones.
00:06:52Podríamos encontrar un archivo muchas veces,
00:06:54y seguimos necesitando sus importaciones,
00:06:55así que queremos poner una caché allí.
00:06:57Y,
00:06:58saben,
00:06:58los resultados de resolución son bastante complicados,
00:07:01así que definitivamente deberíamos cachear eso para poder reutilizar el trabajo que hicimos al resolver React.
00:07:08Pero, bien, ahora tenemos otro problema.
00:07:11Sus resultados de resolución cambian cuando actualizan dependencias o añaden nuevos archivos,
00:07:16así que necesitamos otro callback allí.
00:07:18Y definitivamente también queremos,
00:07:20como,
00:07:20cachear la lógica para producir salidas porque,
00:07:23si lo piensan en una sesión HMR,
00:07:25están editando una parte de la aplicación,
00:07:27entonces ¿por qué estamos reescribiendo todas las salidas cada vez?
00:07:31Y también,
00:07:32podrían,
00:07:32como,
00:07:33eliminar un archivo de salida,
00:07:35así que probablemente deberíamos escuchar los cambios allí también.
00:07:39Bien,
00:07:39quizás resolvimos todas esas cosas,
00:07:42pero todavía tenemos este problema,
00:07:44que es que cada vez que algo cambia,
00:07:46empezamos desde cero.
00:07:48Así que,
00:07:48el flujo de control completo de esta función no funciona porque si un solo archivo cambia,
00:07:53realmente querríamos saltar al medio de ese bucle for.
00:07:56Y luego,
00:07:57finalmente,
00:07:58nuestra API para nuestro llamador también es irremediablemente ingenua.
00:08:03Probablemente quieran saber qué archivo ha cambiado,
00:08:05para poder,
00:08:05como,
00:08:06enviar actualizaciones al cliente.
00:08:07Así que, sí.
00:08:11Así que, este enfoque no funciona realmente.
00:08:13E incluso si de alguna manera encadenáramos todos los callbacks en todos estos lugares,
00:08:19¿creen que podrían mantener este código?
00:08:21¿Creen que podrían, como, añadirle una nueva característica?
00:08:24Yo no.
00:08:25Creo que esto simplemente fracasaría estrepitosamente.
00:08:28Y, saben, a eso, diría, sí.
00:08:34Así que, una vez más, ¿qué deberíamos hacer?
00:08:36Saben,
00:08:36al igual que cuando chatean con un LLM,
00:08:40primero necesitan saber lo que quieren.
00:08:43Y luego tienen que ser extremadamente claros al respecto.
00:08:48Entonces, ¿qué queremos siquiera?
00:08:50Así que,
00:08:50saben,
00:08:51consideramos muchos enfoques diferentes,
00:08:53y muchas personas del equipo tenían mucha experiencia trabajando en empaquetadores.
00:08:59Así que, se nos ocurrieron estos requisitos más o menos.
00:09:02Así que,
00:09:02definitivamente queremos poder cachear cada operación costosa en el empaquetador.
00:09:05Y debería ser realmente fácil hacer esto.
00:09:08Como,
00:09:09no deberían recibir 15 comentarios en su revisión de código cada vez que añaden una nueva caché.
00:09:12Y luego,
00:09:13en realidad no confío en que los desarrolladores escriban claves de caché correctas o rastreen entradas o dependencias manualmente.
00:09:24Así que, deberíamos manejarlo nosotros.
00:09:26Definitivamente deberíamos hacer esto a prueba de errores.
00:09:30A continuación, necesitamos manejar las entradas cambiantes.
00:09:33Esta es una gran idea en HMR, pero incluso entre sesiones.
00:09:36Así que,
00:09:36principalmente serán archivos,
00:09:38pero también podrían ser cosas como configuraciones.
00:09:40Y con la caché del sistema de archivos,
00:09:42en realidad termina siendo cosas como variables de entorno también.
00:09:45Así que, queremos ser reactivos.
00:09:47Queremos poder recalcular las cosas tan pronto como algo cambie,
00:09:51y no queremos encadenar callbacks por todas partes.
00:09:54Finalmente,
00:09:55solo necesitamos aprovechar las arquitecturas modernas y ser multihilo y,
00:10:01en general,
00:10:02rápidos.
00:10:02Así que,
00:10:03quizás estén viendo este conjunto de requisitos,
00:10:06y algunos de ustedes estén pensando,
00:10:09¿qué tiene esto que ver con un empaquetador?
00:10:12Y a eso,
00:10:12diría,
00:10:13por supuesto,
00:10:14mi equipo de gestión está en la sala,
00:10:17así que no necesitamos hablar de eso.
00:10:20Pero en realidad,
00:10:21supongo que muchos de ustedes llegaron a la conclusión mucho más obvia.
00:10:24Esto suena mucho a señales.
00:10:28Y sí, estoy describiendo un sistema que suena a señales.
00:10:31Es una forma de componer cálculos,
00:10:33rastrear dependencias,
00:10:34con cierta cantidad de memoización automática.
00:10:37Y debo señalar que nos inspiramos en todo tipo de sistemas,
00:10:41especialmente en el compilador de Rust y en un sistema llamado Salsa.
00:10:45E incluso hay literatura académica sobre estos conceptos llamada Adaptons,
00:10:50si les interesa.
00:10:51Bien,
00:10:51echemos un vistazo a lo que,
00:10:53veamos cómo se ve esto en la práctica,
00:10:55y luego vamos a dar un salto muy brusco de ejemplos de código en JavaScript a Rust.
00:11:01Aquí tienen un ejemplo de la infraestructura que construimos.
00:11:05Una función TurboTask es una unidad de trabajo cacheada en nuestro compilador.
00:11:12Así que podemos,
00:11:13una vez que anotan una función así,
00:11:16podemos rastrearla,
00:11:17podemos construir una clave de caché a partir de sus parámetros,
00:11:21y eso nos permite tanto cachearla como volver a ejecutarla cuando lo necesitamos.
00:11:28Estos tipos VC aquí,
00:11:30pueden pensarlos como señales,
00:11:34este es un valor reactivo,
00:11:37VC significa
00:11:39Cuando declaran un parámetro así,
00:11:41están diciendo que esto podría cambiar,
00:11:44quiero volver a ejecutarlo cuando cambie.
00:11:47¿Y cómo sabemos eso?
00:11:49Así que leemos estos valores a través de un
00:11:52Una vez que esperan un valor reactivo como este,
00:11:55rastreamos automáticamente la dependencia.
00:11:58Y luego,
00:11:58finalmente,
00:11:59por supuesto,
00:12:00hacemos el cálculo real que queríamos hacer,
00:12:04y lo almacenamos en una celda.
00:12:07Así que,
00:12:07como hemos rastreado automáticamente las dependencias,
00:12:11sabemos que esta función depende tanto del contenido del archivo como del valor de la configuración.
00:12:17Y cada vez que almacenamos un nuevo resultado en la celda,
00:12:21podemos compararlo con el anterior,
00:12:23y luego,
00:12:23si ha cambiado,
00:12:24podemos propagar notificaciones a todos los que han leído ese valor.
00:12:29Así que este concepto de cambio es clave para nuestro enfoque de incrementalidad.
00:12:33Y sí, de nuevo, el caso más simple está aquí.
00:12:37Si el archivo cambia,
00:12:38Turbo Pack lo observará,
00:12:40invalidará la ejecución de esta función y la volverá a ejecutar inmediatamente.
00:12:45Y luego,
00:12:45si por casualidad producimos el mismo AST,
00:12:48nos detendremos allí mismo porque calculamos la misma celda.
00:12:53Ahora,
00:12:54para analizar un archivo,
00:12:55apenas hay ninguna edición que puedan hacer que no cambie realmente el AST.
00:13:00Pero podemos aprovechar la composabilidad fundamental de las funciones de Turbo Pack para llevar esto más lejos.
00:13:07Así que aquí,
00:13:09vemos otra función de caché de Turbo Pack extrayendo importaciones de un módulo.
00:13:15Pueden imaginar que esta es una tarea muy común que tenemos en el Empaquetador.
00:13:20Necesitamos extraer importaciones solo para encontrar realmente todos los módulos en su aplicación.
00:13:25Los aprovechamos para elegir la mejor manera de agrupar módulos en fragmentos.
00:13:29Y,
00:13:29por supuesto,
00:13:30el gráfico de importación es importante para tareas básicas como el
00:13:34Y como hay tantos consumidores diferentes de los datos de importaciones,
00:13:39una caché tiene mucho sentido.
00:13:41Así que esta implementación no es realmente especial.
00:13:44Esto es como lo que encontrarían en cualquier tipo de Empaquetador.
00:13:46Recorremos el AST,
00:13:47recopilamos importaciones en alguna estructura de datos especial que nos gusta,
00:13:53y luego las devolvemos.
00:13:55Pero la idea clave aquí es que los almacenamos en otra celda.
00:13:58Así que si el módulo cambia,
00:14:00sí necesitamos volver a ejecutar esta función porque lo leemos.
00:14:05Pero si piensan en el tipo de cambios que hacen a los módulos,
00:14:09muy pocos de ellos afectan realmente las importaciones.
00:14:12Así que cambian el módulo,
00:14:13actualizan el cuerpo de la función,
00:14:16un literal de cadena,
00:14:17cualquier tipo de detalle de implementación.
00:14:20Invalidará esta función y luego calcularemos el mismo conjunto de importaciones.
00:14:25Y luego no invalidamos nada que haya leído esto.
00:14:29Así que si piensan en esto en una sesión HMR,
00:14:31esto significa que sí necesitamos volver a analizar su archivo,
00:14:35pero realmente ya no necesitamos pensar en cómo tomar decisiones de fragmentación.
00:14:40No necesitamos pensar en ningún tipo de resultado de
00:14:45Así que podemos saltar inmediatamente de analizar el archivo,
00:14:48hacer este análisis simple,
00:14:50y luego saltar directamente a producir salidas.
00:14:53Y esta es una de las formas en que tenemos tiempos de actualización realmente rápidos.
00:14:57Así que esto es bastante imperativo.
00:15:02Otra forma de pensar en esta idea básica es como un gráfico de nodos.
00:15:06Así que aquí a la izquierda,
00:15:08podrían imaginar una compilación en frío.
00:15:12Inicialmente,
00:15:12sí tenemos que leer cada archivo,
00:15:14analizarlos todos,
00:15:15analizar todas las importaciones.
00:15:17Y como efecto secundario de eso,
00:15:18hemos recopilado toda la información de dependencia de su aplicación.
00:15:21Y luego,
00:15:22cuando algo cambia,
00:15:23podemos aprovechar ese gráfico de dependencias que construimos para propagar invalidaciones,
00:15:28volver a la pila y volver a ejecutar las funciones de Turbo Pack.
00:15:32Y así, si producen un nuevo valor, nos detenemos allí.
00:15:35De lo contrario, seguimos propagando la invalidación.
00:15:37Así que, genial.
00:15:41Saben,
00:15:41esto es en realidad una especie de sobresimplificación masiva de lo que estamos haciendo en la práctica,
00:15:46podrían imaginar.
00:15:47Así que en Turbo Pack hoy,
00:15:49hay alrededor de 2.500 funciones Turbo task diferentes.
00:15:53Y en una compilación típica,
00:15:54podríamos tener literalmente millones de tareas diferentes.
00:15:58Así que realmente se ve quizás un poco más así.
00:16:01Ahora, realmente no espero que puedan leer esto.
00:16:04No pude realmente meterlo en la diapositiva.
00:16:06Así que quizás deberíamos alejar el zoom.
00:16:08Bien, eso obviamente no es útil.
00:16:14En realidad,
00:16:15sí tenemos mejores formas de,
00:16:16digamos,
00:16:17rastrear y visualizar lo que está sucediendo dentro de Turbo Pack.
00:16:21Pero fundamentalmente,
00:16:22eso funciona descartando la gran mayoría de la información de dependencia.
00:16:26Y ahora supongo que algunos de ustedes quizás realmente tienen experiencia trabajando con señales,
00:16:32quizás malas experiencias.
00:16:34Saben,
00:16:35a mí,
00:16:35por ejemplo,
00:16:36me gustan los rastreos de pila y poder entrar y salir de funciones en un depurador.
00:16:41Así que quizás sospechen que esta es la panacea completa.
00:16:45Como que obviamente viene con compensaciones.
00:16:47Y sí,
00:16:48y a eso,
00:16:49por supuesto,
00:16:50diría,
00:16:50bueno,
00:16:51saben,
00:16:52lo que realmente diría es que toda la ingeniería de software se trata de gestionar compensaciones.
00:17:01No siempre estamos resolviendo problemas exactamente,
00:17:04pero realmente estamos eligiendo nuevos conjuntos de compensaciones para entregar valor.
00:17:08Así que para lograr nuestros objetivos de diseño en torno a las compilaciones incrementales en Turbo Pack,
00:17:14apostamos,
00:17:14por así decirlo,
00:17:15todas nuestras fichas en este modelo de programación reactiva incremental.
00:17:19Y esto,
00:17:19por supuesto,
00:17:20tuvo algunas consecuencias muy naturales.
00:17:23Así que,
00:17:24saben,
00:17:24quizás realmente sí resolvimos el problema de los sistemas de caché hechos a mano y la lógica de invalidación engorrosa.
00:17:33A cambio,
00:17:34tenemos que gestionar una infraestructura de caché complicada.
00:17:39Y por supuesto,
00:17:40saben,
00:17:40eso me parece una muy buena compensación.
00:17:42Me gusta la infraestructura de caché complicada,
00:17:45pero todos tenemos que vivir con las consecuencias.
00:17:48Así que lo primero,
00:17:49por supuesto,
00:17:50son solo los gastos generales centrales de este sistema.
00:17:54Saben,
00:17:55si lo piensan en una compilación o sesión HMR dada,
00:18:01no están cambiando mucho.
00:18:04Así que rastreamos toda la información de dependencia entre,
00:18:07digamos,
00:18:07cada importación y cada resultado de resolución en su aplicación,
00:18:11pero en realidad solo van a cambiar unos pocos.
00:18:13Así que la mayor parte de la información de dependencia que recopilamos nunca es realmente necesaria.
00:18:16Así que,
00:18:17saben,
00:18:17para gestionar esto,
00:18:19hemos tenido que centrarnos mucho en impulsar,
00:18:21en mejorar el rendimiento de esta capa de caché para reducir los gastos generales y permitir que nuestro sistema escale a aplicaciones cada vez más grandes.
00:18:30Y lo siguiente y más obvio es simplemente la memoria.
00:18:34Saben,
00:18:35las cachés son siempre fundamentalmente una compensación entre tiempo y memoria.
00:18:38Y la nuestra no hace nada realmente diferente allí.
00:18:41Nuestro objetivo simple es que el tamaño de la caché debería escalar linealmente con el tamaño de su aplicación.
00:18:49Pero de nuevo,
00:18:49tenemos que tener cuidado con los gastos generales.
00:18:51Este siguiente es un poco sutil.
00:18:54Así que tenemos muchos algoritmos en el empaquetador,
00:18:57como podrían esperar.
00:18:58Y algunos de ellos,
00:18:59digamos,
00:19:00requieren entender algo global sobre su aplicación.
00:19:03Bueno,
00:19:03eso es un problema porque cada vez que dependen de información global,
00:19:07eso significa que cualquier cambio podría invalidar esa operación.
00:19:10Así que tenemos que tener cuidado con cómo diseñamos estos algoritmos,
00:19:14componer las cosas con cuidado para que podamos preservar la incrementalidad.
00:19:17Y finalmente, este es quizás un poco de una queja personal.
00:19:24Todo es asíncrono en Turbo Pack.
00:19:27Y esto es genial para la escalabilidad horizontal,
00:19:29pero una vez más,
00:19:30daña nuestros objetivos fundamentales de,
00:19:31saben,
00:19:32depuración y perfilado de rendimiento.
00:19:38Así que estoy seguro de que muchos de ustedes tienen experiencia depurando asincronía en,
00:19:43digamos,
00:19:43las herramientas de desarrollo de Chrome.
00:19:46Y esta es generalmente una experiencia bastante agradable.
00:19:48No siempre ideal.
00:19:49Y les aseguro que Rust con LLDB está a años luz de distancia.
00:19:53Así que para gestionar eso,
00:19:55hemos tenido que invertir en herramientas personalizadas de visualización,
00:19:59instrumentación y trazado.
00:20:01Y miren eso,
00:20:02como otro proyecto de infraestructura que no es un empaquetador.
00:20:07Bien,
00:20:07echemos un vistazo y veamos si hicimos la apuesta correcta.
00:20:11Así que en Vercel,
00:20:12tenemos una aplicación de producción muy grande.
00:20:17Creemos que quizás es una de las más grandes del mundo,
00:20:19pero,
00:20:20saben,
00:20:20realmente no lo sabemos.
00:20:21Pero sí tiene alrededor de 80.000 módulos.
00:20:23Así que echemos un vistazo a cómo le va a Turbo Pack con ella.
00:20:26Para la actualización rápida,
00:20:28realmente dominamos lo que Web Pack es capaz de ofrecer.
00:20:32Pero esto es, digamos, una noticia vieja.
00:20:33Turbo Pack para desarrollo ha estado disponible por un tiempo,
00:20:36y realmente espero que todos lo estén usando al menos en desarrollo.
00:20:39Pero,
00:20:39saben,
00:20:40lo nuevo aquí hoy,
00:20:40por supuesto,
00:20:41es que las compilaciones son estables.
00:20:42Así que veamos una compilación.
00:20:44Y aquí pueden ver una victoria sustancial sobre Web Pack para esta aplicación.
00:20:49Esta compilación en particular en realidad se está ejecutando con nuestra nueva capa experimental de caché del sistema de archivos.
00:20:53Así que unos 16 de esos 94 segundos son solo vaciar la caché al final.
00:20:59Y esto es algo en lo que vamos a trabajar para mejorar a medida que el almacenamiento en caché del sistema de archivos se vuelva estable.
00:21:04Pero,
00:21:04por supuesto,
00:21:05lo de las compilaciones en frío es que son frías,
00:21:07nada es incremental.
00:21:07Así que echemos un vistazo a una compilación
00:21:10Así que usando la caché de la compilación en frío,
00:21:13podemos ver esto.
00:21:14Así que esto es solo un vistazo a dónde estamos hoy.
00:21:17Como tenemos este sistema de caché de grano fino,
00:21:19en realidad podemos simplemente escribir la caché en el disco,
00:21:22y luego en la siguiente compilación,
00:21:23leerla de nuevo,
00:21:24averiguar qué cambió y terminar la compilación.
00:21:26Bien,
00:21:27esto se ve bastante bien,
00:21:28pero muchos de ustedes están pensando,
00:21:30bueno,
00:21:30quizás yo personalmente no tengo la aplicación Next.js más grande del mundo.
00:21:34Así que echemos un vistazo a un ejemplo más pequeño.
00:21:37El sitio web react.dev es bastante más pequeño.
00:21:41También es,
00:21:41digamos,
00:21:42interesante porque es un compilador de React.
00:21:44No es sorprendente que sea un adoptador temprano del compilador de React.
00:21:47Y el compilador de React está implementado en Babel.
00:21:49Y esto es,
00:21:50digamos,
00:21:50un problema para nuestro enfoque porque significa que para cada archivo en la aplicación,
00:21:54necesitamos pedirle a Babel que lo procese.
00:21:55Así que,
00:21:55y fundamentalmente,
00:21:56diría que nosotros,
00:21:57o yo,
00:21:58no puedo hacer que el compilador de React sea más rápido.
00:22:01No es mi trabajo.
00:22:02Mi trabajo es Turbo Pack.
00:22:03Pero podemos averiguar exactamente cuándo llamarlo.
00:22:07Así que,
00:22:08mirando los tiempos de actualización rápida,
00:22:10en realidad me decepcionó un poco este resultado.
00:22:13Y resulta que unos 130 de esos 140 milisegundos son del compilador de React.
00:22:18Y tanto Turbo Pack como Web Pack están haciendo eso.
00:22:22Pero con Turbo Pack,
00:22:23podemos,
00:22:23después de que el compilador de React haya procesado este cambio,
00:22:27ver,
00:22:27oh,
00:22:28las importaciones no cambiaron.
00:22:29Lo metemos en la salida y seguimos.
00:22:31Una vez más,
00:22:32en las compilaciones en frío,
00:22:34vemos este tipo de victoria consistente de 3x.
00:22:37Y solo para ser claros, esto es en mi máquina.
00:22:39Pero de nuevo,
00:22:40no hay incrementalidad en una compilación en frío.
00:22:44Y en una compilación
00:22:47Así que de nuevo, con una compilación
00:22:52Todo lo que necesitamos hacer es básicamente,
00:22:54una vez que empezamos,
00:22:55averiguar qué archivos en la aplicación cambian,
00:22:57volver a ejecutar esos trabajos y luego reutilizar todo lo demás de la compilación anterior.
00:23:01Así que la pregunta básica es, ¿ya somos Turbo?
00:23:05Sí.
00:23:06Así que sí,
00:23:06esto se discutió en la presentación principal,
00:23:08por supuesto.
00:23:09Turbo Pack es estable a partir de la versión 16 de Next.
00:23:12E incluso somos el empaquetador predeterminado para Next.
00:23:14Así que, saben, misión cumplida, de nada.
00:23:17Pero. (risas) (aplausos del público)
00:23:23Y si notaron esa cosa de
00:23:30Solo tomó tres intentos.
00:23:31Pero lo que realmente quiero que se lleven,
00:23:34de nuevo,
00:23:35es esto.
00:23:35Saben, porque no hemos terminado.
00:23:37Todavía tenemos mucho que hacer en rendimiento,
00:23:39y dar el toque final a la capa de caché del sistema de archivos.
00:23:42Les sugiero a todos que lo prueben en desarrollo.
00:23:44Y eso es todo.
00:23:46Muchas gracias.
00:23:47Por favor, encuéntrenme, háganme preguntas.
00:23:49(aplausos del público) (música animada) (música animada)