Skip to content

Frontend: webpack build optimizations — contenthash and persistent cache#1366

Merged
gusthoff merged 4 commits into
AdaCore:mainfrom
gusthoff:dev/topic/infrastructure/webpack/build-opts/2026-06-06/main
Jun 6, 2026
Merged

Frontend: webpack build optimizations — contenthash and persistent cache#1366
gusthoff merged 4 commits into
AdaCore:mainfrom
gusthoff:dev/topic/infrastructure/webpack/build-opts/2026-06-06/main

Conversation

@gusthoff
Copy link
Copy Markdown
Collaborator

@gusthoff gusthoff commented Jun 6, 2026

Summary

Two low-effort webpack 5 optimizations to the frontend/webpack.common.cjs
configuration:

  • contenthash: replace [fullhash] with [contenthash] on all output
    filenames (JS, CSS, fonts). [contenthash] hashes only the content of each
    individual chunk, so unchanged chunks keep their filename across builds.
    [fullhash] rotated every filename on any change to any module.
  • Persistent filesystem cache: enable webpack 5's built-in module-graph
    cache. Serializes resolved modules to node_modules/.cache/webpack/ after a
    cold build; subsequent builds restore from cache, giving a significant warm-
    build speedup for local development and CI (when the cache directory is
    restored between runs).

Changes

  • frontend/webpack.common.cjs: output.filename and
    MiniCssExtractPlugin.filename changed from [fullhash] to [contenthash]
  • frontend/webpack.common.cjs: font_rule name option changed from
    [name].[ext]?[fullhash] to [name].[ext]?[contenthash]
  • frontend/webpack.common.cjs: cache: { type: 'filesystem', ... } block
    added

Testing / Validation

Tested on web VM — Node.js 24, pnpm 11, webpack 5.107.2.

contenthash independence: edited one string literal in dom-utils.ts
(which is imported by the entry point). Only the main.js chunk hash changed
(2277acdf…02e595ad…); the vendor split-chunk (634.12d978….js) and
the CSS chunk (main.7c35a299….css) kept their filenames unchanged. Reverting
the edit restored the original hash, confirming deterministic contenthash
behaviour.

Persistent cache — warm-build speedup:

  • Cold build (empty cache): 27.7 s
  • Warm build (cache populated): 3.6 s — 7.5× faster; output filenames
    identical to the cold build
  • Config invalidation: a whitespace-only edit to webpack.common.cjs triggered
    a full rebuild (19.8 s), confirming that buildDependencies.config works
    as expected

Notes

The node_modules/.cache/webpack/ cache directory is already excluded from
git via the node_modules entry in frontend/.gitignore. For CI warm-build
benefit, this directory should be cached in the GitHub Actions workflow (see
the "Cache build artifacts across CI runs" proposal in
LEARN_INFRASTRUCTURE_IMPROVEMENTS.md).

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

gusthoff added 4 commits June 6, 2026 02:07
…hash]

Replace [fullhash] with [contenthash] in all three places in
webpack.common.cjs:
- output.filename: '[name].[fullhash].js' → '[name].[contenthash].js'
- MiniCssExtractPlugin filename: '[name].[fullhash].css' → '[name].[contenthash].css'
- font_rule name option: '[name].[ext]?[fullhash]' → '[name].[ext]?[contenthash]'

[fullhash] is a build-level hash — it rotates every filename whenever any
module changes. [contenthash] is a per-chunk hash that only changes when
the content of that specific chunk changes. Unchanged chunks therefore keep
their filename across releases, improving CDN and browser cache hit rate.
Add a cache block to webpack.common.cjs:

    cache: {
      type: 'filesystem',
      buildDependencies: {
        config: [__filename],
      },
    },

webpack 5's filesystem cache serializes the resolved module graph to
node_modules/.cache/webpack/ after a cold build. Subsequent builds restore
from that cache, skipping module resolution and giving a significant
warm-build speedup for local development and CI (when the cache directory
is restored between runs).

The buildDependencies.config entry ensures that any change to
webpack.common.cjs itself (or its transitive require()s) invalidates the
cache and forces a full rebuild, preventing stale cache hits after config
changes.

The cache directory is already covered by the node_modules entry in
frontend/.gitignore, so no .gitignore change is needed.
@gusthoff gusthoff merged commit 93ae539 into AdaCore:main Jun 6, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant