00:00:00(musique entraînante) Bonjour à tous, merci.
00:00:07Je m'appelle Luke Sandberg.
00:00:09Je suis ingénieur logiciel chez Vercel,
00:00:10et je travaille sur Turbo Pack.
00:00:12Je suis chez Vercel depuis environ six mois,
00:00:15ce qui m'a donné juste assez de temps pour monter sur scène et vous parler de l'excellent travail que je n'ai pas fait.
00:00:23Avant Vercel,
00:00:24j'étais chez Google,
00:00:25où j'ai eu l'occasion de travailler sur nos chaînes d'outils web internes et de faire des choses étranges,
00:00:31comme créer un compilateur TSX vers bytecode Java et travailler sur le compilateur Closure.
00:00:37Alors,
00:00:37quand je suis arrivé chez Vercel,
00:00:40c'était un peu comme atterrir sur une autre planète,
00:00:43tout était différent.
00:00:45J'ai été assez surpris par tout ce que nous faisions dans l'équipe et par nos objectifs.
00:00:50Aujourd'hui,
00:00:51je vais partager quelques-uns des choix de conception que nous avons faits pour Turbo Pack et comment,
00:00:56selon moi,
00:00:56ils nous permettront de continuer à bâtir sur les performances fantastiques que nous avons déjà.
00:01:01Pour vous donner une idée,
00:01:02voici notre objectif de conception global.
00:01:06De là,
00:01:06vous pouvez immédiatement en déduire que nous avons probablement fait des choix difficiles.
00:01:14Alors, qu'en est-il des builds à froid ?
00:01:17Ils sont importants,
00:01:18mais l'une de nos idées est que vous ne devriez pas en rencontrer du tout.
00:01:22Et c'est ce sur quoi cette présentation va se concentrer.
00:01:24Lors de la keynote,
00:01:25vous avez entendu parler de la façon dont nous tirons parti de l'incrémentalité pour améliorer les performances de bundling.
00:01:31Une idée clé que nous avons pour l'incrémentalité concerne la mise en cache.
00:01:35Nous voulons que chaque action du bundler soit cachable,
00:01:38de sorte que chaque fois que vous faites une modification,
00:01:40nous n'ayons à refaire que le travail lié à ce changement.
00:01:43Ou peut-être,
00:01:44pour le dire autrement,
00:01:45le coût de votre build devrait vraiment évoluer avec la taille ou la complexité de votre modification plutôt qu'avec la taille ou la complexité de votre application.
00:01:53Et c'est ainsi que nous pouvons nous assurer que Turbo Pack continuera à offrir de bonnes performances aux développeurs,
00:01:58quel que soit le nombre de bibliothèques d'icônes que vous importez.
00:02:01Pour aider à comprendre et à motiver cette idée,
00:02:04imaginons le bundler le plus simple du monde,
00:02:07qui pourrait ressembler à ceci.
00:02:09Voici notre petit bundler.
00:02:12Et c'est peut-être un peu trop de code à mettre sur une diapositive,
00:02:16mais ça va empirer.
00:02:17Ici, nous analysons chaque point d'entrée.
00:02:20Nous suivons leurs importations,
00:02:21résolvons leurs références,
00:02:23de manière récursive dans toute l'application pour trouver tout ce dont vous dépendez.
00:02:28Ensuite,
00:02:28à la fin,
00:02:29nous collectons simplement tout ce dont chaque point d'entrée dépend et le plaçons dans un fichier de sortie.
00:02:35Hourra, nous avons un petit bundler.
00:02:38C'est évidemment naïf,
00:02:39mais si nous l'examinons d'un point de vue incrémental,
00:02:43aucune partie de cela n'est incrémentale.
00:02:45Nous allons certainement analyser certains fichiers plusieurs fois,
00:02:49peut-être selon le nombre d'importations,
00:02:52ce qui est terrible.
00:02:53Nous allons certainement résoudre l'importation de React des centaines,
00:02:56voire des milliers de fois.
00:02:57Alors, aïe.
00:03:01Donc,
00:03:01si nous voulons que cela soit au moins un peu plus incrémental,
00:03:05nous devons trouver un moyen d'éviter le travail redondant.
00:03:08Alors, ajoutons un cache.
00:03:10Vous pouvez imaginer que c'est notre fonction d'analyse.
00:03:15C'est assez simple.
00:03:15Et c'est probablement un peu le cheval de bataille de notre bundler.
00:03:19Très simple.
00:03:19Nous lisons le contenu du fichier,
00:03:22le transmettons à SWC pour obtenir un AST.
00:03:25Alors, ajoutons un cache.
00:03:27D'accord, c'est clairement une belle victoire simple.
00:03:31Mais,
00:03:32vous savez,
00:03:32je suis sûr que certains d'entre vous ont déjà écrit du code de mise en cache.
00:03:36Peut-être qu'il y a des problèmes ici.
00:03:38Par exemple, que se passe-t-il si le fichier change ?
00:03:41C'est clairement quelque chose qui nous tient à cœur.
00:03:46Et,
00:03:46vous savez,
00:03:47que se passe-t-il si le fichier n'est pas vraiment un fichier,
00:03:50mais trois liens symboliques dans un imperméable ?
00:03:52Beaucoup de gestionnaires de paquets organisent les dépendances de cette façon.
00:03:55Et nous utilisons le nom du fichier comme clé de cache.
00:03:59Est-ce suffisant ?
00:04:00Par exemple,
00:04:01nous faisons du bundling pour le client et le serveur.
00:04:03Les mêmes fichiers se retrouvent dans les deux.
00:04:04Cela fonctionne-t-il ?
00:04:05Nous stockons également l'AST et le retournons.
00:04:08Nous devons donc nous soucier des mutations.
00:04:11Alors,
00:04:11vous savez,
00:04:12et enfin,
00:04:13n'est-ce pas une façon vraiment naïve d'analyser ?
00:04:16Je sais que tout le monde a des configurations massives pour le compilateur.
00:04:21Une partie de cela doit être incluse ici.
00:04:23Oui, ce sont tous d'excellents retours.
00:04:27Et c'est une approche très naïve.
00:04:32Et à cela,
00:04:33bien sûr,
00:04:33je dirais,
00:04:34oui,
00:04:34cela ne fonctionnera pas.
00:04:36Alors, que faisons-nous pour résoudre ces problèmes ?
00:04:39Corrigez, et sans faire d'erreurs.
00:04:44Alors, d'accord.
00:04:46Alors, c'est peut-être un peu mieux.
00:04:49Vous savez,
00:04:49vous pouvez voir ici que nous avons des transformations.
00:04:52Nous devons appliquer des traitements personnalisés à chaque fichier,
00:04:55comme la rétrogradation ou l'implémentation de l'utilisation du cache.
00:04:58Nous avons aussi de la configuration.
00:05:00Et donc,
00:05:01bien sûr,
00:05:01nous devons l'inclure dans notre clé pour notre cache.
00:05:04Mais peut-être que tout de suite vous êtes méfiant.
00:05:08Par exemple, est-ce correct ?
00:05:09Par exemple,
00:05:10est-ce vraiment suffisant d'identifier une transformation basée sur le nom ?
00:05:13Je ne sais pas,
00:05:13peut-être que cela a sa propre configuration compliquée.
00:05:16Et,
00:05:17d'accord,
00:05:18cette valeur JSON va-t-elle vraiment capturer tout ce qui nous importe ?
00:05:24Les développeurs vont-ils le maintenir ?
00:05:26Quelle sera la taille de ces clés de cache ?
00:05:29Combien de copies de la configuration aurons-nous ?
00:05:31J'ai personnellement vu du code exactement comme ça,
00:05:34et je trouve qu'il est presque impossible de le comprendre.
00:05:37D'accord,
00:05:37nous avons aussi essayé de résoudre cet autre problème concernant les invalidations.
00:05:43Nous avons donc ajouté une API de rappel pour lire les fichiers.
00:05:46C'est génial,
00:05:47donc si le fichier change,
00:05:48nous pouvons simplement le supprimer du cache,
00:05:51afin de ne pas continuer à servir du contenu obsolète.
00:05:55D'accord,
00:05:55mais c'est en fait assez naïf,
00:05:57car,
00:05:57bien sûr,
00:05:58nous devons vider notre cache,
00:05:59mais notre appelant doit aussi savoir qu'il doit obtenir une nouvelle copie.
00:06:03Alors, d'accord, commençons à propager les rappels.
00:06:06D'accord, nous l'avons fait.
00:06:09Nous avons propagé les rappels à travers la pile.
00:06:12Vous pouvez voir ici que nous permettons à notre appelant de s'abonner aux changements.
00:06:16Nous pouvons simplement relancer l'ensemble du bundle si quelque chose change,
00:06:20et si un fichier change,
00:06:21nous l'appelons.
00:06:22Super, nous avons un bundler réactif.
00:06:25Mais ce n'est toujours guère incrémental.
00:06:28Donc,
00:06:29si un fichier change,
00:06:30nous devons parcourir tous les modules à nouveau et produire tous les fichiers de sortie.
00:06:37Alors,
00:06:38vous savez,
00:06:38nous avons économisé beaucoup de travail grâce à notre cache d'analyse,
00:06:43mais ce n'est pas vraiment suffisant.
00:06:45Et puis finalement, il y a tout ce travail redondant.
00:06:49Par exemple,
00:06:49nous voulons absolument mettre en cache les importations.
00:06:52Nous pourrions trouver un fichier plusieurs fois,
00:06:54et nous avons constamment besoin de ses importations,
00:06:56donc nous voulons y mettre un cache.
00:06:57Et,
00:06:58vous savez,
00:06:58les résultats de résolution sont en fait assez compliqués,
00:07:01nous devrions donc absolument les mettre en cache afin de pouvoir réutiliser le travail que nous avons fait pour résoudre React.
00:07:08Mais, d'accord, maintenant nous avons un autre problème.
00:07:11Vos résultats de résolution changent lorsque vous mettez à jour les dépendances ou ajoutez de nouveaux fichiers,
00:07:16nous avons donc besoin d'un autre rappel là-bas.
00:07:18Et nous voulons aussi absolument,
00:07:19par exemple,
00:07:20mettre en cache la logique de production des sorties,
00:07:23car si vous y pensez lors d'une session HMR,
00:07:25vous modifiez une partie de l'application,
00:07:27alors pourquoi réécrivons-nous toutes les sorties à chaque fois ?
00:07:31Et aussi,
00:07:32vous pourriez,
00:07:32par exemple,
00:07:33supprimer un fichier de sortie,
00:07:35nous devrions donc probablement écouter les changements là aussi.
00:07:39D'accord,
00:07:39nous avons peut-être résolu toutes ces choses,
00:07:42mais nous avons toujours ce problème,
00:07:44c'est-à-dire que chaque fois que quelque chose change,
00:07:46nous repartons de zéro.
00:07:48Donc,
00:07:48en quelque sorte,
00:07:49tout le flux de contrôle de cette fonction ne fonctionne pas parce que si un seul fichier change,
00:07:54nous voudrions vraiment sauter au milieu de cette boucle for.
00:07:56Et puis,
00:07:57enfin,
00:07:58notre API à notre appelant est aussi désespérément naïve.
00:08:03Ils veulent probablement savoir quel fichier a changé,
00:08:05afin de pouvoir,
00:08:05par exemple,
00:08:06pousser les mises à jour vers le client.
00:08:07Alors, oui.
00:08:11Donc, cette approche ne fonctionne pas vraiment.
00:08:13Et même si nous réussissions d'une manière ou d'une autre à propager tous les rappels à tous ces endroits,
00:08:18pensez-vous que vous pourriez réellement maintenir ce code ?
00:08:21Pensez-vous que vous pourriez,
00:08:22par exemple,
00:08:23y ajouter une nouvelle fonctionnalité ?
00:08:24Moi non.
00:08:25Je pense que cela échouerait lamentablement.
00:08:28Et, vous savez, à cela, je dirais, oui.
00:08:34Alors, encore une fois, que devrions-nous faire ?
00:08:36Vous savez,
00:08:37tout comme lorsque vous discutez avec un LLM,
00:08:40vous devez d'abord savoir ce que vous voulez.
00:08:43Et ensuite, vous devez être extrêmement clair à ce sujet.
00:08:48Alors, que voulons-nous vraiment ?
00:08:50Alors,
00:08:50vous savez,
00:08:51nous avons envisagé de nombreuses approches différentes,
00:08:54et de nombreuses personnes de l'équipe avaient en fait beaucoup d'expérience dans le travail sur les bundlers.
00:08:59Nous avons donc élaboré ces sortes d'exigences générales.
00:09:02Nous voulons absolument pouvoir mettre en cache chaque opération coûteuse dans le bundler.
00:09:05Et cela devrait être très facile à faire.
00:09:08Par exemple,
00:09:09vous ne devriez pas recevoir 15 commentaires sur votre revue de code chaque fois que vous ajoutez un nouveau cache.
00:09:12Et puis,
00:09:13je ne fais pas vraiment confiance aux développeurs pour écrire des clés de cache correctes ou suivre les entrées ou les dépendances à la main.
00:09:24Donc, nous devrions nous en occuper.
00:09:26Nous devrions absolument rendre cela infaillible.
00:09:30Ensuite, nous devons gérer les entrées changeantes.
00:09:33C'est une grande idée dans HMR,
00:09:34mais même entre les sessions.
00:09:36Donc,
00:09:36il s'agira principalement de fichiers,
00:09:38mais cela pourrait aussi être des choses comme les paramètres de configuration.
00:09:40Et avec le cache du système de fichiers,
00:09:42cela finit par être aussi des choses comme les variables d'environnement.
00:09:45Donc, nous voulons être réactifs.
00:09:47Nous voulons pouvoir recalculer les choses dès que quelque chose change,
00:09:51et nous ne voulons pas propager des rappels partout.
00:09:54Enfin,
00:09:55nous devons simplement tirer parti des architectures modernes,
00:09:59être multithreadé et généralement rapide.
00:10:02Alors,
00:10:03peut-être que vous regardez cet ensemble d'exigences,
00:10:06et certains d'entre vous se disent,
00:10:09qu'est-ce que cela a à voir avec un bundler ?
00:10:12Et à cela,
00:10:12je dirais,
00:10:13bien sûr,
00:10:14mon équipe de direction est dans la salle,
00:10:16donc nous n'avons pas vraiment besoin d'en parler.
00:10:20Mais en réalité,
00:10:21je suppose que beaucoup d'entre vous ont sauté à la conclusion beaucoup plus évidente.
00:10:24Cela ressemble beaucoup à des signaux.
00:10:28Et oui, je décris un système qui ressemble à des signaux.
00:10:31C'est une façon de composer des calculs,
00:10:33de suivre les dépendances,
00:10:34avec une certaine quantité de mémoïsation automatique.
00:10:37Et je dois noter que nous nous sommes inspirés de toutes sortes de systèmes,
00:10:42en particulier du compilateur Rust et d'un système appelé Salsa.
00:10:45Et il existe même une littérature académique sur ces concepts appelés Adaptons,
00:10:50si cela vous intéresse.
00:10:51D'accord,
00:10:51alors jetons un coup d'œil à ce que,
00:10:53voyons à quoi cela ressemble en pratique,
00:10:55et ensuite nous allons faire un saut très brutal des exemples de code en JavaScript vers Rust.
00:11:01Voici donc un exemple de l'infrastructure que nous avons construite.
00:11:05Une fonction TurboTask est une unité de travail mise en cache dans notre compilateur.
00:11:12Ainsi,
00:11:13une fois que vous annotez une fonction comme celle-ci,
00:11:16nous pouvons la suivre,
00:11:17nous pouvons construire une clé de cache à partir de ses paramètres,
00:11:21et cela nous permet à la fois de la mettre en cache et de la réexécuter lorsque nous en avons besoin.
00:11:28Ces types VC ici,
00:11:29vous pouvez les considérer comme des signaux,
00:11:32c'est une valeur réactive,
00:11:34VC signifie 'value cell',
00:11:35mais 'signal' pourrait être un nom un peu meilleur.
00:11:39Lorsque vous déclarez un paramètre comme celui-ci,
00:11:42vous dites que cela pourrait changer,
00:11:45je veux réexécuter quand cela change.
00:11:47Et comment le savons-nous ?
00:11:49Nous lisons donc ces valeurs via un 'await'.
00:11:52Une fois que vous attendez une valeur réactive comme celle-ci,
00:11:55nous suivons automatiquement la dépendance.
00:11:58Et puis finalement,
00:11:59bien sûr,
00:12:00nous effectuons le calcul que nous voulions faire,
00:12:04et nous le stockons dans une cellule.
00:12:07Ainsi,
00:12:07parce que nous avons automatiquement suivi les dépendances,
00:12:11nous savons que cette fonction dépend à la fois du contenu du fichier et de la valeur de la configuration.
00:12:17Et chaque fois que nous stockons un nouveau résultat dans la cellule,
00:12:21nous pouvons le comparer avec le précédent,
00:12:23et si cela a changé,
00:12:24nous pouvons propager des notifications à tous ceux qui ont lu cette valeur.
00:12:29Ce concept de changement est donc essentiel à notre approche de l'incrémentalité.
00:12:33Et oui, encore une fois, le cas le plus simple est ici.
00:12:37Si le fichier change,
00:12:38Turbo Pack l'observera,
00:12:40invalidera l'exécution de cette fonction et la réexécutera immédiatement.
00:12:45Et si nous produisons le même AST,
00:12:47nous nous arrêterons là parce que nous calculons la même cellule.
00:12:53Maintenant,
00:12:54pour l'analyse d'un fichier,
00:12:55il n'y a pratiquement aucune modification que vous puissiez y apporter qui ne change pas réellement l'AST.
00:13:00Mais nous pouvons tirer parti de la composabilité fondamentale des fonctions Turbo Pack pour aller plus loin.
00:13:07Ici,
00:13:08nous voyons une autre fonction de cache Turbo Pack extrayant les importations d'un module.
00:13:15Vous pouvez imaginer que c'est une tâche très courante que nous avons dans le Bundler.
00:13:20Nous devons extraire les importations juste pour trouver tous les modules de votre application.
00:13:25Nous les utilisons pour choisir la meilleure façon de regrouper les modules en chunks.
00:13:29Et bien sûr,
00:13:29le graphe d'importation est important pour des tâches de base comme le tree shaking.
00:13:34Et comme il y a tellement de consommateurs différents des données d'importation,
00:13:39un cache a beaucoup de sens.
00:13:41Donc, cette implémentation n'est pas vraiment spéciale.
00:13:44C'est ce que vous trouveriez dans n'importe quel type de Bundler.
00:13:46Nous parcourons l'AST,
00:13:47collectons les importations dans une structure de données spéciale que nous aimons,
00:13:53puis nous les retournons.
00:13:55Mais l'idée clé ici est que nous les stockons dans une autre cellule.
00:13:58Donc,
00:13:58si le module change,
00:14:00nous devons relancer cette fonction parce que nous l'avons lue.
00:14:05Mais si vous pensez au type de modifications que vous apportez aux modules,
00:14:09très peu d'entre elles affectent réellement les importations.
00:14:12Donc vous changez le module,
00:14:14vous mettez à jour le corps de la fonction,
00:14:16un littéral de chaîne,
00:14:18tout type de détail d'implémentation.
00:14:20Cela invalidera cette fonction et ensuite nous calculerons le même ensemble d'importations.
00:14:25Et ensuite, nous n'invalidons rien qui a lu cela.
00:14:29Donc,
00:14:29si vous y pensez dans une session HMR,
00:14:31cela signifie que nous devons reparser votre fichier,
00:14:34mais nous n'avons vraiment plus besoin de réfléchir à la façon de prendre des décisions de découpage en chunks.
00:14:40Nous n'avons pas besoin de penser à aucun type de résultats de tree shaking parce que nous savons qu'ils n'ont pas changé.
00:14:45Nous pouvons donc passer immédiatement de l'analyse du fichier,
00:14:49à cette simple analyse,
00:14:50puis directement à la production des sorties.
00:14:53Et c'est l'une des façons dont nous obtenons des temps de rafraîchissement très rapides.
00:14:57C'est donc assez impératif.
00:15:02Une autre façon de penser à cette idée de base est comme un graphe de nœuds.
00:15:06Ici, à gauche, vous pourriez imaginer un build à froid.
00:15:12Initialement,
00:15:12nous devons en fait lire chaque fichier,
00:15:14les analyser tous,
00:15:15analyser toutes les importations.
00:15:17Et comme effet secondaire de cela,
00:15:18nous avons collecté toutes les informations de dépendance de votre application.
00:15:21Et puis quand quelque chose change,
00:15:23nous pouvons tirer parti de ce graphe de dépendances que nous avons construit pour propager les invalidations,
00:15:29remonter la pile et réexécuter les fonctions Turbo Pack.
00:15:32Et donc s'ils produisent une nouvelle valeur,
00:15:34nous nous arrêtons là.
00:15:35Sinon, nous continuons à propager l'invalidation.
00:15:37C'est super.
00:15:41Vous savez,
00:15:41c'est en fait une simplification massive de ce que nous faisons en pratique,
00:15:46vous pouvez l'imaginer.
00:15:47Donc,
00:15:48dans Turbo Pack aujourd'hui,
00:15:49il y a environ 2 500 fonctions Turbo task différentes.
00:15:53Et dans un build typique,
00:15:54nous pourrions avoir littéralement des millions de tâches différentes.
00:15:58Donc, cela ressemble peut-être un peu plus à ceci.
00:16:01Maintenant,
00:16:02je ne m'attends pas vraiment à ce que vous puissiez lire ceci.
00:16:04Je n'ai pas vraiment pu le faire tenir sur la diapositive.
00:16:06Alors, peut-être devrions-nous dézoomer.
00:16:08D'accord, ce n'est évidemment pas utile.
00:16:14En réalité,
00:16:15nous avons de meilleures façons de suivre et de visualiser ce qui se passe à l'intérieur de Turbo Pack.
00:16:21Mais fondamentalement,
00:16:22cela fonctionne en éliminant la grande majorité des informations de dépendance.
00:16:26Et maintenant,
00:16:27je suppose que certains d'entre vous ont peut-être déjà travaillé avec des signaux,
00:16:32peut-être de mauvaises expériences.
00:16:34Vous savez,
00:16:35moi,
00:16:35j'aime les traces de pile et pouvoir entrer et sortir des fonctions dans un débogueur.
00:16:41Alors,
00:16:41peut-être êtes-vous méfiant que ce soit la panacée complète.
00:16:45Comme cela vient évidemment avec des compromis.
00:16:47Et oui,
00:16:48à cela je dirais bien sûr,
00:16:50eh bien,
00:16:51vous savez,
00:16:52ce que je dirais en fait,
00:16:54c'est que toute l'ingénierie logicielle consiste à gérer les compromis.
00:17:01Nous ne résolvons pas toujours les problèmes exactement,
00:17:04mais nous choisissons de nouveaux ensembles de compromis pour apporter de la valeur.
00:17:08Donc,
00:17:09pour atteindre nos objectifs de conception concernant les builds incrémentaux dans Turbo Pack,
00:17:14nous avons misé tous nos jetons sur ce modèle de programmation réactive incrémentale.
00:17:19Et cela a bien sûr eu des conséquences très naturelles.
00:17:23Alors,
00:17:24vous savez,
00:17:25peut-être avons-nous réellement résolu le problème des systèmes de mise en cache faits à la main et de la logique d'invalidation fastidieuse.
00:17:33En échange,
00:17:34nous devons gérer une infrastructure de mise en cache compliquée.
00:17:39Et bien sûr,
00:17:39vous savez,
00:17:40cela me semble être un très bon compromis.
00:17:42J'aime l'infrastructure de mise en cache compliquée,
00:17:45mais nous devons tous vivre avec les conséquences.
00:17:48Le premier est bien sûr juste les surcoûts fondamentaux de ce système.
00:17:54Vous savez,
00:17:55si vous y pensez dans un build donné ou une session HMR,
00:18:00vous ne changez pas vraiment grand-chose.
00:18:04Nous suivons donc toutes les informations de dépendance entre chaque importation et chaque résultat de résolution dans votre application,
00:18:10mais vous n'allez en fait en changer que quelques-unes.
00:18:13La plupart des informations de dépendance que nous collectons ne sont donc jamais réellement nécessaires.
00:18:16Alors,
00:18:17vous savez,
00:18:18pour gérer cela,
00:18:18nous avons dû beaucoup nous concentrer sur l'amélioration des performances de cette couche de mise en cache pour réduire les surcoûts et permettre à notre système de s'adapter à des applications de plus en plus grandes.
00:18:30Et le suivant et le plus évident est simplement la mémoire.
00:18:34Vous savez,
00:18:35les caches sont toujours fondamentalement un compromis temps/mémoire.
00:18:38Et le nôtre ne fait rien de vraiment différent à cet égard.
00:18:41Notre objectif simple est que la taille du cache devrait évoluer linéairement avec la taille de votre application.
00:18:49Mais encore une fois,
00:18:49nous devons faire attention aux surcoûts.
00:18:51Celui-ci est un peu subtil.
00:18:54Nous avons donc beaucoup d'algorithmes dans le bundler,
00:18:57comme vous pouvez vous y attendre.
00:18:58Et certains d'entre eux nécessitent en quelque sorte de comprendre quelque chose de global sur votre application.
00:19:03Eh bien,
00:19:03c'est un problème car chaque fois que vous dépendez d'informations globales,
00:19:07cela signifie que tout changement pourrait invalider cette opération.
00:19:10Nous devons donc être prudents quant à la façon dont nous concevons ces algorithmes,
00:19:14composer les choses avec soin afin de pouvoir préserver l'incrémentalité.
00:19:17Et enfin,
00:19:18celui-ci est peut-être un peu une plainte personnelle.
00:19:24Tout est asynchrone dans Turbo Pack.
00:19:27Et donc c'est excellent pour la scalabilité horizontale,
00:19:29mais encore une fois,
00:19:30cela nuit à nos objectifs fondamentaux,
00:19:31comme,
00:19:31vous savez,
00:19:32le débogage et le profilage des performances.
00:19:38Je suis donc sûr que beaucoup d'entre vous ont de l'expérience dans le débogage asynchrone,
00:19:43par exemple dans les outils de développement de Chrome.
00:19:46Et c'est généralement une expérience assez agréable.
00:19:48Pas toujours idéal.
00:19:49Et je vous assure que Rust avec LLDB est à des années-lumière derrière.
00:19:53Donc,
00:19:54pour gérer cela,
00:19:55nous avons dû investir dans des outils de visualisation,
00:19:58d'instrumentation et de traçage personnalisés.
00:20:01Et regardez ça,
00:20:02encore un projet d'infrastructure qui n'est pas un bundler.
00:20:07D'accord,
00:20:07alors jetons un coup d'œil et voyons si nous avons fait le bon pari.
00:20:11Chez Vercel,
00:20:12nous avons une très grande application de production.
00:20:17Nous pensons que c'est peut-être l'une des plus grandes au monde,
00:20:19mais,
00:20:19vous savez,
00:20:20nous ne le savons pas vraiment.
00:20:21Mais elle contient environ 80 000 modules.
00:20:23Alors, voyons comment Turbo Pack se comporte avec elle.
00:20:26Pour le rafraîchissement rapide,
00:20:28nous dominons vraiment ce que Web Pack est capable de livrer.
00:20:32Mais c'est un peu une vieille nouvelle.
00:20:33Turbo Pack pour le développement est sorti depuis un certain temps,
00:20:36et j'espère vraiment que tout le monde l'utilise au moins en développement.
00:20:39Mais vous savez,
00:20:39la nouveauté ici aujourd'hui,
00:20:40bien sûr,
00:20:41c'est que les builds sont stables.
00:20:42Alors, regardons un build.
00:20:44Et ici,
00:20:45vous pouvez voir une victoire substantielle sur Web Pack pour cette application.
00:20:49Ce build particulier fonctionne en fait avec notre nouvelle couche de cache de système de fichiers expérimentale.
00:20:53Donc,
00:20:54environ 16 de ces 94 secondes consistent juste à vider le cache à la fin.
00:20:59Et c'est quelque chose que nous allons nous efforcer d'améliorer à mesure que la mise en cache du système de fichiers deviendra stable.
00:21:04Mais bien sûr,
00:21:04le problème avec les builds à froid,
00:21:06c'est qu'ils sont froids,
00:21:06rien n'est incrémental.
00:21:07Alors, jetons un coup d'œil à un véritable build à chaud.
00:21:10Donc,
00:21:11en utilisant le cache du build à froid,
00:21:13nous pouvons voir ceci.
00:21:14C'est donc juste un aperçu de là où nous en sommes aujourd'hui.
00:21:17Parce que nous avons ce système de mise en cache à grain fin,
00:21:19nous pouvons en fait simplement écrire le cache sur le disque,
00:21:22puis lors du prochain build,
00:21:23le relire,
00:21:24déterminer ce qui a changé et terminer le build.
00:21:26D'accord,
00:21:27cela semble plutôt bien,
00:21:28mais beaucoup d'entre vous se disent,
00:21:29eh bien,
00:21:30peut-être que je n'ai pas personnellement la plus grande application Next.js au monde.
00:21:34Alors, jetons un coup d'œil à un exemple plus petit.
00:21:37Le site web react.dev est un peu plus petit.
00:21:41C'est aussi intéressant car il utilise un compilateur React.
00:21:44Il est sans surprise un des premiers à adopter le compilateur React.
00:21:47Et le compilateur React est implémenté en Babel.
00:21:49Et c'est un peu un problème pour notre approche car cela signifie que pour chaque fichier de l'application,
00:21:53nous devons demander à Babel de le traiter.
00:21:55Fondamentalement,
00:21:56je dirais que nous,
00:21:57ou plutôt moi,
00:21:58ne pouvons pas rendre le compilateur React plus rapide.
00:22:01Ce n'est pas mon travail.
00:22:02Mon travail, c'est Turbo Pack.
00:22:03Mais nous pouvons déterminer exactement quand l'appeler.
00:22:07Alors,
00:22:08en regardant les temps de rafraîchissement rapide,
00:22:11j'ai été en fait un peu déçu de ce résultat.
00:22:13Et il s'avère qu'environ 130 de ces 140 millisecondes sont dues au compilateur React.
00:22:18Et Turbo Pack et Web Pack font cela.
00:22:22Mais avec Turbo Pack,
00:22:23après que le compilateur React ait traité ce changement,
00:22:26nous pouvons voir,
00:22:27oh,
00:22:27les importations n'ont pas changé.
00:22:29L'envoyer vers la sortie et continuer.
00:22:31Encore une fois,
00:22:32sur les builds à froid,
00:22:34nous voyons ce genre de gain constant de 3x.
00:22:37Et juste pour être clair, c'est sur ma machine.
00:22:39Mais encore une fois,
00:22:41pas d'incrémentalité dans un build à froid.
00:22:44Et dans un build à chaud,
00:22:45nous voyons ce temps bien meilleur.
00:22:47Donc encore une fois,
00:22:48avec un build à chaud,
00:22:49nous avons déjà le cache sur le disque.
00:22:52Tout ce que nous devons faire est,
00:22:53une fois que nous commençons,
00:22:55de déterminer quels fichiers de l'application ont changé,
00:22:57de réexécuter ces tâches,
00:22:58puis de réutiliser tout le reste du build précédent.
00:23:01Alors la question fondamentale est : sommes-nous déjà Turbo ?
00:23:05Oui.
00:23:06Alors oui, cela a été discuté lors de la keynote, bien sûr.
00:23:09Turbo Pack est stable à partir de Next 16.
00:23:12Et nous sommes même le bundler par défaut pour Next.
00:23:14Alors, vous savez, mission accomplie, de rien.
00:23:17Mais. (rires) (applaudissements du public)
00:23:23Et si vous avez remarqué ce retour en arrière lors de la keynote,
00:23:27c'était moi qui essayais de faire de Turbo Pack le bundler par défaut.
00:23:30Cela n'a pris que trois tentatives.
00:23:31Mais ce que je veux vraiment vous laisser,
00:23:34encore une fois,
00:23:35c'est ceci.
00:23:35Vous savez, parce que nous n'avons pas fini.
00:23:37Nous avons encore beaucoup à faire sur les performances,
00:23:39et à achever le développement de la couche de cache du système de fichiers.
00:23:42Je vous suggère à tous de l'essayer en développement.
00:23:44Et c'est tout.
00:23:46Merci beaucoup.
00:23:47N'hésitez pas à venir me voir, à me poser des questions.
00:23:49(applaudissements du public) (musique entraînante) (musique entraînante)