Gulp 使用 gulp-rev 处理一组文件
Gulp handle an array of files with gulp-rev
上下文
我有一个gulpfile.js
。它基本上将两个带有 js 文件的文件夹连接到两个文件以导出到 dist 文件夹。它还添加了缓存破坏器和用于生产的丑化版本。
//gulpfile.js
const gulp = require('gulp');
const sass = require('gulp-sass');
const concat = require('gulp-concat');
const rename = require('gulp-rename');
const maps = require('gulp-sourcemaps');
const uglify = require('gulp-uglify');
const gulpif = require('gulp-if');
const inlineCss = require('gulp-inline-css');
const jsValidate = require('gulp-jsvalidate');
const notify = require('gulp-notify');
const rev = require('gulp-rev');
const fs = require("fs");
const del = require('del');
const distFolder = './myapp/dist/';
/* Concat all scripts and add cache buster */
gulp.task('app_concatScripts', (done) => {
/*first remove old app.js files */
return del([distFolder + "app-*.{js,map}"])
.then(paths => {
/*Concat files with sourcemaps, hash them and write to manifest*/
return gulp.src("./myapp/js/source-app/*.js")
.pipe(maps.init())
.pipe(concat({
path: "app.js",
cwd: '',
newLine: '; \n'
}))
.pipe(gulp.dest(distFolder))
.pipe(rev())
.pipe(maps.write('./'))
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
base: distFolder,
merge: true
}))
.pipe(gulp.dest(distFolder));
});
});
/* Minify scripts and add cache buster */
gulp.task('app_minifyScripts', (done) => {
return gulp.src(distFolder + "app.js", {
allowEmpty: true
})
.pipe(uglify())
.on('error', notify.onError((error) => {
console.log(error);
return error.message + ' in ' + error.fileName;
}))
.pipe(rename("app.min.js"))
.pipe(rev())
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
base: distFolder,
merge: true
}))
.pipe(gulp.dest(distFolder));
});
/* Concat all scripts and add cache buster, this function is exactly the same as app_concatScripts */
gulp.task('main_concatScripts', (done) => {
/*Concat files with sourcemaps, hash them and write to manifest*/
return del(["./myapp/dist/main-*.{js,map}"])
.then(paths => {
return gulp.src("./myapp/js/source-main/*.js")
.pipe(maps.init())
.pipe(concat({
path: "main.js",
cwd: '',
newLine: '; \n'
}))
.pipe(gulp.dest(distFolder))
.pipe(rev())
.pipe(maps.write('./'))
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
base: distFolder,
merge: true
}))
.pipe(gulp.dest(distFolder));
});
});
/* Minify scripts and add cache buster, this function is the same as app_minifyScripts */
gulp.task('main_minifyScripts', (done) => {
return gulp.src("./myapp/dist/main.js")
.pipe(uglify())
.on('error', notify.onError((error) => {
console.log(error);
return error.message + ' in ' + error.fileName;
}))
.pipe(rename("main.min.js"))
.pipe(rev())
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
base: distFolder,
merge: true
}))
.pipe(gulp.dest(distFolder));
});
/* watch task */
gulp.task('watch', (done) => {
gulp.watch('./myapp/js/source-app/*.js', gulp.series('app_concatScripts', 'app_minifyScripts'));
gulp.watch('./myapp/js/source-main/*.js', gulp.series('main_concatScripts', 'main_minifyScripts'));
done();
});
gulp.task('default', gulp.series('main_concatScripts', 'main_minifyScripts', 'app_concatScripts', 'app_minifyScripts', 'watch'));
输出
gulpfile.js
有效。它构建了一个 rev-manifest.json
像这样:
{
"app.js": "app-234318a58d.js",
"app.min.js": "app-7788fee7f3.min.js",
"main.js": "main-60788c863c.js",
"main.min.js": "main-1e92517890.min.js",
"style.css": "style-296f22c598.css",
"admin.css": "admin-a3742ed2f6.css",
}
问题
为了让它工作,我为每个 js 文件复制了 _concatScripts
和 _minifyScripts
任务:app.js
和 main.js
。使 gulp 文件变得不必要的大且难以维护。
我试过的
我尝试使用数组来定义脚本源文件和输出名称。这是行不通的,因为循环块中的代码不会等待前一个块准备就绪。所以 minify 任务有时会失败,因为原始 js 文件尚不存在,有时 rev-manifest.json
会被先前的代码块覆盖。所以它不再是真正的 gulp 系列了。执行此类操作的最佳做法是什么?
const scripts = [{
name: 'app',
source: './myapp/js/source-app/*.js'
}, {
name: 'main',
source: './myapp/js/source-main/*.js'
}];
/* Concat all scripts and add cache buster */
gulp.task('concatScripts', (done) => {
for (var i = 0; i < scripts.length; i++) {
var script = scripts[i];
del([distFolder + script.name + "-*.{js,map}"])
.then(paths => {
/*Concat files with sourcemaps, hash them and write to manifest*/
gulp.src(script.source)
.pipe(maps.init())
.pipe(concat({
path: script.name + ".js",
cwd: '',
newLine: '; \n'
}))
.pipe(gulp.dest(distFolder))
.pipe(rev())
.pipe(maps.write('./'))
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
base: distFolder,
merge: true
}))
.pipe(gulp.dest(distFolder));
});
}
});
/* Minify scripts and add cache buster */
gulp.task('minifyScripts', (done) => {
for (var i = 0; i < scripts.length; i++) {
var script = scripts[i];
gulp.src(distFolder + script.name + ".js", {
allowEmpty: true
})
.pipe(uglify())
.on('error', notify.onError((error) => {
console.log(error);
return error.message + ' in ' + error.fileName;
}))
.pipe(rename(script.name + ".min.js"))
.pipe(rev())
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
base: distFolder,
merge: true
}))
.pipe(gulp.dest(distFolder));
}
});
/* watch task */
gulp.task('watch', (done) => {
gulp.watch(['./myapp/js/source-app/*.js', './myapp/js/source-main/*.js'], gulp.series('concatScripts', 'minifyScripts'));
done();
});
gulp.task('default', gulp.series('concatScripts', 'minifyScripts', 'watch'));
更新
我的 gulp 文件现在看起来像这样:
//gulpfile.js
const gulp = require('gulp');
const sass = require('gulp-sass');
const concat = require('gulp-concat');
const rename = require('gulp-rename');
const maps = require('gulp-sourcemaps');
const uglify = require('gulp-uglify');
const gulpif = require('gulp-if');
const inlineCss = require('gulp-inline-css');
const jsValidate = require('gulp-jsvalidate');
const notify = require('gulp-notify');
const rev = require('gulp-rev');
const fs = require("fs");
const del = require('del');
/* Concat all scripts and add cache buster */
const distFolder = './myapp/dist/';
function concatTask(opts) {
const taskName = opts.name + '_concatScripts';
gulp.task(taskName, (done) => {
/*Concat files with sourcemaps, hash them and write to manifest*/
return del(opts.del)
.then(paths => {
return gulp.src(opts.source)
.pipe(maps.init())
.pipe(concat({
'path': opts.name + '.js',
'cwd': '',
'newLine': '; \n'
}))
.pipe(gulp.dest(distFolder))
.pipe(rev())
.pipe(maps.write('./'))
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
'base': distFolder,
'merge': true
}))
.pipe(gulp.dest(distFolder));
});
});
return taskName;
}
function minifyTask(opts) {
const taskName = opts.name + '_minifyScripts';
gulp.task(taskName, (done) => {
return gulp.src(distFolder + opts.name + '.js', opts.sourceParams)
.pipe(uglify())
.on('error', notify.onError((error) => {
console.log(error);
return error.message + ' in ' + error.fileName;
}))
.pipe(rename(opts.name + '.min.js'))
.pipe(rev())
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
'base': distFolder,
'merge': true
}))
.pipe(gulp.dest(distFolder));
});
return taskName;
}
const taskOptions = [{
'name': 'main',
'source': './myapp/js/source-main/*.js',
'sourceParams': {
'allowEmpty': false
},
'del': ['./myapp/dist/main-*.{js,map}']
}, {
'name': 'app',
'source': './myapp/js/source-app/*.js',
'sourceParams': {
'allowEmpty': false
},
'del': ['./myapp/dist/app-*.{js,map}']
},
];
const taskNames = taskOptions.map(opts => {
return [concatTask(opts), minifyTask(opts)];
});
/* equivalent to defining tasks and assigning:
* var taskNames = [
* ['main_concatScripts', 'main_minifyScripts'],
* ['app_concatScripts', 'app_minifyScripts']
* ];
*/
gulp.task('watch', (done) => {
taskOptions.forEach((opts, i) => {
gulp.watch(opts.source, gulp.series.apply(gulp, taskNames[i]));
});
done();
});
/* equivalent to:
* gulp.task('watch', (done) => {
* gulp.watch('./myapp/js/source-main/*.js', gulp.series('main_concatScripts', 'main_minifyScripts'));
* gulp.watch('./myapp/js/source-app/*.js', gulp.series('app_concatScripts', 'app_minifyScripts'));
* done();
* });
*/
const allTaskNames = taskNames.reduce((arr, names) => arr.concat(names), []); // flatmap the task names into a single array
// console.log(allTaskNames.concat(['watch']));
/* equivalent to:
* let allTaskNames = ['main_concatScripts', 'main_minifyScripts', 'app_concatScripts', 'app_minifyScripts'];
*/
gulp.task('default', gulp.series.apply(gulp, allTaskNames.concat(['styles', 'watch'])));
/* equivalent to:
* gulp.task('default', gulp.series('main_concatScripts', 'main_minifyScripts', 'app_concatScripts', 'app_minifyScripts', 'watch'));
*/
动态任务创建者工作。不幸的是,缩小任务在连接任务完成之前就开始了。我收到以下错误,添加 allowEmpty 选项确实有效,但随后错误的串联文件被缩小:
[12:57:19] Using gulpfile /repo/myapp/gulpfile.js
[12:57:19] Starting 'default'...
[12:57:19] Starting 'main_concatScripts'...
[12:57:19] Finished 'main_concatScripts' after 47 ms
[12:57:19] Starting 'main_minifyScripts'...
[12:57:19] 'main_minifyScripts' errored after 11 ms
[12:57:19] Error: File not found with singular glob: /repo/myapp/dist/main.js (if this was purposeful, use `allowEmpty` option)
如果只是保留代码的问题DRY,您可以编写两个包含 WET 代码泛化的函数:
concatTask()
minifyTask()
这些函数中的每一个都应该定义一个 gulp 任务和 return 一个内部生成的任务名称。
function concatTask(opts) {
const taskName = opts.name + '_concatScripts';
gulp.task(taskName, (done) => {
/*Concat files with sourcemaps, hash them and write to manifest*/
return del(opts.del)
.then(paths => {
return gulp.src(opts.source)
.pipe(maps.init())
.pipe(concat({
'path': opts.name + '.js',
'cwd': '',
'newLine': '; \n'
}))
.pipe(gulp.dest(distFolder))
.pipe(rev())
.pipe(maps.write('./'))
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
'base': distFolder,
'merge': true
}))
.pipe(gulp.dest(distFolder));
});
});
return taskName;
}
function minifyTask(opts) {
const taskName = opts.name + '_minifyScripts';
gulp.task(taskName, (done) => {
return gulp.src(opts.source, opts.sourceParams)
.pipe(uglify())
.on('error', notify.onError((error) => {
console.log(error);
return error.message + ' in ' + error.fileName;
}))
.pipe(rename(opts.name + '.min.js'))
.pipe(rev())
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
'base': distFolder,
'merge': true
}))
.pipe(gulp.dest(distFolder));
});
return taskName;
}
任务定义、监视和系列执行可以程序化如下:
const taskOptions = [
{
'name': 'main',
'source': './myapp/js/source-main/*.js',
'sourceParams': {},
'del': ['./myapp/dist/main-*.{js,map}']
},
{
'name': 'app',
'source': './myapp/js/source-app/*.js',
'sourceParams': { 'allowEmpty': true },
'del': ['./myapp/dist/app-*.{js,map}']
}
];
const taskNames = taskOptions.map(opts => {
return [concatTask(opts), minifyTask(opts)];
});
/* equivalent to defining tasks and assigning:
* var taskNames = [
* ['main_concatScripts', 'main_minifyScripts'],
* ['app_concatScripts', 'app_minifyScripts']
* ];
*/
gulp.task('watch', (done) => {
taskOptions.forEach((opts, i) => {
gulp.watch(opts.source, gulp.series.apply(gulp, taskNames[i]));
});
done();
});
/* equivalent to:
* gulp.task('watch', (done) => {
* gulp.watch('./myapp/js/source-main/*.js', gulp.series('main_concatScripts', 'main_minifyScripts'));
* gulp.watch('./myapp/js/source-app/*.js', gulp.series('app_concatScripts', 'app_minifyScripts'));
* done();
* });
*/
const allTaskNames = taskNames.reduce((arr, names) => arr.concat(names), []); // flatmap the task names into a single array
/* equivalent to:
* let allTaskNames = ['main_concatScripts', 'main_minifyScripts', 'app_concatScripts', 'app_minifyScripts'];
*/
gulp.task('default', gulp.series.apply(gulp, allTaskNames.concat('watch')));
/* equivalent to:
* gulp.task('default', gulp.series('main_concatScripts', 'main_minifyScripts', 'app_concatScripts', 'app_minifyScripts', 'watch'));
*/
除了错误,一切都将按照原始代码中的相同顺序发生。
你最终得到的东西并不是特别不言自明。了解 Function.prototype.apply() 肯定会有帮助。
就个人而言,我会在部署的代码中留下 "equivalent to:..." 注释,以提醒自己(并向他人解释)实际发生的事情。
所以感谢 Roamer 如果想添加另一个任务来删除 js 文件。所以一个任务可以等待另一个任务完成。这是 gulp 文件:
//gulpfile.js
const gulp = require('gulp');
const sass = require('gulp-sass');
const concat = require('gulp-concat');
const rename = require('gulp-rename');
const maps = require('gulp-sourcemaps');
const uglify = require('gulp-uglify');
const gulpif = require('gulp-if');
const inlineCss = require('gulp-inline-css');
const jsValidate = require('gulp-jsvalidate');
const notify = require('gulp-notify');
const rev = require('gulp-rev');
const fs = require("fs");
const del = require('del');
/* Concat all scripts and add cache buster */
const distFolder = './myapp/dist/';
function delTask(opts) {
const taskName = opts.name + '_delScripts';
gulp.task(taskName, (done) => {
/*Delete old files*/
return del(opts.del)
});
return taskName;
}
function concatTask(opts) {
const taskName = opts.name + '_concatScripts';
gulp.task(taskName, (done) => {
/*Concat files with sourcemaps, hash them and write to manifest*/
return gulp.src(opts.source)
.pipe(maps.init())
.pipe(concat({
'path': opts.name + '.js',
'cwd': '',
'newLine': '; \n'
}))
.pipe(gulp.dest(distFolder))
.pipe(rev())
.pipe(maps.write('./'))
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
'base': distFolder,
'merge': true
}))
.pipe(gulp.dest(distFolder));
});
return taskName;
}
function minifyTask(opts) {
const taskName = opts.name + '_minifyScripts';
gulp.task(taskName, (done) => {
return gulp.src(distFolder + opts.name + '.js', opts.sourceParams)
.pipe(uglify())
.on('error', notify.onError((error) => {
console.log(error);
return error.message + ' in ' + error.fileName;
}))
.pipe(rename(opts.name + '.min.js'))
.pipe(rev())
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
'base': distFolder,
'merge': true
}))
.pipe(gulp.dest(distFolder));
});
return taskName;
}
const taskOptions = [{
'name': 'main',
'source': './myapp/js/source-main/*.js',
'sourceParams': {
'allowEmpty': false
},
'del': ['./myapp/dist/main-*.{js,map}']
}, {
'name': 'app',
'source': './myapp/js/source-app/*.js',
'sourceParams': {
'allowEmpty': false
},
'del': ['./myapp/dist/app-*.{js,map}']
}];
const taskNames = taskOptions.map(opts => {
return [delTask(opts), concatTask(opts), minifyTask(opts)];
});
/* equivalent to defining tasks and assigning:
* var taskNames = [
* ['main_delScripts', 'main_concatScripts', 'main_minifyScripts'],
* ['app_delScripts', 'app_concatScripts', 'app_minifyScripts']
* ];
*/
gulp.task('watch', (done) => {
taskOptions.forEach((opts, i) => {
gulp.watch(opts.source, gulp.series.apply(gulp, taskNames[i]));
});
done();
});
/* equivalent to:
* gulp.task('watch', (done) => {
* gulp.watch('./myapp/js/source-main/*.js', gulp.series('main_delScripts', 'main_concatScripts', 'main_minifyScripts'));
* gulp.watch('./myapp/js/source-app/*.js', gulp.series('app_delScripts', 'app_concatScripts', 'app_minifyScripts'));
* done();
* });
*/
const allTaskNames = taskNames.reduce((arr, names) => arr.concat(names), []); // flatmap the task names into a single array
// console.log(allTaskNames.concat(['watch']));
/* equivalent to:
* let allTaskNames = ['main_delScripts', 'main_concatScripts', 'main_minifyScripts', 'app_delScripts', 'app_concatScripts', 'app_minifyScripts'];
*/
gulp.task('default', gulp.series.apply(gulp, allTaskNames.concat(['styles', 'watch'])));
/* equivalent to:
* gulp.task('default', gulp.series('main_delScripts', 'main_concatScripts', 'main_minifyScripts', 'app_delScripts', 'app_concatScripts', 'app_minifyScripts', 'watch'));
*/
并且输出:
[16:40:31] Using gulpfile gulpfile.js
[16:40:31] Starting 'default'...
[16:40:31] Starting 'main_delScripts'...
[16:40:31] Finished 'main_delScripts' after 29 ms
[16:40:31] Starting 'main_concatScripts'...
[16:40:31] Finished 'main_concatScripts' after 84 ms
[16:40:31] Starting 'main_minifyScripts'...
[16:40:34] Finished 'main_minifyScripts' after 2.45 s
[16:40:34] Starting 'app_delScripts'...
[16:40:34] Finished 'app_delScripts' after 941 μs
[16:40:34] Starting 'app_concatScripts'...
[16:40:34] Finished 'app_concatScripts' after 58 ms
[16:40:34] Starting 'app_minifyScripts'...
[16:40:37] Finished 'app_minifyScripts' after 3.12 s
[16:40:37] Starting 'styles'...
[16:40:37] Finished 'styles' after 215 ms
[16:40:37] Starting 'watch'...
[16:40:37] Finished 'watch' after 19 ms
[16:40:37] Finished 'default' after 6.04 s
上下文
我有一个gulpfile.js
。它基本上将两个带有 js 文件的文件夹连接到两个文件以导出到 dist 文件夹。它还添加了缓存破坏器和用于生产的丑化版本。
//gulpfile.js
const gulp = require('gulp');
const sass = require('gulp-sass');
const concat = require('gulp-concat');
const rename = require('gulp-rename');
const maps = require('gulp-sourcemaps');
const uglify = require('gulp-uglify');
const gulpif = require('gulp-if');
const inlineCss = require('gulp-inline-css');
const jsValidate = require('gulp-jsvalidate');
const notify = require('gulp-notify');
const rev = require('gulp-rev');
const fs = require("fs");
const del = require('del');
const distFolder = './myapp/dist/';
/* Concat all scripts and add cache buster */
gulp.task('app_concatScripts', (done) => {
/*first remove old app.js files */
return del([distFolder + "app-*.{js,map}"])
.then(paths => {
/*Concat files with sourcemaps, hash them and write to manifest*/
return gulp.src("./myapp/js/source-app/*.js")
.pipe(maps.init())
.pipe(concat({
path: "app.js",
cwd: '',
newLine: '; \n'
}))
.pipe(gulp.dest(distFolder))
.pipe(rev())
.pipe(maps.write('./'))
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
base: distFolder,
merge: true
}))
.pipe(gulp.dest(distFolder));
});
});
/* Minify scripts and add cache buster */
gulp.task('app_minifyScripts', (done) => {
return gulp.src(distFolder + "app.js", {
allowEmpty: true
})
.pipe(uglify())
.on('error', notify.onError((error) => {
console.log(error);
return error.message + ' in ' + error.fileName;
}))
.pipe(rename("app.min.js"))
.pipe(rev())
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
base: distFolder,
merge: true
}))
.pipe(gulp.dest(distFolder));
});
/* Concat all scripts and add cache buster, this function is exactly the same as app_concatScripts */
gulp.task('main_concatScripts', (done) => {
/*Concat files with sourcemaps, hash them and write to manifest*/
return del(["./myapp/dist/main-*.{js,map}"])
.then(paths => {
return gulp.src("./myapp/js/source-main/*.js")
.pipe(maps.init())
.pipe(concat({
path: "main.js",
cwd: '',
newLine: '; \n'
}))
.pipe(gulp.dest(distFolder))
.pipe(rev())
.pipe(maps.write('./'))
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
base: distFolder,
merge: true
}))
.pipe(gulp.dest(distFolder));
});
});
/* Minify scripts and add cache buster, this function is the same as app_minifyScripts */
gulp.task('main_minifyScripts', (done) => {
return gulp.src("./myapp/dist/main.js")
.pipe(uglify())
.on('error', notify.onError((error) => {
console.log(error);
return error.message + ' in ' + error.fileName;
}))
.pipe(rename("main.min.js"))
.pipe(rev())
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
base: distFolder,
merge: true
}))
.pipe(gulp.dest(distFolder));
});
/* watch task */
gulp.task('watch', (done) => {
gulp.watch('./myapp/js/source-app/*.js', gulp.series('app_concatScripts', 'app_minifyScripts'));
gulp.watch('./myapp/js/source-main/*.js', gulp.series('main_concatScripts', 'main_minifyScripts'));
done();
});
gulp.task('default', gulp.series('main_concatScripts', 'main_minifyScripts', 'app_concatScripts', 'app_minifyScripts', 'watch'));
输出
gulpfile.js
有效。它构建了一个 rev-manifest.json
像这样:
{
"app.js": "app-234318a58d.js",
"app.min.js": "app-7788fee7f3.min.js",
"main.js": "main-60788c863c.js",
"main.min.js": "main-1e92517890.min.js",
"style.css": "style-296f22c598.css",
"admin.css": "admin-a3742ed2f6.css",
}
问题
为了让它工作,我为每个 js 文件复制了 _concatScripts
和 _minifyScripts
任务:app.js
和 main.js
。使 gulp 文件变得不必要的大且难以维护。
我试过的
我尝试使用数组来定义脚本源文件和输出名称。这是行不通的,因为循环块中的代码不会等待前一个块准备就绪。所以 minify 任务有时会失败,因为原始 js 文件尚不存在,有时 rev-manifest.json
会被先前的代码块覆盖。所以它不再是真正的 gulp 系列了。执行此类操作的最佳做法是什么?
const scripts = [{
name: 'app',
source: './myapp/js/source-app/*.js'
}, {
name: 'main',
source: './myapp/js/source-main/*.js'
}];
/* Concat all scripts and add cache buster */
gulp.task('concatScripts', (done) => {
for (var i = 0; i < scripts.length; i++) {
var script = scripts[i];
del([distFolder + script.name + "-*.{js,map}"])
.then(paths => {
/*Concat files with sourcemaps, hash them and write to manifest*/
gulp.src(script.source)
.pipe(maps.init())
.pipe(concat({
path: script.name + ".js",
cwd: '',
newLine: '; \n'
}))
.pipe(gulp.dest(distFolder))
.pipe(rev())
.pipe(maps.write('./'))
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
base: distFolder,
merge: true
}))
.pipe(gulp.dest(distFolder));
});
}
});
/* Minify scripts and add cache buster */
gulp.task('minifyScripts', (done) => {
for (var i = 0; i < scripts.length; i++) {
var script = scripts[i];
gulp.src(distFolder + script.name + ".js", {
allowEmpty: true
})
.pipe(uglify())
.on('error', notify.onError((error) => {
console.log(error);
return error.message + ' in ' + error.fileName;
}))
.pipe(rename(script.name + ".min.js"))
.pipe(rev())
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
base: distFolder,
merge: true
}))
.pipe(gulp.dest(distFolder));
}
});
/* watch task */
gulp.task('watch', (done) => {
gulp.watch(['./myapp/js/source-app/*.js', './myapp/js/source-main/*.js'], gulp.series('concatScripts', 'minifyScripts'));
done();
});
gulp.task('default', gulp.series('concatScripts', 'minifyScripts', 'watch'));
更新
我的 gulp 文件现在看起来像这样:
//gulpfile.js
const gulp = require('gulp');
const sass = require('gulp-sass');
const concat = require('gulp-concat');
const rename = require('gulp-rename');
const maps = require('gulp-sourcemaps');
const uglify = require('gulp-uglify');
const gulpif = require('gulp-if');
const inlineCss = require('gulp-inline-css');
const jsValidate = require('gulp-jsvalidate');
const notify = require('gulp-notify');
const rev = require('gulp-rev');
const fs = require("fs");
const del = require('del');
/* Concat all scripts and add cache buster */
const distFolder = './myapp/dist/';
function concatTask(opts) {
const taskName = opts.name + '_concatScripts';
gulp.task(taskName, (done) => {
/*Concat files with sourcemaps, hash them and write to manifest*/
return del(opts.del)
.then(paths => {
return gulp.src(opts.source)
.pipe(maps.init())
.pipe(concat({
'path': opts.name + '.js',
'cwd': '',
'newLine': '; \n'
}))
.pipe(gulp.dest(distFolder))
.pipe(rev())
.pipe(maps.write('./'))
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
'base': distFolder,
'merge': true
}))
.pipe(gulp.dest(distFolder));
});
});
return taskName;
}
function minifyTask(opts) {
const taskName = opts.name + '_minifyScripts';
gulp.task(taskName, (done) => {
return gulp.src(distFolder + opts.name + '.js', opts.sourceParams)
.pipe(uglify())
.on('error', notify.onError((error) => {
console.log(error);
return error.message + ' in ' + error.fileName;
}))
.pipe(rename(opts.name + '.min.js'))
.pipe(rev())
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
'base': distFolder,
'merge': true
}))
.pipe(gulp.dest(distFolder));
});
return taskName;
}
const taskOptions = [{
'name': 'main',
'source': './myapp/js/source-main/*.js',
'sourceParams': {
'allowEmpty': false
},
'del': ['./myapp/dist/main-*.{js,map}']
}, {
'name': 'app',
'source': './myapp/js/source-app/*.js',
'sourceParams': {
'allowEmpty': false
},
'del': ['./myapp/dist/app-*.{js,map}']
},
];
const taskNames = taskOptions.map(opts => {
return [concatTask(opts), minifyTask(opts)];
});
/* equivalent to defining tasks and assigning:
* var taskNames = [
* ['main_concatScripts', 'main_minifyScripts'],
* ['app_concatScripts', 'app_minifyScripts']
* ];
*/
gulp.task('watch', (done) => {
taskOptions.forEach((opts, i) => {
gulp.watch(opts.source, gulp.series.apply(gulp, taskNames[i]));
});
done();
});
/* equivalent to:
* gulp.task('watch', (done) => {
* gulp.watch('./myapp/js/source-main/*.js', gulp.series('main_concatScripts', 'main_minifyScripts'));
* gulp.watch('./myapp/js/source-app/*.js', gulp.series('app_concatScripts', 'app_minifyScripts'));
* done();
* });
*/
const allTaskNames = taskNames.reduce((arr, names) => arr.concat(names), []); // flatmap the task names into a single array
// console.log(allTaskNames.concat(['watch']));
/* equivalent to:
* let allTaskNames = ['main_concatScripts', 'main_minifyScripts', 'app_concatScripts', 'app_minifyScripts'];
*/
gulp.task('default', gulp.series.apply(gulp, allTaskNames.concat(['styles', 'watch'])));
/* equivalent to:
* gulp.task('default', gulp.series('main_concatScripts', 'main_minifyScripts', 'app_concatScripts', 'app_minifyScripts', 'watch'));
*/
动态任务创建者工作。不幸的是,缩小任务在连接任务完成之前就开始了。我收到以下错误,添加 allowEmpty 选项确实有效,但随后错误的串联文件被缩小:
[12:57:19] Using gulpfile /repo/myapp/gulpfile.js
[12:57:19] Starting 'default'...
[12:57:19] Starting 'main_concatScripts'...
[12:57:19] Finished 'main_concatScripts' after 47 ms
[12:57:19] Starting 'main_minifyScripts'...
[12:57:19] 'main_minifyScripts' errored after 11 ms
[12:57:19] Error: File not found with singular glob: /repo/myapp/dist/main.js (if this was purposeful, use `allowEmpty` option)
如果只是保留代码的问题DRY,您可以编写两个包含 WET 代码泛化的函数:
concatTask()
minifyTask()
这些函数中的每一个都应该定义一个 gulp 任务和 return 一个内部生成的任务名称。
function concatTask(opts) {
const taskName = opts.name + '_concatScripts';
gulp.task(taskName, (done) => {
/*Concat files with sourcemaps, hash them and write to manifest*/
return del(opts.del)
.then(paths => {
return gulp.src(opts.source)
.pipe(maps.init())
.pipe(concat({
'path': opts.name + '.js',
'cwd': '',
'newLine': '; \n'
}))
.pipe(gulp.dest(distFolder))
.pipe(rev())
.pipe(maps.write('./'))
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
'base': distFolder,
'merge': true
}))
.pipe(gulp.dest(distFolder));
});
});
return taskName;
}
function minifyTask(opts) {
const taskName = opts.name + '_minifyScripts';
gulp.task(taskName, (done) => {
return gulp.src(opts.source, opts.sourceParams)
.pipe(uglify())
.on('error', notify.onError((error) => {
console.log(error);
return error.message + ' in ' + error.fileName;
}))
.pipe(rename(opts.name + '.min.js'))
.pipe(rev())
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
'base': distFolder,
'merge': true
}))
.pipe(gulp.dest(distFolder));
});
return taskName;
}
任务定义、监视和系列执行可以程序化如下:
const taskOptions = [
{
'name': 'main',
'source': './myapp/js/source-main/*.js',
'sourceParams': {},
'del': ['./myapp/dist/main-*.{js,map}']
},
{
'name': 'app',
'source': './myapp/js/source-app/*.js',
'sourceParams': { 'allowEmpty': true },
'del': ['./myapp/dist/app-*.{js,map}']
}
];
const taskNames = taskOptions.map(opts => {
return [concatTask(opts), minifyTask(opts)];
});
/* equivalent to defining tasks and assigning:
* var taskNames = [
* ['main_concatScripts', 'main_minifyScripts'],
* ['app_concatScripts', 'app_minifyScripts']
* ];
*/
gulp.task('watch', (done) => {
taskOptions.forEach((opts, i) => {
gulp.watch(opts.source, gulp.series.apply(gulp, taskNames[i]));
});
done();
});
/* equivalent to:
* gulp.task('watch', (done) => {
* gulp.watch('./myapp/js/source-main/*.js', gulp.series('main_concatScripts', 'main_minifyScripts'));
* gulp.watch('./myapp/js/source-app/*.js', gulp.series('app_concatScripts', 'app_minifyScripts'));
* done();
* });
*/
const allTaskNames = taskNames.reduce((arr, names) => arr.concat(names), []); // flatmap the task names into a single array
/* equivalent to:
* let allTaskNames = ['main_concatScripts', 'main_minifyScripts', 'app_concatScripts', 'app_minifyScripts'];
*/
gulp.task('default', gulp.series.apply(gulp, allTaskNames.concat('watch')));
/* equivalent to:
* gulp.task('default', gulp.series('main_concatScripts', 'main_minifyScripts', 'app_concatScripts', 'app_minifyScripts', 'watch'));
*/
除了错误,一切都将按照原始代码中的相同顺序发生。
你最终得到的东西并不是特别不言自明。了解 Function.prototype.apply() 肯定会有帮助。
就个人而言,我会在部署的代码中留下 "equivalent to:..." 注释,以提醒自己(并向他人解释)实际发生的事情。
所以感谢 Roamer 如果想添加另一个任务来删除 js 文件。所以一个任务可以等待另一个任务完成。这是 gulp 文件:
//gulpfile.js
const gulp = require('gulp');
const sass = require('gulp-sass');
const concat = require('gulp-concat');
const rename = require('gulp-rename');
const maps = require('gulp-sourcemaps');
const uglify = require('gulp-uglify');
const gulpif = require('gulp-if');
const inlineCss = require('gulp-inline-css');
const jsValidate = require('gulp-jsvalidate');
const notify = require('gulp-notify');
const rev = require('gulp-rev');
const fs = require("fs");
const del = require('del');
/* Concat all scripts and add cache buster */
const distFolder = './myapp/dist/';
function delTask(opts) {
const taskName = opts.name + '_delScripts';
gulp.task(taskName, (done) => {
/*Delete old files*/
return del(opts.del)
});
return taskName;
}
function concatTask(opts) {
const taskName = opts.name + '_concatScripts';
gulp.task(taskName, (done) => {
/*Concat files with sourcemaps, hash them and write to manifest*/
return gulp.src(opts.source)
.pipe(maps.init())
.pipe(concat({
'path': opts.name + '.js',
'cwd': '',
'newLine': '; \n'
}))
.pipe(gulp.dest(distFolder))
.pipe(rev())
.pipe(maps.write('./'))
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
'base': distFolder,
'merge': true
}))
.pipe(gulp.dest(distFolder));
});
return taskName;
}
function minifyTask(opts) {
const taskName = opts.name + '_minifyScripts';
gulp.task(taskName, (done) => {
return gulp.src(distFolder + opts.name + '.js', opts.sourceParams)
.pipe(uglify())
.on('error', notify.onError((error) => {
console.log(error);
return error.message + ' in ' + error.fileName;
}))
.pipe(rename(opts.name + '.min.js'))
.pipe(rev())
.pipe(gulp.dest(distFolder))
.pipe(rev.manifest(distFolder + 'rev-manifest.json', {
'base': distFolder,
'merge': true
}))
.pipe(gulp.dest(distFolder));
});
return taskName;
}
const taskOptions = [{
'name': 'main',
'source': './myapp/js/source-main/*.js',
'sourceParams': {
'allowEmpty': false
},
'del': ['./myapp/dist/main-*.{js,map}']
}, {
'name': 'app',
'source': './myapp/js/source-app/*.js',
'sourceParams': {
'allowEmpty': false
},
'del': ['./myapp/dist/app-*.{js,map}']
}];
const taskNames = taskOptions.map(opts => {
return [delTask(opts), concatTask(opts), minifyTask(opts)];
});
/* equivalent to defining tasks and assigning:
* var taskNames = [
* ['main_delScripts', 'main_concatScripts', 'main_minifyScripts'],
* ['app_delScripts', 'app_concatScripts', 'app_minifyScripts']
* ];
*/
gulp.task('watch', (done) => {
taskOptions.forEach((opts, i) => {
gulp.watch(opts.source, gulp.series.apply(gulp, taskNames[i]));
});
done();
});
/* equivalent to:
* gulp.task('watch', (done) => {
* gulp.watch('./myapp/js/source-main/*.js', gulp.series('main_delScripts', 'main_concatScripts', 'main_minifyScripts'));
* gulp.watch('./myapp/js/source-app/*.js', gulp.series('app_delScripts', 'app_concatScripts', 'app_minifyScripts'));
* done();
* });
*/
const allTaskNames = taskNames.reduce((arr, names) => arr.concat(names), []); // flatmap the task names into a single array
// console.log(allTaskNames.concat(['watch']));
/* equivalent to:
* let allTaskNames = ['main_delScripts', 'main_concatScripts', 'main_minifyScripts', 'app_delScripts', 'app_concatScripts', 'app_minifyScripts'];
*/
gulp.task('default', gulp.series.apply(gulp, allTaskNames.concat(['styles', 'watch'])));
/* equivalent to:
* gulp.task('default', gulp.series('main_delScripts', 'main_concatScripts', 'main_minifyScripts', 'app_delScripts', 'app_concatScripts', 'app_minifyScripts', 'watch'));
*/
并且输出:
[16:40:31] Using gulpfile gulpfile.js
[16:40:31] Starting 'default'...
[16:40:31] Starting 'main_delScripts'...
[16:40:31] Finished 'main_delScripts' after 29 ms
[16:40:31] Starting 'main_concatScripts'...
[16:40:31] Finished 'main_concatScripts' after 84 ms
[16:40:31] Starting 'main_minifyScripts'...
[16:40:34] Finished 'main_minifyScripts' after 2.45 s
[16:40:34] Starting 'app_delScripts'...
[16:40:34] Finished 'app_delScripts' after 941 μs
[16:40:34] Starting 'app_concatScripts'...
[16:40:34] Finished 'app_concatScripts' after 58 ms
[16:40:34] Starting 'app_minifyScripts'...
[16:40:37] Finished 'app_minifyScripts' after 3.12 s
[16:40:37] Starting 'styles'...
[16:40:37] Finished 'styles' after 215 ms
[16:40:37] Starting 'watch'...
[16:40:37] Finished 'watch' after 19 ms
[16:40:37] Finished 'default' after 6.04 s