Gulpを使用したスクリプトの連結


192

たとえば、バックボーンなどでプロジェクトを構築していて、スクリプトを特定の順序でロードする必要があるとします。 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はunderscore.js後に連結しますbackbone.jsに、私のスクリプトの順序はsource/index.html重要ではないため、ディレクトリ内のファイルを調べます。

それで誰かがこれについて考えを持っていますか?

私が持っている最高のアイデアは、ベンダースクリプトの名前を123それらを適切な順序を与えることが、私はこれが好きかどうかはわかりません。

さらに知りながら、Browserifyは優れたソリューションであることを発見しました。最初は面倒なことかもしれませんが、素晴らしいものです。


4
今日私はbrowserifyを使用していると言ってもいいでしょう。独自の小さな学習曲線IMOがあります。最初は苦労しましたが、gulp browserifyはクールな方法です!コードをモジュール化できるようにする!注文はシムで処理するため、browserifyを使用する場合は連結する必要はありません。
マイケルジョセフオーブリー2014

ソリューションまたはリンクの詳細を伝えたいですか?
ドミトリザイツェフ2014

kroltech.com/2013/12/…これは、ボイラープレートプロジェクトへのリンクです。このボイラープレートプロジェクトは、優れたプロジェクト管理を始めるのに本当に役立ちました。これらすべてを学ぶことに苦しんだ後、私は私のプロジェクトをはるかによく管理することができます。彼のプロジェクトはgithubにあり、彼がbrowserifyをどのように使用しているかを確認できます。YouTubeは常に役立ちます。もちろん、ソース自体は常に過小評価されていますgithub.com/substack/node-browserify#usage
Michael Joseph Aubry 14

基本的にはrequire、フロントエンドでnpmのような構文を使用してnpmを使用できるという考え方です。もちろん、サーバー側でnpmを使用している場合、モジュールを必要とする方法がわかりますが、browserifyを使用すると、クライアント側のコードでそれを実行できます。始めるには少し工夫が必要ですが、主にpackage.json内にあり、gulp.jsまたはgrunt.jsで使用したい場合に使用します。gulp / grunt browserifyパッケージをインストールするgulp/grunt browserifyと、スクリプトを実行して1つのメインスクリプトに変換できます。これはわずかな学習曲線ですが、IMOに値します。
Michael Joseph Aubry 14

ありがとう!実際に私は偉大な記事に出くわしたmedium.com/@dickeyxxx/...あなたが本当に必要としないという良い点作るbrowserifyためAngularの単純な連結の作品や順序は問題ではないモジュールを、:)
ドミトリザイツェフ

回答:


199

AngularJSアプリをビルドするときに、最近Gruntで同様の問題が発生しました。これが私が投稿した質問です。

私がやったことは、grunt configに順番にファイルを明示的にリストすることです。設定ファイルは次のようになります。

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

Gruntはどのファイルが重複しているかを把握し、それらを含めないようにすることができます。同じテクニックがGulpでも機能します。


74
ちなみに、これはgulpでも問題なく機能します。Gulpはファイルも繰り返しません。
OverZealous 14

1
クールな男、これらの2つの傑作は素晴らしいです。最後に、gulp.jsファイルを希望どおりに動作するように設定し、いくつかのhtmlに書き込み、ファイルを保存し、ボタンを押すだけで最高のフレームワークと優れたプラクティスで構築されたサイトをブームしました。必要な更新プログラムを使用していなければ、Plusの更新は簡単です。
Michael Joseph Aubry 14

1
はい!私は最近Gruntを使い始めました、そしてそれは素晴らしいです。JavaScriptアプリケーションをバックエンドフレームワーク内に埋め込む必要はもうありません。
チャドジョンソン

3
私の試みではGulpがファイルを複製していましたが、gulpとファイルシステムではケースが異なることに気づきました。正確なケースでは、gulpはファイルを複製しません。
クリス

2
手動の注文は、深刻なプロジェクトでは悪夢です。特別なファイルソーターがあります-angularjsと他のもののために
zhekaus 2016年

135

ファイルのブロブの後にいくつかのファイルが必要な場合に役立つもう1つのことは、次のよう特定のファイルをグロブから除外することです。

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

これを、Chad Johnsonの回答で説明されているように、最初に来る必要があるファイルの指定と組み合わせることができます。


ああ、私は実際に以前にあなたの投稿を見ました、そして私にコードを注入するのを助けましたそして私があなたがその構文を使用しsrcているのbuildを見たので、私はその部分を消去することになりました。
マイケルジョセフオーブリー2014

ああ、わかりましたので、ここでのあなたのポイントは私を襲っただけです。それは逆でなければなりません。['./source/js/*.js', './source/js/**/underscore.js', './source/js/**/!(underscore)*.js']
Michael Joseph Aubry 14

ええ、これは単なる追加の助けでした。他のすべてがロードされた後にコアアプリケーションコードが必要になる、または必要になる場合に最も役立ちます。!(foobar)特定のファイルを事前にインクルードしている場合は、それを使用する理由はありません()。
OverZealous 2014

名前に「ダッシュなし」が含まれるファイルにモジュール定義が存在するAngularJSアプリケーションの場合、このGulpグロブパターンは機能しました。['src/app/**/!(*-)*.js', 'src/app/**/*.js']
サムT

