使用 Gulp 连接和 Uglify 文件
Posted
技术标签:
【中文标题】使用 Gulp 连接和 Uglify 文件【英文标题】:Using Gulp to Concatenate and Uglify files 【发布时间】:2014-08-26 19:54:23 【问题描述】:我正在尝试使用 Gulp 来:
-
获取 3 个特定的 javascript 文件,将它们连接起来,然后将结果保存到文件 (concat.js)
获取这个连接的文件并对其进行 uglify/minify,然后将结果保存到另一个文件 (uglify.js)
到目前为止,我有以下代码
var gulp = require('gulp'),
gp_concat = require('gulp-concat'),
gp_uglify = require('gulp-uglify');
gulp.task('js-fef', function()
return gulp.src(['file1.js', 'file2.js', 'file3.js'])
.pipe(gp_concat('concat.js'))
.pipe(gp_uglify())
.pipe(gulp.dest('js'));
);
gulp.task('default', ['js-fef'], function());
但是,uglify 操作似乎不起作用,或者由于某种原因没有生成文件。
我需要做些什么才能做到这一点?
【问题讨论】:
很惊讶还没有看到它,所以我想快速指出,这个目标本身有点违背 Gulp 的哲学。编写中间文件更像是 Grunt 的工作方式。 Gulp 促进流以提高速度。但我敢肯定,问的人有他的理由:)。 我知道这是一个旧线程,但我已经制作了一个 npm 模块来使用 yaml 文件非常轻松地完成此类工作。看看:github.com/Stnaire/gulp-yaml-packages. 【参考方案1】:var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
gulp.task('create-vendor', function ()
var files = [
'bower_components/q/q.js',
'bower_components/moment/min/moment-with-locales.min.js',
'node_modules/jstorage/jstorage.min.js'
];
return gulp.src(files)
.pipe(concat('vendor.js'))
.pipe(gulp.dest('scripts'))
.pipe(uglify())
.pipe(gulp.dest('scripts'));
);
您的解决方案不起作用,因为您需要在 concat 过程后保存文件,然后再次进行 uglify 和保存。您不需要在 concat 和 uglify 之间重命名文件。
【讨论】:
我想说的是开发人员有权决定他们在使用 gulp 时需要做什么和不需要做什么。就我而言,我想在每一步重命名文件。其他人可能更喜欢其他方式。 当然,您可以决定什么是最适合您的选择。我明白了,下面的答案说你需要重命名文件,我只是说你不需要(这不是强制性的),如果我造成了一些混乱,对不起。【参考方案2】:我们正在使用下面的配置来做类似的事情
var gulp = require('gulp'),
async = require("async"),
less = require('gulp-less'),
minifyCSS = require('gulp-minify-css'),
uglify = require('gulp-uglify'),
concat = require('gulp-concat'),
gulpDS = require("./gulpDS"),
del = require('del');
// CSS & Less
var jsarr = [gulpDS.jsbundle.mobile, gulpDS.jsbundle.desktop, gulpDS.jsbundle.common];
var cssarr = [gulpDS.cssbundle];
var generateJS = function()
jsarr.forEach(function(gulpDSObject)
async.map(Object.keys(gulpDSObject), function(key)
var val = gulpDSObject[key]
execGulp(val, key);
);
)
var generateCSS = function()
cssarr.forEach(function(gulpDSObject)
async.map(Object.keys(gulpDSObject), function(key)
var val = gulpDSObject[key];
execCSSGulp(val, key);
)
)
var execGulp = function(arrayOfItems, dest)
var destSplit = dest.split("/");
var file = destSplit.pop();
del.sync([dest])
gulp.src(arrayOfItems)
.pipe(concat(file))
.pipe(uglify())
.pipe(gulp.dest(destSplit.join("/")));
var execCSSGulp = function(arrayOfItems, dest)
var destSplit = dest.split("/");
var file = destSplit.pop();
del.sync([dest])
gulp.src(arrayOfItems)
.pipe(less())
.pipe(concat(file))
.pipe(minifyCSS())
.pipe(gulp.dest(destSplit.join("/")));
gulp.task('css', generateCSS);
gulp.task('js', generateJS);
gulp.task('default', ['css', 'js']);
示例 GulpDS 文件如下:
jsbundle:
"mobile":
"public/javascripts/sample.min.js": ["public/javascripts/a.js", "public/javascripts/mobile/b.js"]
,
"desktop":
'public/javascripts/sample1.js': ["public/javascripts/c.js", "public/javascripts/d.js"],
"common":
'public/javascripts/responsive/sample2.js': ['public/javascripts/n.js']
,
cssbundle:
"public/stylesheets/a.css": "public/stylesheets/less/a.less",
【讨论】:
【参考方案3】:原来我需要使用gulp-rename
,并且在'uglification'之前首先输出连接的文件。代码如下:
var gulp = require('gulp'),
gp_concat = require('gulp-concat'),
gp_rename = require('gulp-rename'),
gp_uglify = require('gulp-uglify');
gulp.task('js-fef', function()
return gulp.src(['file1.js', 'file2.js', 'file3.js'])
.pipe(gp_concat('concat.js'))
.pipe(gulp.dest('dist'))
.pipe(gp_rename('uglify.js'))
.pipe(gp_uglify())
.pipe(gulp.dest('dist'));
);
gulp.task('default', ['js-fef'], function());
来自grunt
,起初有点令人困惑,但现在它是有道理的。我希望它可以帮助gulp
菜鸟。
而且,如果您需要源地图,这里是更新后的代码:
var gulp = require('gulp'),
gp_concat = require('gulp-concat'),
gp_rename = require('gulp-rename'),
gp_uglify = require('gulp-uglify'),
gp_sourcemaps = require('gulp-sourcemaps');
gulp.task('js-fef', function()
return gulp.src(['file1.js', 'file2.js', 'file3.js'])
.pipe(gp_sourcemaps.init())
.pipe(gp_concat('concat.js'))
.pipe(gulp.dest('dist'))
.pipe(gp_rename('uglify.js'))
.pipe(gp_uglify())
.pipe(gp_sourcemaps.write('./'))
.pipe(gulp.dest('dist'));
);
gulp.task('default', ['js-fef'], function());
有关选项和配置的更多信息,请参阅gulp-sourcemaps。
【讨论】:
仅供参考,您在 concat.js 之前缺少一个单引号。gulp.task
中的 return 语句后面的行应该是:.pipe(gp_concat('concat.js'))
所有文件都生成了,但是,在调试器中我仍然看到缩小版本。可能是什么原因?地图文件命名正确,可以通过其 URL 访问。
它将取决于浏览器,原始来源位于不同的选项卡上。您需要在此处放置断点。
我不清楚为什么我们需要重命名?是错误还是?
@przemcio 在我的情况下,我想要记录该过程中每个步骤的所有文件。但是,如果您只关心最终的缩小文件,那么您当然可以进一步缩短 gulp 文件【参考方案4】:
我的 gulp 文件生成了最终编译的 bundle-min.js,希望这对某人有所帮助。
//Gulpfile.js
var gulp = require("gulp");
var watch = require("gulp-watch");
var concat = require("gulp-concat");
var rename = require("gulp-rename");
var uglify = require("gulp-uglify");
var del = require("del");
var minifyCSS = require("gulp-minify-css");
var copy = require("gulp-copy");
var bower = require("gulp-bower");
var sourcemaps = require("gulp-sourcemaps");
var path =
src: "bower_components/",
lib: "lib/"
var config =
jquerysrc: [
path.src + "jquery/dist/jquery.js",
path.src + "jquery-validation/dist/jquery.validate.js",
path.src + "jquery-validation/dist/jquery.validate.unobtrusive.js"
],
jquerybundle: path.lib + "jquery-bundle.js",
ngsrc: [
path.src + "angular/angular.js",
path.src + "angular-route/angular-route.js",
path.src + "angular-resource/angular-resource.js"
],
ngbundle: path.lib + "ng-bundle.js",
//JavaScript files that will be combined into a Bootstrap bundle
bootstrapsrc: [
path.src + "bootstrap/dist/js/bootstrap.js"
],
bootstrapbundle: path.lib + "bootstrap-bundle.js"
// Synchronously delete the output script file(s)
gulp.task("clean-scripts", function (cb)
del(["lib","dist"], cb);
);
//Create a jquery bundled file
gulp.task("jquery-bundle", ["clean-scripts", "bower-restore"], function ()
return gulp.src(config.jquerysrc)
.pipe(concat("jquery-bundle.js"))
.pipe(gulp.dest("lib"));
);
//Create a angular bundled file
gulp.task("ng-bundle", ["clean-scripts", "bower-restore"], function ()
return gulp.src(config.ngsrc)
.pipe(concat("ng-bundle.js"))
.pipe(gulp.dest("lib"));
);
//Create a bootstrap bundled file
gulp.task("bootstrap-bundle", ["clean-scripts", "bower-restore"], function ()
return gulp.src(config.bootstrapsrc)
.pipe(concat("bootstrap-bundle.js"))
.pipe(gulp.dest("lib"));
);
// Combine and the vendor files from bower into bundles (output to the Scripts folder)
gulp.task("bundle-scripts", ["jquery-bundle", "ng-bundle", "bootstrap-bundle"], function ()
);
//Restore all bower packages
gulp.task("bower-restore", function ()
return bower();
);
//build lib scripts
gulp.task("compile-lib", ["bundle-scripts"], function ()
return gulp.src("lib/*.js")
.pipe(sourcemaps.init())
.pipe(concat("compiled-bundle.js"))
.pipe(gulp.dest("dist"))
.pipe(rename("compiled-bundle.min.js"))
.pipe(uglify())
.pipe(sourcemaps.write("./"))
.pipe(gulp.dest("dist"));
);
【讨论】:
很好的例子@wchoward 这正是我想要的,非常简洁明了的设计。【参考方案5】:2015 年 6 月 10 日:gulp-uglifyjs
作者的说明:
已弃用:此插件已被列入黑名单,因为它依赖于 Uglify 来连接文件,而不是使用 gulp-concat,这打破了“它应该做一件事”的范式。当我创建这个插件时,没有办法让源映射与 gulp 一起工作,但是现在有一个 gulp-sourcemaps 插件可以实现相同的目标。 gulp-uglifyjs 仍然运行良好,并且对 Uglify 执行提供了非常精细的控制,我只是提醒您现在存在其他选项。
2015 年 2 月 18 日: gulp-uglify
和 gulp-concat
现在都可以很好地与 gulp-sourcemaps
配合使用。只需确保为gulp-concat
正确设置newLine
选项;我推荐\n;
。
原始答案(2014 年 12 月):请改用 gulp-uglifyjs。 gulp-concat
不一定安全;它需要正确处理尾随分号。 gulp-uglify
也不支持源映射。这是我正在从事的一个项目的 sn-p:
gulp.task('scripts', function ()
gulp.src(scripts)
.pipe(plumber())
.pipe(uglify('all_the_things.js',
output:
beautify: false
,
outSourceMap: true,
basePath: 'www',
sourceRoot: '/'
))
.pipe(plumber.stop())
.pipe(gulp.dest('www/js'))
);
【讨论】:
嗯? gulp-uglify 绝对支持源映射:github.com/floridoo/gulp-sourcemaps/wiki/… @MisterOh 在撰写本文时不确定它是否确实如此,或者如果确实如此,也许gulp-concat
没有(gulp-uglify
不会让您缩小多个文件,因此您必须先 concat )。此外,gulp-concat
默认使用 \r\n
,如果您的 JS 文件未正确终止,这可能会导致问题。但是,是的,既然有了支持,那么走这条路可能会更好,因为它更灵活。
@Mark - 如果您能使用与 Obinwanne 的答案内联的 gulp-sourcemaps 发布解决方案,将不胜感激。我似乎无法让它工作。
@NightOwl888 okay 实际上,如果这就是您所要求的,那不会产生内联源地图;它仍然是一个单独的文件。
gulp-uglifyjs 现在也被弃用了。现在只需使用 gulp-uglify 插件就足够了。查看其他答案以获取最新解决方案。【参考方案6】:
使用gulp-uglify
、gulp-concat
和gulp-sourcemaps
的解决方案。这是来自我正在从事的一个项目。
gulp.task('scripts', function ()
return gulp.src(scripts, base: '.')
.pipe(plumber(plumberOptions))
.pipe(sourcemaps.init(
loadMaps: false,
debug: debug,
))
.pipe(gulpif(debug, wrapper(
header: fileHeader,
)))
.pipe(concat('all_the_things.js',
newLine:'\n;' // the newline is needed in case the file ends with a line comment, the semi-colon is needed if the last statement wasn't terminated
))
.pipe(uglify(
output: // http://lisperator.net/uglifyjs/codegen
beautify: debug,
comments: debug ? true : /^!|\b(copyright|license)\b|@(preserve|license|cc_on)\b/i,
,
compress: // http://lisperator.net/uglifyjs/compress, http://davidwalsh.name/compress-uglify
sequences: !debug,
booleans: !debug,
conditionals: !debug,
hoist_funs: false,
hoist_vars: debug,
warnings: debug,
,
mangle: !debug,
outSourceMap: true,
basePath: 'www',
sourceRoot: '/'
))
.pipe(sourcemaps.write('.',
includeContent: true,
sourceRoot: '/',
))
.pipe(plumber.stop())
.pipe(gulp.dest('www/js'))
);
这会合并并压缩您所有的scripts
,将它们放入一个名为all_the_things.js
的文件中。该文件将以特殊行结束
//# sourceMappingURL=all_the_things.js.map
这会告诉您的浏览器查找该地图文件,它也会写出。
【讨论】:
以上是关于使用 Gulp 连接和 Uglify 文件的主要内容,如果未能解决你的问题,请参考以下文章