如何在Grunt中通过动态参数循环执行JS压缩任务?
问题
我用Grunt JS把文件夹里的JS文件压缩到另一个文件夹,硬编码路径或者通过CLI传入版本号(比如执行grunt minify --vrn=11.3.0)时都能正常运行。我的ecommerce目录下有多个版本子目录(比如10.0.0、11.3.0),JS源文件路径是../../ecommerce/${version}/js/sitejs/,压缩后的目标路径是../../ecommerce/${version}/js/sitejs/u-min/。
我想实现:读取ecommerce下的所有版本目录名并动态传入任务,只需执行一次grunt minify命令,就能检查所有版本目录的文件变更并生成对应的压缩文件。注意:不能使用watch功能。
以下是当前的Gruntfile.js及执行输出,请问是否可行?
当前Gruntfile.js
module.exports = function (grunt) { let version = grunt.option('vrn'); let inputSiteFilePath = `../../ecommerce/${version}/js/sitejs/`; let targetSiteFilePath = `../../ecommerce/${version}/js/sitejs/u-min/`; let versionDirList = []; grunt.file.expand({ filter: 'isDirectory' }, '../../ecommerce/*').forEach(element => { versionDirList.push(element.split("/").pop()); }); console.log('versionDirList:',versionDirList); grunt.loadNpmTasks("grunt-contrib-uglify"); grunt.loadNpmTasks('grunt-changed'); grunt.initConfig({ pkg: grunt.file.readJSON("package.json"), uglify: { site: { options: { sourceMap: true, ie8: true, mangle: false, compress: { sequences: true, properties: true, dead_code: true, drop_debugger: true, unsafe: false, conditionals: true, comparisons: true, evaluate: true, booleans: true, loops: true, unused: true, hoist_funs: true, hoist_vars: false, if_return: true, join_vars: true, side_effects: true, drop_console: true, global_defs: {}, }, }, files: [ { cwd: inputSiteFilePath, src: ["*.js"], dest:targetSiteFilePath, expand: true, flatten: false, }, ], }, }, }); grunt.registerTask('minify', ['changed:uglify:site']); };
执行输出
PS D:\GitHubApplications\minify-app> grunt minify --vrn=11.3.0 versionDirList: [ '10.12.0', '11.3.0' ] Running "changed:uglify:site" (changed) task Running "uglify:site" (uglify) task >> 1 sourcemap created. >> 1 file created 16.8 kB → 11.3 kB Running "changed-postrun:uglify:site:1:D:\GitHubApplications\minify-app\node_modules\grunt-changed\.cache" (changed-postrun) task Done. PS D:\GitHubApplications\minify-app>
解决方案
完全可行,修改你的Gruntfile.js,通过动态生成每个版本对应的Uglify任务,再批量执行即可。修改后的代码如下:
module.exports = function (grunt) { // 读取所有版本目录 const versionDirList = grunt.file.expand({ filter: 'isDirectory' }, '../../ecommerce/*') .map(dir => dir.split("/").pop()); console.log('要处理的版本目录:', versionDirList); grunt.loadNpmTasks("grunt-contrib-uglify"); grunt.loadNpmTasks('grunt-changed'); // 初始化配置 const config = { pkg: grunt.file.readJSON("package.json"), uglify: {} }; // 为每个版本生成独立的Uglify任务 versionDirList.forEach(version => { const inputPath = `../../ecommerce/${version}/js/sitejs/`; const targetPath = `../../ecommerce/${version}/js/sitejs/u-min/`; config.uglify[`site_${version}`] = { options: { sourceMap: true, ie8: true, mangle: false, compress: { sequences: true, properties: true, dead_code: true, drop_debugger: true, unsafe: false, conditionals: true, comparisons: true, evaluate: true, booleans: true, loops: true, unused: true, hoist_funs: true, hoist_vars: false, if_return: true, join_vars: true, side_effects: true, drop_console: true, global_defs: {}, }, }, files: [{ cwd: inputPath, src: ["*.js"], dest: targetPath, expand: true, flatten: false, }] }; }); grunt.initConfig(config); // 构建minify任务的执行列表:包含所有版本的changed+uglify任务 const minifyTasks = versionDirList.map(version => `changed:uglify:site_${version}`); grunt.registerTask('minify', minifyTasks); };
关键改动说明
- 动态遍历版本目录:直接读取ecommerce下的所有版本目录,不再依赖CLI传入的
vrn参数 - 生成独立Uglify子任务:每个版本对应一个命名为
site_${version}的Uglify子任务,各自维护独立的源路径、目标路径和压缩配置 - 批量构建执行任务:将所有版本对应的
changed:uglify:site_${version}任务加入minify任务列表,执行grunt minify时会逐个处理每个版本的变更文件 - 独立缓存机制:grunt-changed会为每个子任务生成独立的缓存,确保每个版本的文件变更检查互不干扰
现在直接执行grunt minify,就能自动遍历所有版本目录,只处理有变更的JS文件并生成对应压缩文件。
内容的提问来源于stack exchange,提问作者Warrior
相关产品推荐
相关产品推荐

