【问题标题】:Compile JavaScripts with Gulp and Resolve Dependencies (separate files)使用 Gulp 编译 JavaScript 并解决依赖关系(单独的文件)
【发布时间】:2014-09-07 13:33:55
【问题描述】:

我想用 Gulp 编译 JavaScript 文件。

我有一个src 目录,其中所有脚本都带有.js 扩展名。我希望将所有脚本单独编译并放入与原始文件名相同的目标目录 (dist)。

考虑这个例子:

src/jquery.js

/**
 * @require ../../vendor/jquery/dist/jquery.js
 */

src/application.js

/**
 * @require ../../vendor/angular/angular.js
 * @require ../../vendor/ngprogress-lite/ngprogress-lite.js
 * @require ../../vendor/restangular/dist/restangular.js
 * @require ../../vendor/lodash/dist/lodash.underscore.js
 * @require ../../vendor/angular-input-locker/dist/angular-input-locker.js
 * @require ../../vendor/angular-route/angular-route.js
 */

(function(document, angular) {

    'use strict';

    var moduleName = 'waApp';

    angular.module(moduleName, [
        // Some more code here.
    ;

    // Bootstrapping application when DOM is ready.
    angular.element(document).ready(function() {
        angular.bootstrap(document, [moduleName]);
    });

})(document, angular);

我正在使用gulp-resolve-dependencies 来解析每个源 JavaScript 文件的标头中指定的依赖项。

我的 gulpfile.js 看起来像这样:

//==============//
// Dependencies //
//==============//

var gulp = require('gulp');
var pathModule = require('path');
var resolveDependencies = require('gulp-resolve-dependencies');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');

//=======//
// TASKS //
//=======//

gulp.task('build:scripts', function(callback) {

    return gulp.src('scripts/*.js')
        .pipe(resolveDependencies({
            pattern: /\* @require [\s-]*(.*?\.js)/g,
            log: true
        }))
        .pipe(concat('all.js'))
        .pipe(uglify())
        .pipe(gulp.dest('js/'))
    ;
});

为了合并由resolveDependencies 解析的脚本,我必须使用concat,但concat 需要一个文件名,并且不仅合并原始文件和为其解析的依赖项,还合并所有通过glob 模式指定的JavaScript 文件。

那么,如何获取单个 JavaScript 文件作为输出? 像这样:

dist/jquery.js:
    src/jquery.js
    vendor/jquery.js

dist/application.js:
    src/application.js
    vendor/angular.js
    vendor/ngprogress-lite.js
    ...

我现在有这个解决方法:

gulp.task('build:scripts', function(callback) {

    var compileScript = function(stream, filename) {
        return stream
            .pipe(resolveDependencies({
                pattern: /\* @require [\s-]*(.*?\.js)/g,
                log: true
            }))
            .pipe(concat(filename))
            .pipe(uglify())
            .pipe(gulp.dest('dist/'))
        ;
    };

    var scripts = getListOfFiles('src/', 'js');
    for (key in scripts) {
        var filename = scripts[key];
        var stream = gulp.src(pathModule.join('src/', filename));
        compileScript(stream, filename);
    }

    callback(null);
});

//===================//
// FUNCTIONS & UTILS //
//===================//

/**
 * Returns list of files in the specified directory
 * with the specified extension.
 *
 * @param {string} path
 * @param {string} extension
 * @returns {string[]}
 */
function getListOfFiles(path, extension) {

    var list = [];
    var files = fs.readdirSync(path);
    var pattern = new RegExp('.' + extension + '$');

    for (var key in files) {
        var filename = files[key];
        if (filename.match(pattern)) {
            list.push(filename);
        }
    }

    return list;
}

但它看起来很老套,我找不到一个很好的方法让它与gulp-watch一起工作。

有没有更好更简单的方法来解决这个问题并达到预期的效果?

【问题讨论】:

    标签: javascript compilation assets gulp


    【解决方案1】:

    如何获取单个 JavaScript 文件作为输出?

    在这里查看我对类似问题的回答:Pass random value to gulp pipe template

    使用这个 gulp 插件:https://github.com/adam-lynch/glob-to-vinyl

    您可以访问单个文件。

    这是怎么做的(假设使用这个插件):

    function compileScript(file) {
      gulp
        .src('file')
        .pipe(resolveDependencies({
          pattern: /\* @require [\s-]*(.*?\.js)/g,
          log: true
        }))
        .pipe(concat())
        .pipe(uglify())
        .pipe(gulp.dest('dist/'))
      ;
    };
    
    gulp.task('build:scripts', function() {
      globToVinyl('src/**/*.js', function(err, files){
        for (var file in files) {
          compileScript(files[file].path);
        }
      });
    });
    

    【讨论】:

    • 嘿,谢谢!它看起来是一个可行的解决方案,我会试一试,然后再回复你。顺便说一句concat 需要文件名才能操作,您能否更新您的代码 sn-p 以反映这一点?也许我们可以从compileScript函数的参数中提取文件名?
    • compileScript 接收文件名作为参数,这就是我们使用 globToViny 的原因,所以我想只是将文件添加到:.pipe(concat(file)) 但我无法(没有时间)真正测试代码,所以,你必须这样做。请检查并告诉我。
    • 我认为file 是文件的完整路径名,concat 只需要文件名的一部分。不是吗?
    • 啊,明白了,没听懂你的意思。我不知道我们必须发送文件名。我的错。为此,只需从路径字符串中提取文件名,如下所示: .pipe(concat(file.replace(/^.*[\\\/]/, ''))) 如果有帮助,请告诉我.
    • 感谢您的回答!我已经设法使用您的建议重写了我的任务。我已经发布了完整的工作代码作为未来参考的另一个答案。
    【解决方案2】:

    这是使用@avcajaraville 指定的解决方案重写我的任务的结果。这是一个完整的、经过测试的、可以工作的代码。

    var targetDir = 'web';
    var sourceDir = 'assets';
    
    var gulp = require('gulp');
    var pathModule = require('path');
    var resolveDependencies = require('gulp-resolve-dependencies');
    var concat = require('gulp-concat');
    var uglify = require('gulp-uglify');
    var globToVinyl = require('glob-to-vinyl');
    
    gulp.task('build:scripts', function(callback) {
    
        var compileScript = function(filePath, destinationDirectory) {
    
            // Extracting filename from absolute path (required by concat).
            var filename = pathModule.basename(filePath);
    
            return gulp
                .src(filePath)
                .pipe(resolveDependencies({
                    pattern: /\* @require [\s-]*(.*?\.js)/g,
                    log: true
                }))
                .pipe(concat(filename))
                .pipe(uglify())
                .pipe(gulp.dest(destinationDirectory))
            ;
        };
    
        var sourceGlob = pathModule.join(sourceDir, '/scripts/*.js');
        var destinationDirectory = pathModule.join(targetDir, '/js/');
    
        globToVinyl(sourceGlob, function(errors, files) {
            for (var file in files) {
                compileScript(files[file].path, destinationDirectory);
            }
        });
    
        callback(null);
    });
    

    【讨论】:

      猜你喜欢
      • 2016-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多