使用 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-uglifygulp-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-uglifygulp-concatgulp-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 文件的主要内容,如果未能解决你的问题,请参考以下文章

gulp常用插件之gulp-uglify使用

gulp 插件之 gulp-uglify

Gulp将多个js文件缩小为一个

gulp之gulp-uglify模块

gulp插件gulp-uglify

191.gulp处理JavaScript文件的任务