195

比如说,您正在 Backbone 或其他任何东西上构建一个项目,并且您需要按特定顺序加载脚本,例如underscore.js需要在backbone.js.

我如何让它连接脚本以使它们井井有条?

// JS concat, strip debugging and minify
gulp.task('scripts', function() {
    gulp.src(['./source/js/*.js', './source/js/**/*.js'])
    .pipe(concat('script.js'))
    .pipe(stripDebug())
    .pipe(uglify())
    .pipe(gulp.dest('./build/js/'));
});

我在 my 中有正确的脚本顺序source/index.html,但是由于文件是按字母顺序组织的,gulp 将underscore.js在之后连接backbone.js,并且 my 中的脚本顺序source/index.html无关紧要,它会查看目录中的文件。

那么有人对此有想法吗?

我最好的想法是用 , 重命名供应商脚本,1以给它们正确的顺序,但我不确定我是否喜欢这个。23

随着我了解更多,我发现 Browserify 是一个很好的解决方案,起初可能会很痛苦,但它很棒。

4

17 回答 17

204

最近在构建我的 AngularJS 应用程序时,我遇到了与 Grunt 类似的问题。这是我发布的一个问题。

我最终做的是在 grunt 配置中按顺序显式列出文件。配置文件将如下所示:

[
  '/path/to/app.js',
  '/path/to/mymodule/mymodule.js',
  '/path/to/mymodule/mymodule/*.js'
]

Grunt 能够找出哪些文件是重复的并且不包含它们。同样的技术也适用于 Gulp。

于 2014-02-22T22:05:25.783 回答
138

如果您需要将一些文件放在一堆文件之后,另一件有帮助的事情是从您的 glob 中排除特定文件,如下所示:

[
  '/src/**/!(foobar)*.js', // all files that end in .js EXCEPT foobar*.js
  '/src/js/foobar.js',
]

您可以将其与指定需要首先出现的文件结合起来,如 Chad Johnson 的回答中所述。

于 2014-02-22T22:12:49.733 回答
18

我已经使用了 gulp-order 插件,但它并不总是成功的,你可以从我的堆栈溢出后gulp-order 节点模块与合并流中看到。在浏览 Gulp 文档时,我遇到了 streamque 模块,该模块在指定我的案例串联顺序方面非常有效。https://github.com/gulpjs/gulp/blob/master/docs/recipes/using-multiple-sources-in-one-task.md

我如何使用它的示例如下

var gulp         = require('gulp');
var concat       = require('gulp-concat');
var handleErrors = require('../util/handleErrors');
var streamqueue  = require('streamqueue');

gulp.task('scripts', function() {
    return streamqueue({ objectMode: true },
        gulp.src('./public/angular/config/*.js'),
        gulp.src('./public/angular/services/**/*.js'),
        gulp.src('./public/angular/modules/**/*.js'),
        gulp.src('./public/angular/primitives/**/*.js'),
        gulp.src('./public/js/**/*.js')
    )
        .pipe(concat('app.js'))
        .pipe(gulp.dest('./public/build/js'))
        .on('error', handleErrors);
});
于 2014-05-07T02:45:12.230 回答
14

使用 gulp-useref,您可以按照声明的顺序连接索引文件中声明的每个脚本。

https://www.npmjs.com/package/gulp-useref

var $ = require('gulp-load-plugins')();
gulp.task('jsbuild', function () {
  var assets = $.useref.assets({searchPath: '{.tmp,app}'});
  return gulp.src('app/**/*.html')
    .pipe(assets)
    .pipe($.if('*.js', $.uglify({preserveComments: 'some'})))
    .pipe(gulp.dest('dist'))
    .pipe($.size({title: 'html'}));
});

在 HTML 中,您必须声明要生成的构建文件的名称,如下所示:

<!-- build:js js/main.min.js -->
    <script src="js/vendor/vendor.js"></script>
    <script src="js/modules/test.js"></script>
    <script src="js/main.js"></script>

在您的构建目录中,您将拥有对 main.min.js 的引用,其中将包含 vendor.js、test.js 和 main.js

于 2015-02-01T05:37:48.370 回答
6

排序流也可用于确保带有gulp.src. 将backbone.js始终作为要处理的最后一个文件的示例代码:

