Rollup Asset Optimization

Implement deterministic asset fingerprinting and automated CDN cache invalidation using Rollup’s output configuration. This workflow ensures production deployments serve immutable static files while maintaining zero-downtime cache turnover. The architecture integrates directly with enterprise-grade Build Tool & Framework Asset Pipeline Integration strategies to standardize release engineering across frontend and infrastructure teams.

Core Objectives:

  • Deterministic content hashing for JavaScript, CSS, and static assets
  • Automated CDN purge execution via build lifecycle hooks
  • Cross-environment cache consistency for staging and production
  • Seamless integration with CI/CD deployment pipelines

Rollup Output Hashing Configuration

Configure output.assetFileNames and output.chunkFileNames to enforce deterministic content hashing. Production environments require stable asset naming to prevent unnecessary cache invalidation and ensure predictable routing.

Hash Placeholder Strategy

Rollup provides multiple placeholder options. Selecting the correct one dictates cache behavior and build reproducibility.

Placeholder Derivation Cache Behavior Production Suitability
[hash] Module ID + Build Order Volatile across environments ❌ Avoid
[contenthash] File Content Only Stable across environments ✅ Mandatory
[name] Entry/Chunk Name Predictable but non-unique ️ Use with hash

Always use [contenthash] for production. It derives exclusively from file content, ensuring deterministic naming regardless of build order or environment variables. Align the hash length to 8–12 characters to satisfy most CDN routing requirements without bloating filenames.

Implementation

Execute the following configuration in rollup.config.mjs. This setup isolates assets into a dedicated directory, applies an 8-character content hash, and emits a routing manifest during the generateBundle phase.

export default {
 input: 'src/main.js',
 output: {
 dir: 'dist',
 format: 'es',
 chunkFileNames: 'assets/[name]-[contenthash:8].js',
 assetFileNames: 'assets/[name]-[contenthash:8][extname]'
 },
 plugins: [
 {
 name: 'generate-manifest',
 generateBundle(outputOptions, bundle) {
 const manifest = {};
 for (const [fileName, asset] of Object.entries(bundle)) {
 if (asset.type === 'chunk' || asset.type === 'asset') {
 manifest[asset.name || fileName] = fileName;
 }
 }
 this.emitFile({ type: 'asset', fileName: 'asset-manifest.json', source: JSON.stringify(manifest, null, 2) });
 }
 }
 ]
};

Execution Workflow:

  1. Pin your Node.js version using .nvmrc or engines in package.json.
  2. Run the production build: npx rollup -c --environment NODE_ENV:production
  3. Verify deterministic output by running the build twice and comparing checksums: sha256sum dist/assets/*

For framework-specific overrides or when migrating from meta-frameworks, review the Vite Asset Pipeline Configuration documentation to understand how underlying Rollup defaults are abstracted.

CDN Cache Invalidation Workflow

Automate cache purging immediately after bundle generation. Relying on manual invalidation introduces latency and increases the risk of serving stale assets during deployments.

Post-Build Hook Architecture

Leverage Rollup’s closeBundle lifecycle to trigger CDN API calls. This hook executes after all files are written to disk, guaranteeing the manifest is available for precise path extraction.

import { execSync } from 'child_process';

export default {
 // ...output config
 plugins: [{
 name: 'cdn-invalidate',
 closeBundle() {
 const manifest = require('./dist/asset-manifest.json');
 const paths = Object.values(manifest);
 execSync(`curl -X POST https://cdn-api.provider.com/v1/purge -H 'Authorization: Bearer $CDN_TOKEN' -d '${JSON.stringify({ paths })}'`);
 }
 }]
};

CI/CD Integration Steps:

  1. Store your CDN API token securely in your pipeline secrets manager (e.g., GitHub Actions Secrets, AWS Secrets Manager).
  2. Inject the token into the build environment: export CDN_TOKEN=$
  3. Execute the build: npm run build
  4. Validate the purge response in the CI logs. A 200 OK confirms successful invalidation.

When migrating legacy pipelines or aligning with older bundler patterns, validate your invalidation strategy against the Webpack Output Hashing Setup migration patterns to ensure consistent cache turnover logic.

Manifest Generation & Deployment Mapping

The asset-manifest.json file bridges the gap between hashed static assets and server-side routing. It enables dynamic resolution without hardcoding filenames in templates.

Server-Side Integration

  1. Read Manifest at Runtime: Load asset-manifest.json during application startup or request initialization.
  2. Inject into Templates: Replace static asset references with dynamic lookups: <script src="${manifest['main.js']}"></script>
  3. Handle Dynamic Imports: Ensure manualChunks configuration aligns with manifest generation. Rollup’s generateBundle hook iterates over the entire bundle object, capturing asynchronously loaded chunks.
  4. Atomic Deployment: Deploy HTML templates and the manifest simultaneously with the dist/ directory. Non-atomic deployments cause cache misses where the HTML references a new hash that the CDN has not yet received.

Deployment Pipeline Checklist

  • asset-manifest.json is generated and contains all entry/chunk paths
  • 200 OK for all new asset paths
  • Cache-Control: public, max-age=31536000, immutable

Common Pitfalls & Resolutions

Issue Root Cause Resolution
Non-deterministic hashes across environments Rollup uses [hash] which includes volatile module IDs; inconsistent Node versions or plugin execution order Switch to [contenthash], pin Node.js versions, and configure @rollup/plugin-node-resolve with consistent moduleSideEffects
CDN cache miss on first deployment HTML references new hashes while CDN caches old manifest; non-atomic deployment Implement dual-version serving during rollout, enforce immutable cache headers, and deploy HTML/manifest atomically with assets
Dynamic import chunks missing from manifest generateBundle hook only captures top-level outputs if dynamic imports are processed asynchronously Iterate comprehensively over the bundle object, filter by type === 'chunk', and align manualChunks with manifest logic

Frequently Asked Questions

Should I use [hash] or [contenthash] in Rollup output? Always use [contenthash] for production. It derives from file content, ensuring deterministic naming across environments and preventing unnecessary cache invalidation.

How do I handle CDN cache invalidation without purging the entire zone? Use path-based invalidation targeting only newly generated hashed assets. Rollup’s manifest generation enables precise API calls to purge specific URLs rather than blanket zone purges.

Can Rollup optimize third-party vendor assets for fingerprinting? Yes. Configure manualChunks to isolate vendor dependencies, apply consistent output.chunkFileNames patterns, and ensure external dependencies are bundled or properly aliased for deterministic hashing.