Skip to main content

Asset hashing uses content hash in filename

ab-002051 · performance-deep-dive.regression-prevention.asset-content-hash
Severity: infoactive

Why it matters

An asset named app.js with no content hash cannot be safely cached for more than a few minutes — the browser has no way to know whether the file changed since the last visit. Setting a long max-age on an unhashed asset means users receive stale code after a deploy; setting a short max-age means the asset is re-downloaded on every visit. Content hashing is the mechanism that makes aggressive 1-year caching safe: the filename itself is the cache key. ISO 25010:2011 time-behaviour links asset hashing to time-behaviour because it determines whether repeat visitors pay full download cost on every page load.

Severity rationale

Info because missing content hashes force a tradeoff between stale delivery and cache efficiency — the impact is either wasted bandwidth or stale assets, both of which degrade experience but do not cause functional failures.

Remediation

In Next.js and Vite, content hashing is automatic in production mode — verify it is not disabled in next.config.js. For custom webpack setups, configure [contenthash] in the output filename pattern.

// webpack.config.js — content hash in production
module.exports = {
  output: {
    filename: process.env.NODE_ENV === 'production'
      ? '[name].[contenthash:8].js'
      : '[name].js',
  },
}

Verify hashes are generated by inspecting .next/static/chunks/ — filenames should contain an 8-character hex string that changes when the file content changes.

Detection

  • ID: performance-deep-dive.regression-prevention.asset-content-hash

  • Severity: info

  • What to look for: Count all asset files in build output. Enumerate which have content hashes in filenames vs. static names. Examine the build output and analyze file names. Look for hashes in asset filenames (e.g., app.a1b2c3d4.js, style.xyz789.css). Check whether the build system is configured to generate content hashes.

  • Pass criteria: Assets are named with content hash in filename. Hashes change only when asset content changes. Build system automatically generates and updates hashes. At least 95% of JS and CSS assets should have content hashes.

  • Fail criteria: Assets have no hash in filename, or hash is static and doesn't change when content changes (e.g., app.bundle.js with no hash).

  • Skip (N/A) when: Never — asset hashing is a standard best practice.

  • Cross-reference: For cache headers leveraging hashes, see cache-control-hashed-assets.

  • Detail on fail: "Assets bundled as app.js with no content hash — impossible to cache-bust when updating" or "Hash in filename but is static; changing app code doesn't update hash"

  • Remediation: Configure your build tool to generate content hashes. In webpack, Next.js, or Vite, this is usually automatic in production mode.

    // next.config.js — content hashing is automatic in production
    // For webpack: output: { filename: '[name].[contenthash].js' }
    

External references

Taxons

History