17

私は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);
});

stream-seriesも参照してください。オブジェクトモードを指定する必要はなく、gulp-injectで動作します。私の答えを見てください。
15

gulpプラグインの半分は一貫して機能しないようです(指摘したとおりの順序のように)。これはgulpのアーキテクチャの概念が壮観で、プラグインの実装と保守が不十分なため、多くの人が思うに...基盤となるノードモジュールの方が便利だと思うので、このソリューションに感謝します!よく働く!
ジミーHoffa

1
streamqueue、event-streamは機能しませんでしたが、merge2は期待どおりに機能しましたnpmjs.com/package/merge2
Alexander Shutau

12

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>

ビルドディレクトリには、vendor.js、test.js、main.jsを含むmain.min.jsへの参照があります。


2
これは完璧です!順序を定義するために必要な答えは嫌いでした。あのね?順序は次のとおりです:HTMLファイル内。完璧なソリューション。
Ali Ok 2016年

6

ソート・ストリームはまた、とのファイルの特定の順序を保証するために使用することができますgulp.srcbackbone.jsalwaysを最後のファイルとして処理するサンプルコード:

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

このモジュールが私にとって最も簡単な答えのように見えるので機能することを望みますが、私の場合、ファイル名に番号を付け、非常に単純な比較関数を使用しているので、これは機能しません。
ジェレミージョン

5

ファイル名の先頭に数字を追加するだけです:

0_normalize.scss
1_tikitaka.scss
main.scss

問題なく一気に動作します。


1
ええ、これは少し簡単だと思います。つまり、すべてのファイルを本番用にコンパイルしている場合、開発中のファイル名に違いはありません。
Michael Joseph Aubry 2014年

2
これが正しく機能しないことがわかりました。1_xx、2_xx、10_xx、11_xxを使用してみてください。Windowsでは、少なくとも1_xx、10_xx、11_xx、2_xxになります
dbinott

17
個人的には、開発中のファイルに名前を付けることは重要ではないという声明にまったく同意しません。すべての開発は、コンピュータ中心ではなく、最初に人間中心でなければなりません。ビルドツールに一致するようにファイルを変更すると、ビルドツールの目的が損なわれます。プロジェクトと一致するようにビルドを変更します。逆は行いません。
Jon Hieb、2015

2
@JonHiebある意味で、ファイルの前に番号を付けると、次の開発者が各ファイルの依存関係を知るのにも役立ちます。フォルダーを開いて1_foo.js、2_bar.js、3_baz.jsを表示した場合、それらのファイルをこの順序で開き、1_foo.jsからコードの読み取りを開始します
sqram

gulp.srcが非同期で実行されることがわかりました。つまり、dirで処理するファイルがまだある場合、これは一貫して機能しません。
ジェレミージョン

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は非常に広く使用されており、ブラウザはすでに他のサイトからキャッシュされている可能性があるため、これらのCDNを使用する方が良いでしょう。


3

stream-seriesを試してください。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'))
});

2

merge2は、現時点で動作し、維持されている唯一の順序付けられたストリームマージツールのように見えます。

アップデート2020

APIは常に変化しており、一部のライブラリは使用できなくなったり、脆弱性が含まれたり、依存関係に脆弱性が含まれているため、何年も修正されていません。テキストファイルの操作のためには、より良い使用カスタムNodeJSスクリプトなどの人気ライブラリいただきたい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');

1

別の方法は、この問題のために特別に作成された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

お役に立てれば!


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

1

私はgulp-angular-filesortを使用します

function concatOrder() {

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

おっと、私はあなたが角度について申し訳ありません
でしたと気づか

0

私はすべてgulpを使用してコアに依存するモジュール環境にいます。したがって、coreモジュールは他のモジュールの前に追加する必要があります。

私がしたこと:

  1. すべてのスクリプトをsrcフォルダーに移動する
  2. ちょうどgulp-renameあなたのcoreディレクトリに_core
  3. gulpはの順序を維持していますgulp.src。私の連結srcは次のようになります。

    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は2つのモジュールです。


0

サードパーティライブラリの依存関係を注文する場合は、wiredepを試してください。このパッケージは基本的に、bower.jsonの各パッケージの依存関係をチェックしてから、それらを配線します。


0

このページからいくつかの解決策を試しましたが、どれもうまくいきませんでした。一連の番号付きファイルがあり、それらを単純にアルファベット順のフォルダー名でconcat()並べ替えたいので、それらをパイプ処理すると同じ順序になります。つまり、グロビング入力の順序を保持します。簡単ですよね?

これが私の具体的な概念実証コードです(printCLIに印刷された注文を確認するためだけです)。

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より多くのファイルを持つ平均dirs の非同期の結果は、処理に時間がかかるため、より少ないファイルを持つdirsの後に発生しました。


1
同期的な(まあ、少なくとも決定論的な)代替案を見つけましたか?
ELLIOTTCABLE 2018年

0

私のgulpセットアップでは、最初にベンダーファイルを指定し、次に(より一般的な)すべてを指定しています。そしてそれは他のカスタムのものの前にベンダーjsをうまく配置します。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.