Skip to content

Frontend Build Migration: From Yarn in CI to Multi-Stage Dockerfile with pnpm #5460

@nXtCyberNet

Description

@nXtCyberNet

pnpm + Multi-Stage Docker Migration

Overview

This proposal replaces the current Yarn-in-CI + single-stage (or partially optimized) Docker build process with a multi-stage Docker build using pnpm.

The objective is to improve:

  • Build performance (CI/CD)
  • Image size efficiency
  • Reproducibility across environments
  • Long-term maintainability

This is not a speculative optimization. It reflects patterns observed across production-grade Node.js deployments (2025–2026), particularly in frontend-heavy applications (Next.js, Vite, CRA).


Problem Statement

The current setup introduces several inefficiencies:

  • Image size is not significantly bloated currently (already using an nginx alpine runtime with prebuilt assets), but further reductions are still possible via better build-stage isolation and dependency handling
  • Slow CI rebuilds, especially when dependency installation is repeated
  • Inconsistent environments between CI and runtime
  • Split responsibility between CI scripts and Dockerfile logic

These issues compound as the project scales.


Proposed Solution

Adopt a multi-stage Docker build using pnpm with Docker-native caching.

Key Changes

  1. Replace Yarn with pnpm
  2. Introduce a dedicated build stage
  3. Use --mount=type=cache for dependency installation
  4. Copy only required artifacts into the final runtime image
  5. Ensure lockfile-based deterministic installs (pnpm install --frozen-lockfile)

Expected Outcomes (Realistic)

1. Image Size Impact

  • No significant reduction expected

  • Current setup already uses an nginx:alpine runtime with prebuilt static assets, meaning:

    • No node_modules in final image
    • Minimal runtime footprint already achieved

Possible minor improvements:

  • Slight reduction from cleaner build-stage artifacts
  • Better layer optimization

Reality:
Image size is already near-optimal. This migration is not driven by size reduction.


2. CI Rebuild Time Improvement

  • Typical improvement: 15-20% faster

  • Example:

    • Before: 4–12 minutes
    • After: 1–4 minutes (cache hit)

Reason:

  • pnpm’s store + Docker cache avoids repeated full installs
  • Dependency layers remain stable unless lockfile changes

3. Faster Cold Installs

  • Improvement: 1.5× to 3× faster
  • Especially noticeable on fresh CI runners

4. Deployment Efficiency

  • Reduced image size improves:

    • docker push
    • Image pull times in Kubernetes
    • Pod startup latency

5. Reliability Improvements

  • Eliminates environment drift between CI and production
  • Ensures Node version and dependency consistency
  • Reduces “works in CI but fails in runtime” issues

6. Developer Experience

  • Easier debugging via:

    docker build --target build .
  • No need to replicate CI environment manually


7. Maintainability

  • Consolidates build logic into a single Dockerfile
  • Removes dependency on CI-specific scripts/artifacts
  • Stricter lockfile behavior catches issues earlier

8. Scalability (Monorepos)

  • pnpm workspaces are more efficient for large repositories
  • Supports selective installs via filters

Trade-offs / Considerations

  • Initial migration effort required
  • Team familiarity with pnpm may be lower than Yarn
  • Slight learning curve for Docker cache mounts

These are one-time costs with long-term payoff.


Conclusion

The migration to pnpm with a multi-stage Docker build provides consistent, measurable improvements in performance, reliability, and maintainability.

While image size reductions are moderate in well-optimized setups, CI speed and determinism improvements are substantial and consistent, making this change a high-leverage optimization for most Node.js projects.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions