Grunt项目:文件变更触发版本更新及资源缓存配置
Great question! Let's tackle your two core requirements step by step—first updating the project version based on file changes, then configuring your build pipeline to handle cache busting, versioned file names, and reference updates.
1. Update Project Version Automatically When Files Change
To bump your project's version (stored in package.json or a custom version file) whenever specific files are modified, you'll need two key Grunt plugins: grunt-contrib-watch to monitor file changes, and grunt-bump to increment version numbers cleanly.
Step 1: Install the Plugins
First, add them to your dev dependencies via npm:
npm install grunt-contrib-watch grunt-bump --save-dev
Step 2: Configure the Grunt Tasks
Drop this configuration into your Gruntfile.js:
module.exports = function(grunt) { grunt.initConfig({ // Load package.json to access the current version pkg: grunt.file.readJSON('package.json'), // Bump version settings bump: { options: { files: ['package.json'], // Target file to update version in updateConfigs: ['pkg'], // Sync the version with the pkg variable commit: false, // Disable auto-git commits if you don't need them push: false, createTag: false, // Version number pattern (matches semver: major.minor.patch) regExp: /^(\s*)"version": "(\d+)\.(\d+)\.(\d+)"/, } }, // Watch for file changes and trigger version bumps watch: { // Patch version for regular JS/CSS changes (e.g., 0.0.1 → 0.0.2) assets: { files: ['js/**/*.js', 'css/**/*.css'], tasks: ['bump:patch'], options: { spawn: false, interrupt: true, }, }, // Minor version for core code changes (e.g., 0.0.2 → 0.1.0) core: { files: ['src/core/**/*.js'], tasks: ['bump:minor'], options: { spawn: false, interrupt: true, }, }, // Add a major version target here if you need to handle breaking changes } }); // Load the plugins grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-bump'); // Default task: start watching for file changes grunt.registerTask('default', ['watch']); };
How It Works
grunt-bumphandles incrementing the version inpackage.json(adjust thefilesoption if you use a custom version file instead).grunt-contrib-watchmonitors specific file groups:- Regular asset changes trigger a patch version bump.
- Core code changes trigger a minor version bump.
- Swap
bump:patch/bump:minorwithbump:majorfor breaking changes that require a full version reset (e.g., 0.1.0 → 1.0.0).
2. Cache Busting, Versioned File Names, and Reference Updates
For this part, we'll use grunt-contrib-concat to merge files, grunt-processhtml to update cache-related meta tags in index.html, and grunt-string-replace to swap old file references with versioned ones. We'll leverage the version from package.json to name merged files dynamically.
Step 1: Install Required Plugins
npm install grunt-contrib-concat grunt-processhtml grunt-string-replace --save-dev
Step 2: Configure the Build Pipeline
Update your Gruntfile.js with these tasks:
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), // Concatenate files with versioned output names concat: { js: { files: { // Merge js/last.js + js/new.js → js/lastAndNew-<%= pkg.version %>.js 'js/lastAndNew-<%= pkg.version %>.js': ['js/last.js', 'js/new.js'], // Merge js/last.js + all files in js/new/ → js/lastAndAllNews-<%= pkg.version %>.js 'js/lastAndAllNews-<%= pkg.version %>.js': ['js/last.js', 'js/new/*.js'] } }, css: { // Add CSS concatenation if needed files: { 'css/bundle-<%= pkg.version %>.css': ['css/**/*.css'] } } }, // Update cache control meta tags in index.html processhtml: { dist: { options: { data: { version: '<%= pkg.version %>' } }, files: { 'index.html': ['index.html'] } } }, // Replace old file references with versioned ones in index.html 'string-replace': { dist: { files: { 'index.html': 'index.html' }, options: { replacements: [ { pattern: /js\/lastAndNew\.js/g, replacement: 'js/lastAndNew-<%= pkg.version %>.js' }, { pattern: /js\/lastAndAllNews\.js/g, replacement: 'js/lastAndAllNews-<%= pkg.version %>.js' }, { pattern: /css\/bundle\.css/g, replacement: 'css/bundle-<%= pkg.version %>.css' } ] } } } }); // Load the plugins grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-processhtml'); grunt.loadNpmTasks('grunt-string-replace'); // Build task: run all steps in sequence grunt.registerTask('build', ['concat', 'processhtml', 'string-replace']); };
Step 3: Prepare index.html for Updates
Add a cache meta tag with a placeholder for the version, and use base file names for your references (these will be replaced automatically):
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <!-- Cache control with dynamic version --> <meta http-equiv="Cache-Control" content="max-age=31536000, public, version=<!-- @echo version -->"> <link rel="stylesheet" href="css/bundle.css"> </head> <body> <script src="js/lastAndNew.js"></script> </body> </html>
How It Works
- Concatenation:
grunt-contrib-concatmerges your files and uses<%= pkg.version %>to generate versioned output names (e.g.,js/lastAndNew-0.0.2.js). - Cache Meta Update:
grunt-processhtmlreplaces the<!-- @echo version -->placeholder with the current project version, ensuring browsers recognize a new cache entry. - Reference Updates:
grunt-string-replaceswaps unversioned file paths (likejs/lastAndNew.js) with their versioned counterparts inindex.html.
Optional: Tie It All Together
To auto-run the build after a version bump, update your watch task to include the build task:
watch: { assets: { files: ['js/**/*.js', 'css/**/*.css'], tasks: ['bump:patch', 'build'], // Add build here options: { spawn: false, interrupt: true, }, }, // ... other watch targets }
内容的提问来源于stack exchange,提问作者Enmanuel Saravia

