From 3cc388eb5c798377650bea03a8eaa19574c79be1 Mon Sep 17 00:00:00 2001 From: zak Date: Thu, 28 May 2026 14:18:07 +0100 Subject: [PATCH] Speed up yarn develop on warm restart `yarn develop` previously ran `gatsby clean` before every start, so every run was a cold start: ~150s webpack bundle and ~130s sharp image processing for our ~500 MDX pages. Drop `gatsby clean` from `develop` so the babel-loader, terser, webpack, and sharp caches survive between runs, and add `develop:clean` as an escape hatch when a true reset is needed. The reason `develop` previously required a clean is a Gatsby cache quirk: ExampleFile nodes are derived inside onCreateNode from parent File nodes sourced by gatsby-source-filesystem. On warm restart, Gatsby does not call onCreateNode for cached-unchanged parents, so the derived ExampleFile nodes are never touched and get removed by the stale-node GC. createPages then fails with "Examples result is undefined". Add a sourceNodes hook that touches every ExampleFile each build so they survive. With derived-node GC fixed, GATSBY_EXPERIMENTAL_DEV_SSR is safe to enable; it lazy-compiles pages on demand and is the largest single win on warm restart. Earlier attempts blamed DEV_SSR for the missing nodes, but those failures were the same stale-GC bug presenting earlier. Also restrict gatsby-plugin-sharp formats to ['auto'] in dev so cold image processing doesn't produce WebP variants we never look at locally (production unchanged), and set GATSBY_CPU_COUNT=physical_cores on dev scripts so sharp uses every physical core. Measured locally: cold ~290s -> ~120s; warm restart ~17s end-to-end (previously not viable because of the cache bug). --- data/onCreateNode/index.ts | 11 +++++++++++ gatsby-config.ts | 11 ++++++++++- gatsby-node.ts | 2 +- package.json | 5 +++-- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/data/onCreateNode/index.ts b/data/onCreateNode/index.ts index cadf7b576b..526dd3e121 100644 --- a/data/onCreateNode/index.ts +++ b/data/onCreateNode/index.ts @@ -1,5 +1,16 @@ import { GatsbyNode, Node } from 'gatsby'; +// Touch existing derived nodes on every build so Gatsby's stale-node GC +// does not delete them on warm restart. Derived nodes created via +// `createNode` from inside `onCreateNode` are not re-created when their +// parent File nodes are cached unchanged, so without this hook the +// ExampleFile nodes disappear between dev runs and `allExampleFile` +// returns undefined in createPages. +export const sourceNodes: GatsbyNode['sourceNodes'] = ({ actions, getNodesByType }) => { + const { touchNode } = actions; + getNodesByType('ExampleFile').forEach((node) => touchNode(node)); +}; + export const onCreateNode: GatsbyNode['onCreateNode'] = async ({ node, actions: { createNode, createParentChildLink }, diff --git a/gatsby-config.ts b/gatsby-config.ts index cc56590dd8..a6a5597171 100644 --- a/gatsby-config.ts +++ b/gatsby-config.ts @@ -67,7 +67,16 @@ const headerLinkIcon = `