Agent Skill · Salesforce Commerce Cloud

sfnext-performance

Optimize Storefront Next performance with bundle size limits, DynamicImage component, Lighthouse audits, and progressive streaming. Use when checking bundle sizes, optimizing images, improving page load speed, or configuring performance metrics. Covers parallel data fetching, image optimization, and performance monitoring.

Provider: Salesforce Commerce Cloud Path in repo: skills/storefront-next/skills/sfnext-performance/SKILL.md

Skill body

Performance Skill

This skill covers performance optimization techniques for Storefront Next storefronts.

Bundle Size Limits

The application enforces strict bundle size limits in package.json under the bundlesize configuration.

pnpm bundlesize:test      # Verify bundle stays within limits
pnpm bundlesize:analyze   # Analyze bundle composition

Built-in Metrics

Enable performance tracking in config.server.ts:

{
    performance: {
        metrics: {
            serverPerformanceMetricsEnabled: true,
            clientPerformanceMetricsEnabled: true,
            serverTimingHeaderEnabled: false  // Enable for debugging only
        }
    }
}

Tracks:

Parallel Data Fetching

Return all promises simultaneously in loaders — avoid sequential await:

// GOOD — Parallel (all requests start at once)
export function loader({ context }: LoaderFunctionArgs) {
    const clients = createApiClients(context);
    return {
        product: clients.shopperProducts.getProduct({...}),
        reviews: clients.shopperProducts.getReviews({...}),
        recommendations: clients.shopperProducts.getRecommendations({...}),
    };
}

// BAD — Sequential (each waits for previous)
export async function loader({ context }: LoaderFunctionArgs) {
    const product = await clients.shopperProducts.getProduct({...});
    const reviews = await clients.shopperProducts.getReviews({...});
    return { product, reviews };
}

Image Optimization

Use the DynamicImage component with WebP format:

import { DynamicImage } from '@/components/dynamic-image';

<DynamicImage
    src={product.image.link}
    alt={product.image.alt}
    width={400}
    height={400}
    format="webp"
/>

Image Best Practices

Progressive Streaming

Use synchronous loaders returning promises to stream data progressively:

// Streams data as each promise resolves
export function loader({ context }: LoaderFunctionArgs) {
    const clients = createApiClients(context);
    return {
        product: clients.shopperProducts.getProduct({...}),    // Streams independently
        reviews: clients.shopperProducts.getReviews({...}),    // Streams independently
    };
}

Combine with granular Suspense boundaries for progressive page rendering.

Lighthouse Optimization

Monitor and improve performance metrics:

pnpm lighthouse:ci   # Run Lighthouse CI

Key areas:

Troubleshooting

Issue Cause Solution
Large bundle size Unused imports or heavy dependencies Run bundlesize:analyze; tree-shake or lazy load
Slow page transitions Async loaders blocking Use synchronous loaders returning promises
Layout shifts Missing image dimensions Set width and height on images
Slow SCAPI responses Sequential API calls Use parallel data fetching