How to Manage Static Asset Versioning in Vue Projects Without Hashes

This guide explains how to replace hash‑based static asset versioning with timestamps or package version numbers in Vue projects, adjust webpack configuration to keep hashes only on chunk files, handle preload/prefetch hints, and coordinate backend updates for reliable cache busting.

AutoHome Frontend
AutoHome Frontend
AutoHome Frontend
How to Manage Static Asset Versioning in Vue Projects Without Hashes

Background

In single‑page applications the backend serves a static index.html while all JavaScript and CSS assets are hosted on a CDN (e.g., s.autoimg.cn). Vue CLI adds a content hash to every output filename ( app.3f2a1c.js, chunk-vendor.9b8e7d.js, …). When any chunk changes, the hash of the entry file app.js also changes, forcing the backend to modify the HTML template on each release. To avoid frequent HTML updates the team switched to a dynamic timestamp query parameter (e.g., app.js?v=20240101) that can be regenerated hourly or daily.

Disabling filename hashing

Vue CLI enables filenameHashing by default. Setting filenameHashing: false in vue.config.js removes the hash from all output files, but the generated index.html still references the entry file with a hash‑less name, so the backend must still update the HTML when the entry changes.

Keep hashes for chunks while removing them from the entry file

To retain cache‑busting hashes for lazy‑loaded chunks but keep a stable name for the entry script, customize the webpack configuration:

module.exports = {
  chainWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      // CSS filenames – keep hash only for chunk CSS
      config.plugin('extract-css').tap(options => {
        options[0].filename = 'css/[name].css';
        options[0].chunkFilename = 'css/[name].[contenthash:8].css';
        return options;
      });
    }
  },
  configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      // JavaScript filenames – entry without hash, chunks with hash
      config.output.filename = 'js/[name].js';
      config.output.chunkFilename = 'js/[name].[contenthash:8].js';
    }
  }
};

After this change the entry app.js is always emitted as js/app.js, while dynamically imported chunks keep a content hash (e.g., js/chunk-vendor.9b8e7d.js), reducing unnecessary CDN invalidations.

Removing resource hints (preload & prefetch)

Vue CLI injects many <link rel="preload"> and <link rel="prefetch"> tags into the HTML head. When the entry hash changes, these hints may still point to the old assets, causing stale downloads. If aggressive preloading is not required, the plugins can be removed:

module.exports = {
  chainWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      // Remove the prefetch plugin
      config.plugins.delete('prefetch');
      // Remove the preload plugin
      config.plugins.delete('preload');
    }
  }
};

Disabling these hints simplifies version coordination at the cost of a potentially longer initial load.

Using a version string instead of a hash

Instead of a content hash, a stable version identifier (e.g., the version field from package.json) can be embedded in filenames. This makes the URLs predictable across builds and allows the backend to generate matching query parameters.

// vue.config.js (partial)
const pkg = require('./package.json');
const version = pkg.version; // e.g., "0.1.2"

module.exports = {
  chainWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      config.plugin('extract-css').tap(options => {
        options[0].filename = `css/[name].${version}.css`;
        options[0].chunkFilename = `css/[name].[contenthash:8].${version}.css`;
        return options;
      });
    }
  },
  configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      config.output.filename = `js/[name].${version}.js`;
      config.output.chunkFilename = `js/[name].[contenthash:8].${version}.js`;
    }
  }
};

The version can be bumped with npm version (e.g., npm version patch), which updates package.json and creates a Git tag. The backend should append the same version as a query parameter, e.g., app.js?v=0.1.2, to keep preload/prefetch links in sync.

Important notes on preload/prefetch with versioning

Even when using a version string, the HTML template must embed the identical version in the rel="preload" and rel="prefetch" links; otherwise those hints become ineffective. A common approach is to expose a helper function (e.g., addVersion()) in the entry script that injects the correct version at runtime, or to let the backend render the version directly into the HTML.

References

For advanced webpack-chain configuration see the repository: https://github.com/neutrinojs/webpack-chain

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Webpackprefetchpreloadcache bustingvue-cli
AutoHome Frontend
Written by

AutoHome Frontend

AutoHome Frontend Team

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.