var gulp = require('gulp');
var sort = require('sort-stream');
gulp.task('scripts', function() {
gulp.src(['./source/js/*.js', './source/js/**/*.js'])
  .pipe(sort(function(a, b){
    aScore = a.path.match(/backbone.js$/) ? 1 : 0;
    bScore = b.path.match(/backbone.js$/) ? 1 : 0;
    return aScore - bScore;
  }))
  .pipe(concat('script.js'))
  .pipe(stripDebug())
  .pipe(uglify())
  .pipe(gulp.dest('./build/js/'));
});
于 2014-08-26T20:38:02.327 回答
5

我只是在文件名的开头添加数字:

0_normalize.scss
1_tikitaka.scss
main.scss

它可以在 gulp 中正常工作。

于 2014-03-12T11:11:05.723 回答
5

对于从 Bower 中提取的每个包,我的脚本都组织在不同的文件夹中,另外还有我自己的应用程序脚本。既然你要在某个地方列出这些脚本的顺序,为什么不在你的 gulp 文件中列出它们呢?对于您项目的新开发人员,很高兴您的所有脚本端点都在此处列出。您可以使用gulp-add-src执行此操作:

gulpfile.js

var gulp = require('gulp'),
    less = require('gulp-less'),
    minifyCSS = require('gulp-minify-css'),
    uglify = require('gulp-uglify'),
    concat = require('gulp-concat'),
    addsrc = require('gulp-add-src'),
    sourcemaps = require('gulp-sourcemaps');

// CSS & Less
gulp.task('css', function(){
    gulp.src('less/all.less')
        .pipe(sourcemaps.init())
        .pipe(less())
        .pipe(minifyCSS())
        .pipe(sourcemaps.write('source-maps'))
        .pipe(gulp.dest('public/css'));
});

// JS
gulp.task('js', function() {
    gulp.src('resources/assets/bower/jquery/dist/jquery.js')
    .pipe(addsrc.append('resources/assets/bower/bootstrap/dist/js/bootstrap.js'))
    .pipe(addsrc.append('resources/assets/bower/blahblah/dist/js/blah.js'))
    .pipe(addsrc.append('resources/assets/js/my-script.js'))
    .pipe(sourcemaps.init())
    .pipe(concat('all.js'))
    .pipe(uglify())
    .pipe(sourcemaps.write('source-maps'))
    .pipe(gulp.dest('public/js'));
});

gulp.task('default',['css','js']);

注意:添加 jQuery 和 Bootstrap 是为了演示目的。对于那些使用 CDN 可能会更好,因为它们被广泛使用,并且浏览器已经可以从其他站点缓存它们。

于 2015-07-02T14:27:01.863 回答
3

尝试流系列。它的工作方式与merge-stream / event-stream.merge()类似,只是它不是交错,而是附加到末尾。它不需要您指定像streamqueue这样的对象模式,因此您的代码更清晰。

var series = require('stream-series');

gulp.task('minifyInOrder', function() {
    return series(gulp.src('vendor/*'),gulp.src('extra'),gulp.src('house/*'))
        .pipe(concat('a.js'))
        .pipe(uglify())
        .pipe(gulp.dest('dest'))
});
于 2015-07-13T16:35:43.227 回答
3

merge2看起来是目前唯一工作和维护的有序流合并工具。

2020 年更新

API 总是在变化,一些库变得不可用或包含漏洞,或者它们的依赖项包含多年未修复的漏洞。对于文本文件操作,您最好使用自定义 NodeJS 脚本和流行的库,例如没有 Gulp、Grunt 等包装器的其他库globbyfs-extra

import globby from 'globby';
import fs from 'fs-extra';

