komal.nakrani
Browse Themes
ThemesCategoriesDocsBlogTips & Tricks
Deployment••By Komal Nakrani

Astro Build Speed: Faster Builds in CI

Speed up Astro builds in CI by caching node_modules/.astro (processed images and the content data store), using npm ci with a cache, and tuning image work.

#Astro#Deployment#CI#Build Performance

The biggest win for Astro build speed in CI is caching node_modules/.astro between runs. That’s Astro’s default cacheDir, where it keeps optimised images and the content layer’s data store. Without it, every CI build re-processes every image from scratch. Add a dependency cache for npm, and a typical image-heavy site goes from rebuilding everything to only processing what changed.

Key Takeaways

  • Cache node_modules/.astro (or your custom cacheDir) between builds.
  • Cache npm’s download cache and use npm ci.
  • Images are usually the slowest part: avoid unnecessary formats and oversized sources.
  • Measure first: astro build prints timings per phase.

Find what’s slow

Run a build and read the log. Astro reports time spent generating static routes and optimising images:

npm run build

If most of the time is in image generation, caching will help a lot. If it’s in route generation, look at expensive work in getStaticPaths() or page frontmatter, such as one API call per page instead of one for the whole collection.

GitHub Actions

# .github/workflows/build.yml
name: Build
on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm

      - run: npm ci

      - name: Cache Astro assets
        uses: actions/cache@v4
        with:
          path: node_modules/.astro
          key: astro-${{ runner.os }}-${{ hashFiles('package-lock.json') }}-${{ github.sha }}
          restore-keys: |
            astro-${{ runner.os }}-${{ hashFiles('package-lock.json') }}-
            astro-${{ runner.os }}-

      - run: npm run build

npm ci deletes node_modules before installing, so restore the Astro cache after it, as shown. The key includes the commit SHA so each run saves a fresh cache, while restore-keys picks up the most recent one.

Netlify, Vercel and Cloudflare Pages

Hosts cache dependencies between builds automatically. Whether node_modules/.astro survives depends on the platform and changes over time. If builds are slow on a host, move cacheDir to a folder the host is documented to persist, or use the host’s build plugin or cache API. Check your host’s build cache documentation for the current behaviour.

// astro.config.mjs
export default defineConfig({
  cacheDir: './.astro-cache',
});

Reduce image work

Caching helps repeat builds. These help every build:

  • Resize sources before committing. A 6000px camera original takes far longer to process than a 2400px one, and nobody needs the difference on the web.
  • Limit formats. <Picture formats={['avif', 'webp']} /> encodes twice per width. AVIF encoding is slow; use it where the savings matter, such as heroes.
  • Limit widths. A layout generates several widths per image; for small thumbnails, a fixed layout or explicit short widths list is enough.
  • Use the CMS’s image CDN for remote images instead of re-processing them in Astro.

Concurrency

By default Astro builds pages one at a time. If page generation is the slow part and your pages do independent async work, raise it:

export default defineConfig({
  build: { concurrency: 4 },
});

This doesn’t help pages that are CPU-bound, and can increase memory use. Try it, measure, and keep it only if the build gets faster.

Content collections

The content layer stores parsed entries in its data store in the cache directory, and only re-parses changed files when the cache is present. For custom loaders that fetch from an API, use an object loader that compares a digest or updatedAt per entry, so unchanged entries are skipped. The content collections guide covers loaders.

Keep CI and local in sync

  • Pin Node with .nvmrc (22) and engines in package.json.
  • Commit package-lock.json and always install with npm ci in CI.
  • Run astro check as a separate step so type errors fail fast, before the expensive build.

For hosts and deploy settings, see the Astro deploy guide. Responsive image settings that affect build time are covered in responsive images with widths and sizes. The cacheDir and build.concurrency options are documented in the configuration reference.

FAQ

Why is my Astro build slow?

Usually image processing: many large source images, multiple formats and many widths per image. Cache node_modules/.astro and resize sources before committing.

Is it safe to delete node_modules/.astro?

Yes. It’s a cache. Astro rebuilds it on the next build, which will just take longer.