Que fait mcmaster-fast ?
Faites en sorte que les autres sites ressemblent à mcmaster.com : premier affichage en quelques dizaines de millisecondes, page suivante avant que la barre d'URL ne se mette à jour.
La stack importe peu. McMaster le fait avec ASP.NET, YUI et un ScriptCombiner. L'ordre et le nombre de requêtes comptent. La mode des frameworks, non.
Ce qu'ils font réellement
Observé sur le site en direct (2026-09-13) ainsi que le démontage de Wes Bos (notes de klinke.studio) :
| Couche | Ce que fait McMaster | Pourquoi ça semble instantané |
|---|---|---|
| Premier octet | HTML rendu côté serveur. Le navigateur paint avant le JS. FCP ~64ms, TTFB ~19ms sur un shell chaud. | L'utilisateur voit une page, pas un spinner attendant un bundle. |
| Shell | #ShellLayout_Cntnr + #MainContent. L'en-tête/panier restent montés. history.pushState. | Un clic sur une catégorie conserve le même nœud d'en-tête et échange le contenu en 35ms. |
| Prédiction | Le survol/intention récupère le HTML suivant avant le clic. | Le clic est un cache hit + échange DOM. |
| Visite répétée | Service worker en cache-first pour les navigations GET (pas les PDF). Cache de / après le premier chargement. | Le HTML source est ~200ms (mc-turn) ; le SW le sert localement. |
| Waterfall | dns-prefetch pour les hébergeurs d'images. preload pour les polices woff2, le logo, les sprites LCP, le JS/CSS de page, ShellDynamic.aspx. | Le navigateur commence les polices/LCP avant de les découvrir dans le CSS. |
| CSS | ~32KB de CSS commun inline dans <style> dans <head>. Le reste via un combineur spécifique à la page. | Le premier layout n'a besoin d'aucune requête CSS supplémentaire. |
| JS | Bundles ScriptCombiner spécifiques à la page (?files=…). Async. Les WebParts se chargent après le paint. | La page catalogue ne télécharge pas le code de la caisse. |
| Assets | URLs versionnées (/mv1789156784/, ?ver=). Cache-Control: public,immutable,max-age=31536000. Hôte d'images images1.mcmaster.com. Sprites pour les grilles de tuiles. | Cache d'un an, pas de danse d'invalidation, peu de requêtes. |
| Stabilité | Boîtes réservées / sprites. CLS mesuré 0. | Pas de reflow pendant l'arrivée des images. |
| Poids | Analytiques first-party (/trk/). Pas de pubs. CSP verrouillé sur *.mcmaster.com. | La page est le produit. |
Les documents HTML eux-mêmes sont Cache-Control: no-cache et x-check-cacheable: NO chez Akamai. Ne copiez pas "cache-tout-le-HTML-sur-CDN". Ils mettent en cache le shell dans le navigateur et les fichiers statiques immutables en périphérie.
Échelle de priorités
Arrêtez-vous au premier échelon qui amène la page sous ~200ms de LCP sur un cache chaud. N'installez pas Workbox, un pipeline de sprites et des règles de spéculation en une seule PR.
- Livrez du HTML que le navigateur peut peindre. SSR ou HTML statique. Pas de rendu client-only pour la première vue. Supprimez le JS qui construit le premier écran.
- Débloquez le premier affichage. Inlinez seulement le CSS au-dessus-de-la-ligne (ou une petite feuille bloquante).
preloadl'image LCP et les polices woff2 (crossorigin).width/height(ou aspect-ratio CSS) sur chaque image. - Fichiers statiques immutables. Empreinte ou requête de version.
Cache-Control: public, immutable, max-age=31536000. - Chrome persistant + échange de contenu. Layout partagé. La navigation suivante remplace un nœud de contenu et fait
pushState. Ne remontez pas l'en-tête. - Préchargement intentionnel. Document suivant spéculé au survol / dans le viewport. Limitez-le. Ne préchargez jamais la caisse, les API de recherche ou le HTML authentifié.
- Service worker de navigation (optionnel). Cache-first pour les navigations GET du shell/public/accueil. Effacez au déploiement. Invalidez depuis la page, pas avec un SW malin. Sautez si le site est majoritairement privé.
- JS spécifique à la page. Route-split. Reportez les analytiques jusqu'à l'inactivité. Supprimez les tags tiers qui ne sont pas le produit.
- Sprites / hôte d'images seulement si vous avez des dizaines de petites icônes sur une vue. HTTP/2 + quelques images compressées suffisent en dessous.
Workflow de l'agent
Lorsqu'on vous demande de rendre un site rapide de cette manière :
- Tracez le vrai premier chargement et une navigation dans l'application (réseau + ce qui s'affiche). Nommez l'élément LCP actuel et le JS qui le bloque.
- Appliquez l'échelon le plus bas manquant. Un changement par passage, sauf si l'utilisateur demande une révision complète.
- Préférez les fonctionnalités déjà présentes dans le dépôt (Next
<Link>,next/font, layouts App Router) aux nouvelles bibliothèques. - Après un passage, laissez un indicateur : les chiffres LCP / FCP, ou une petite assertion que le nœud du shell est réutilisé lors d'une navigation client.
- Lisez techniques.md pour la recette exacte de l'échelon que vous implémentez. Lisez recipes.md pour les correspondances Next.js / vanilla / SPA existant.
Règles strictes
- Le HTML est le produit. JS est une amélioration optionnelle.
- Le préchargement est une indication, pas un crawler. Uniquement des documents GET de même origine.
- HTML personnalisé est
no-storeou uniquement via SW avec un TTL court. Ne mettez jamais le HTML du panier/compte sur un cache CDN partagé. - N'ajoutez pas de service worker qui intercepte tous les assets. Uniquement les documents de navigation, correspondant à
ServiceWorkerJS.aspxde McMaster. - Ne copiez pas YUI, sprites ou ASP.NET. Copiez l'ordre des opérations.
- Ne "modernisez" pas une page HTML rapide en un SPA client comme solution.
- Les scripts tiers (pubs, gestionnaires de tags, chat) sont présumés coupables. Gardez-les hors du premier affichage ou supprimez-les.
- Marquez les raccourcis avec
ponytail:lorsque vous sautez un échelon de moindre valeur.
Fait quand
- Première visite : le HTML s'affiche avant qu'aucun bundle d'application ne s'exécute. LCP est un élément envoyé par le serveur, pas un élément rendu côté client.
- Prochain clic : le chrome reste monté ; seule la zone de contenu est remplacée.
- Visite répétée de l'accueil/shell : servie localement ou depuis le cache mémoire.
- Polices et image LCP dans les 1 à 2 premiers allers-retours, pas découvertes après le CSS.
- CLS reste proche de 0 sur les pages que vous avez touchées.