按顺序与Gulp连接脚本

例如,您正在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/'));
});

我的source/index.html中的脚本顺序是正确的,但由于文件是按字母顺序组织的,因此Gulp将在backbone.js之后连接underscore.js,而我的source/index.html中的脚本顺序并不重要,它会查看目录中的文件。

有人对此有什么想法吗?

我的最佳想法是将供应商脚本重命名为123,以使它们具有正确的顺序,但我不确定我是否喜欢这样。

随着我了解得越来越多,我发现Browserify是一个很好的解决方案,一开始可能会很痛苦,但它很棒。

122816 次浏览

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

我最后做的是在Grunt配置中按顺序明确列出文件。配置文件将如下所示:

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

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

如果您需要某些文件之后文件的BLOB,则另一件有用的事情是从您的GLOB中排除特定文件,如下所示:

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

正如ChadJohnson的回答中所解释的那样,您可以将此与指定需要首先出现的文件结合起来。

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

0_normalize.scss
1_tikitaka.scss
main.scss

它在吞咽中工作没有任何问题。

我已经使用了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);
});

我在一个模块环境中,所有人都是使用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']
    

It'll obviously take the _ as the first directory from the list (natural sort?).

Note (angularjs): I then use gulp-angular-extender to dynamically add the modules to the core module. Compiled it looks like this:

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

其中管理和产品是两个模块。

排序流还可用于确保具有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/'));
});

使用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

我将我的脚本组织在不同的文件夹中,用于我从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可能更好,因为它们被广泛使用,浏览器可以从其他站点缓存它们。

尝试流系。它的工作方式类似于合并流/event-stream.merge(),不同之处在于它不是交错,而是附加到末尾。它不需要您指定对象模式(如流队列),因此您的代码会更干净。

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'))
});

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

它允许您通过添加.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

希望这能有所帮助!

对我来说,我在重新排序文件的管道中有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}))

我只使用Gulp-Angular-Filesort

function concatOrder() {


return gulp.src('./build/src/app/**/*.js')
.pipe(sort())
.pipe(plug.concat('concat.js'))
.pipe(gulp.dest('./output/'));
}

如果要订购第三方库依赖项,请尝试电线。这个包主要检查Bower.JSON中的每个包依赖关系,然后为您连接它们。

_,ABC_0看起来像是目前唯一工作并维护的有序流合并工具。

更新2020

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

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');

我在这个页面上尝试了几个解决方案,但都没有成功。我有一系列已编号的文件,我只想按字母顺序排列文件夹名,这样当管道传输到concat()时,它们将处于相同的顺序。也就是说,保留globbing输入的顺序。很容易,对吧?

下面是我的特定概念验证代码(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());
});

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

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

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

gulp.src([
// vendor folder first
path.join(folder, '/vendor/**/*.js'),
// custom js after vendor
path.join(folder, '/**/*.js')
])

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