async function bundleScripts() {
    const rootPaths = await globby('./source/js/*.js');
    const otherPaths = (await globby('./source/**/*.js'))
        .filter(f => !rootFiles.includes(f));
    const paths = rootPaths.concat(otherPaths);

    const files = Promise.all(
        paths.map(
            // Returns a Promise
            path => fs.readFile(path, {encoding: 'utf8'})
        )
    );

    let bundle = files.join('\n');
    bundle = uglify(bundle);
    bundle = whatever(bundle);
    bundle = bundle.replace(/\/\*.*?\*\//g, '');

    await fs.outputFile('./build/js/script.js', bundle, {encoding: 'utf8'});
}

bundleScripts.then(() => console.log('done');
于 2017-06-26T14:36:14.293 回答
1

另一种方法是使用专门为此问题创建的 Gulp 插件。https://www.npmjs.com/package/gulp-ng-module-sort

它允许您通过添加 a 来对脚本进行排序.pipe(ngModuleSort())

var ngModuleSort = require('gulp-ng-module-sort');
var concat = require('gulp-concat');

gulp.task('angular-scripts', function() {
    return gulp.src('./src/app/**/*.js')
        .pipe(ngModuleSort())
        .pipe(concat('angularAppScripts.js))
        .pipe(gulp.dest('./dist/));
});

假设目录约定为:

|——— src/
|   |——— app/
|       |——— module1/
|           |——— sub-module1/
|               |——— sub-module1.js
|           |——— module1.js
|       |——— module2/
|           |——— sub-module2/
|               |——— sub-module2.js
|           |——— sub-module3/
|               |——— sub-module3.js
|           |——— module2.js
|   |——— app.js

希望这可以帮助!

于 2015-10-23T19:44:46.800 回答
1

对我来说,我在重新排序文件的管道中有 natualSort() 和 angularFileSort() 。我删除了它,现在它对我来说很好

$.inject( // app/**/*.js files
    gulp.src(paths.jsFiles)
      .pipe($.plumber()), // use plumber so watch can start despite js errors
      //.pipe($.naturalSort())
      //.pipe($.angularFilesort()),
    {relative: true}))
于 2016-03-15T12:34:02.847 回答
1

我只是使用 gulp-angular-filesort

function concatOrder() {

    return gulp.src('./build/src/app/**/*.js')
        .pipe(sort())
        .pipe(plug.concat('concat.js'))
        .pipe(gulp.dest('./output/'));
}
于 2016-08-04T15:24:01.013 回答
0

我在一个模块环境中,所有这些都是使用 gulp 的核心依赖项。因此,core需要在其他模块之前附加该模块。

我做了什么:

  1. 将所有脚本移动到一个src文件夹
  2. 只是gulp-rename你的core目录_core
  3. gulp 保持你的顺序gulp.src,我的 concatsrc看起来像这样:

    concat: ['./client/src/js/*.js', './client/src/js/**/*.js', './client/src/js/**/**/*.js']
    

显然,它会_作为列表中的第一个目录(自然排序?)。

注意(angularjs):然后我使用 gulp -angular-extender将模块动态添加到core模块中。编译出来是这样的:

angular.module('Core', ["ui.router","mm.foundation",(...),"Admin","Products"])

其中 Admin 和 Products 是两个模块。

于 2014-08-12T10:37:05.313 回答
0

如果您想订购第三方库依赖项,请尝试wiredep。这个包基本上检查 bower.json 中的每个包依赖关系,然后为您连接它们。

于 2017-03-16T06:26:03.833 回答
0

我从这个页面尝试了几种解决方案,但都没有奏效。我有一系列编号的文件,我只想按字母文件夹名排序,这样当通过管道传输到concat()它们时,它们的顺序相同。也就是说,保留通配输入的顺序。容易,对吧?

这是我的特定概念验证代码(print只是为了查看打印到 cli 的订单):

var order = require('gulp-order');
var gulp = require('gulp');
var print = require('gulp-print').default;

var options = {};

options.rootPath = {
  inputDir: process.env.INIT_CWD + '/Draft',
  inputGlob: '/**/*.md',
};

gulp.task('default', function(){
  gulp.src(options.rootPath.inputDir + options.rootPath.inputGlob, {base: '.'})
    .pipe(order([options.rootPath.inputDir + options.rootPath.inputGlob]))
    .pipe(print());
});

疯狂的原因是gulp.src什么?gulp.src当我能够使用sleep()函数(使用.map按索引递增的睡眠时间)来正确排序流输出时,我确定它正在运行异步。

src包含更多文件的平均目录的异步结果出现在文件较少的目录之后,因为它们需要更长的处理时间。

于 2018-07-21T15:32:46.757 回答
0

在我的 gulp 设置中,我首先指定供应商文件,然后再指定(更一般的)所有内容。它成功地将供应商 js 放在其他自定义内容之前。

gulp.src([
  // vendor folder first
  path.join(folder, '/vendor/**/*.js'),
  // custom js after vendor
  path.join(folder, '/**/*.js')
])    
于 2018-12-12T19:58:57.640 回答
0

显然,您可以将“nosort”选项传递给 gulp.src gulp.src

于 2019-10-15T21:15:20.647 回答