質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.61%

  • Node.js

    1806questions

    Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

  • gulp

    266questions

    gulpは、Node.jsをベースとしたタスク自動化ツールの一つ。ストリームでファイルを処理することが特徴です。CSSプリプロセッサの使用時のコンパイルや、CSS・JavaScriptファイルの圧縮・結合などを自動的に行うことができます。

  • npm

    265questions

    npmは、Node Packaged Modulesの略。Node.jsのライブラリ・パッケージを管理できるツールです。様々なモジュールを簡単にインストールでき、自分でモジュールを作成し公開する際にも使用できます。

Gulpで2つのタスクを1タスクにまとめるには?

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 230

Bonito_Bonito

score 60

Gulpのタスクをグルーピングしたいです。
Gulpでファイルを生成し、生成したファイルの変数をもとにシンボリックリンクを作成する一連のタスクを作るにはどのようにすればよいでしょうか?
下記が詳細になります。
説明がかなり長くなってしまい恐縮ではありますが、目的から順序立てて説明してまいります。

 01. 前提

Gulp を使用しています。開発はローカルで行っています。( browser-sync )

 02. 目的・実現したいこと

大目標としては、異なる子プロジェクトへのシンボリックリンクの作成です。
まず、 prj_name/ という親プロジェクトがあり、その下層に _master と _template という2つの子プロジェクトがあります。
ファイル構成は下記の様な構造になっております。
下記のように _template/ にも Gulp を入れてあり、目的としては _template/ で Gulp を実行する際に _master/ の共通アセット( A と B )を参照したいのです。

prj_name/
├── _master/
│  ├── _development/
│  │  ├── _assets/
│  │  │  ├── css/
│  │  │  │  └── style.css ← A
│  │  │  └── js
│  │  │     └── bundle.js ← B
│  │  └── index.html
│  └ gulpfile.js

└── _template/
   ├── _development/
   │  └── index.html
   └ gulpfile.js

上記の prj_name/ は、丸ごとリモートリポジトリに置いてあり、複数人が各自でローカルにクローンし、 _template/ を更新したり、複製・リネームして新規プロジェクトを作成するのですが、 _master/ に入っている JS や CSS などの共通アセットを _template/ や、その派生版のプロジェクトで使用することになっています。共通アセットは _template/ へ(単純にコピーするのではなく)シンボリックリンクとして配置したいのです。

各自がクローンするディレクトリの構造や名称も異なるため、例えば私のローカルのシンボリックリンクをコミットしても他の作業者では当然処理されません。そこで、クローンしたらまず最初に各自でシンボリックリンクの生成を作業の前に行ってもらうことになり、また、そのための Gulp のタスクを用意することになりました。

現段階では Gulp の設定の途中であり、 _template/ へのシンボリックリンクの作成のタスクと、シンボリックリンク作成に必要なJSファイルを生成するタスク自体は用意出来ており、その2つのタスクを順番に実行すれば作業者各自の最初の準備が完了する、というところまで出来ているため大きな問題という訳ではないのですが、 Gulp コマンドを2回も叩かせたくないので、この2つのタスクを1つのタスクにまとめたいのです。

ご教示いただきたいのは1つのタスクにまとめる方法です。
以下、回りくどくなるかとは思いますが順を追って説明してまいります。
この方法以外の代替手段で実現できるのであれば、別の手段でも構いませんm(_ _)m

 03. 現段階での Gulp の設定およびディレクトリの説明

_template/ でローカル作業をする際に localhost を立ち上げるので、 _master/ 
にある共通アセットは相対パスなどを駆使しても参照できません。(ホスト配下にないため…)
そのため、 _master/ にある共通アセットのシンボリックリンクを _template/ 内に作成する必要がありました。下記の A' と B' のようなイメージです。
(※ _master が完成品であれば、共通アセットをコピーするだけでも良いのですが、 _master はスタイルの追加などの更新がされているため、シンボリックリンクにて同期させる必要があります。今までは毎回コピーして上書きしていましたが、ストレージや作業効率の観点からNGとなりました。)

prj_name/
├── _master/
│  ├── _development/
│  │  ├── _assets/
│  │  │  ├── css/
│  │  │  │  └── style.css ← A
│  │  │  └── js
│  │  │     └── bundle.js ← B
│  │  └── index.html
│  └ gulpfile.js

└── _template/
   ├── _development/
   │  ├── _assets/
   │  │  └── _symbolic/
   │  │     ├── css/
   │  │     │  └── style.css ← A'
   │  │     └── js
   │  │        └── bundle.js ← B'
   │  └── index.html
   └ gulpfile.js

「 A と B のシンボリックリンクを A' と B' に作成する 」・・・
そのためには、シンボリックリンクの元となるファイル( = A と B )へのファイルパスを使用して、Gulp によって処理させています。

シンボリックリンクの元となるファイルのファイルパスを記述した、 './symlink_config.js' ( = C' )を用意し、それを元にシンボリックリンクの作成を行うことにしました。
※なぜ C' なのか(なぜダッシュを付けているのか)は、後に C が出てくるためです。
一時的に分かりづらいですがご容赦下さい。

prj_name/
├── _master/
│  └── _development/
│     └── _assets/
│        ├── css/
│        │  └── style.css ← A
│        └── js
│          └── bundle.js ← B

├── _template/
│  └── _development/
│     └── _assets/
│       └── _symbolic/
│          ├── css/
│          │  └── style.css ← A'
│          └── js
│             └── bundle.js ← B'

├── gulpfile.js
└── symlink_config.js ← C'

./symlink_config.js

module.exports = {
    commonPath : [
        '/Users/u_name/prj/prj_name/_master/_development/_assets/**/**.css',
        '/Users/u_name/prj/prj_name/_master/_development/_assets/**/**.js'
    ]
};

./symlink_config.js ( = C' )に記載されている値をもとに vinyl-fs で生成する、symlink というタスクを用意しました。

./gulpfile.js

var gulp = require('gulp');
var symlink = require('gulp-sym');
var vfs = require('vinyl-fs');
var symlink_config = require('./symlink_config');

gulp.task('symlink', function () {
    return vfs.src(symlink_config.commonPath, {followSymlinks: false})
    .pipe(vfs.symlink('_template/_development/_assets/_symbolic/'));
});

これにより( $ gulp symlink を実行することで) A' と B' は正常に作成されました。

しかし、 ./symlink_config.js ( = C' ) 内に記述している commonPath (クローンしたプロジェクトのあるローカルのファイルパスを入れている変数)は、作業者ごとにフォルダ構造やユーザー名が変わるため、作業する前に作業者ごとに ./symlink_config.js ( = C' ) を作成する必要があります。

これ(作業する前に作業者ごとに C を作成する作業)を手作業で行うのは手間なので、別のディレクトリに C' の元ファイルとなる 
./.origin_files/symlink_config.js ( = C )を用意し、それをもとに C' を作成することにしました。

prj_name/
├── _master/
│  └── _development/
│     └── _assets/
│        ├── css/
│        │  └── style.css ← A
│        └── js
│          └── bundle.js ← B

├── _template/
│  └── _development/
│     └── _assets/
│       └── _symbolic/
│          ├── css/
│          │  └── style.css ← A'
│          └── js
│             └── bundle.js ← B'

├── .origin_files/
│  └── symlink_config.js ← C

├── gulpfile.js
└── symlink_config.js ← C'

./.origin_files/symlink_config.js

module.exports = {
    commonPath : [
        'FILEPATH/_master/_development/_assets/**/**.css',
        'FILEPATH/_master/_development/_assets/**/**.js'
    ]
};

文字列 FILEPATH の部分は仮のファイルパスであり、タスクの実行の際に正規のファイルパスで書き換えを行うという考えです。

次に、このファイル( = C )を ./.origin_files/ から ./ へ dest し、その際に仮のファイルパスである文字列 FILEPATH が正規のファイルパスへ置換されるタスクとして、 symlink_config_create を用意しました。

./gulpfile.js

gulp.task('symlink_config_create', function() {
    return gulp
        .src(['./.origin_files/symlink_config.js'])
        .pipe(replace('FILEPATH', path.resolve()))
        .pipe(gulp.dest('./'));
});

これにより C' は正常に作成されました。

ここまでは正常に動作ています

  • $ gulp symlink_config_create
  • $ gulp symlink

いずれも、正常に動作します。
問題はここからとなります。

 04. 問題

問題というほどの問題ではないのですが、この2つのタスクは作業者が最初にクローンして npm install してからまずたたいてもらうものなので、手間がかかると感じています。
なので、この2つのタスクを1つにまとめたタスクを用意したいのです。

 04.01. この様にしたい

通常はタスクをグルーピングする場合、例えば、

./gulpfile.js

// CSSを納品用フォルダへ持っていく
gulp.task('css-dest', function () {
    return gulp.src('./css/*.css')
        .pipe(gulp.dest('./district/css'));
});

// JSを圧縮して納品用フォルダへ持っていく
gulp.task('js-dest', function () {
    return gulp.src(paths.js + '/**/*.js')
        .pipe(uglify())
        .pipe(gulp.dest('./district/js'));
});

などのタスクがあるとした場合、

./gulpfile.js

// いっぺんに納品用ファイルを生成する
gulp.task('dest', function () {
    gulp.run('css-dest');
    gulp.run('js-dest');
});

の様にして1つのタスクにできますよね?
これと同様に、前回用意してある2つのタスクをグルーピングした 'pj_init_1' というタスクを下記の様に用意しましたが…

 04.02. 試したこと

下記の通り、 Gulp にて3つほど試しています。

 04.02.01 試したこと その1 単純に

./gulpfile.js

gulp.task('pj_init_1', function () {
    gulp.run('symlink_config_create');
    gulp.run('symlink');
});

symlink_config_create までは正常に動作しています。
エラーの内容は下記のようなものです。

machine_name:prj_name u_name$ gulp pj_init_1
[18:09:42] Using gulpfile ~/prj/prj_name/gulpfile.js
[18:09:42] Starting 'pj_init_1'...
gulp.run() has been deprecated. Use task dependencies or gulp.watch task triggering instead.
[18:09:42] Starting 'symlink_config_create'...
[18:09:42] Starting 'symlink'...
[18:09:42] 'symlink' errored after 430 μs
[18:09:42] Error: Invalid glob argument: undefined
    at Object.src (/Users/u_name/prj/prj_name/node_modules/vinyl-fs/lib/src/index.js:20:11)
    at Gulp.<anonymous> (/Users/u_name/prj/prj_name/gulpfile.js:164:13)
    at module.exports (/Users/u_name/prj/prj_name/node_modules/orchestrator/lib/runTask.js:34:7)
    at Gulp.Orchestrator._runTask (/Users/u_name/prj/prj_name/node_modules/orchestrator/index.js:273:3)
    at Gulp.Orchestrator._runStep (/Users/u_name/prj/prj_name/node_modules/orchestrator/index.js:214:10)
    at Gulp.Orchestrator.start (/Users/u_name/prj/prj_name/node_modules/orchestrator/index.js:134:8)
    at Gulp.run (/Users/u_name/prj/prj_name/node_modules/gulp/index.js:22:14)
    at Gulp.run (/Users/u_name/prj/prj_name/node_modules/deprecated/index.js:9:17)
    at Gulp.<anonymous> (/Users/u_name/prj/prj_name/gulpfile.js:185:7)
    at module.exports (/Users/u_name/prj/prj_name/node_modules/orchestrator/lib/runTask.js:34:7)
[18:09:42] Finished 'pj_init_1' after 8.08 ms
[18:09:42] Finished 'symlink_config_create' after 18 ms
machine_name:prj_name u_name$

これは勝手な予想になりますが、 Gulp のタスクが並列に処理されているため、 symlink が動作するために必要な symlink_config.js の作成が間に合っていないためなのでしょうか。

 04.02.02 試したこと その2 タスクの直列処理

Gulp のタスクが並列に処理されている事が原因であると考え、単純に直列で動作するように下記の pj_init_2 というタスクを用意しました。

./gulpfile.js

var runSequence = require('run-sequence');
gulp.task('pj_init_2', function () {
    return runSequence(
        'symlink_config_create',
        'symlink'
    );
});

しかし、これも結果は pj_init_1 の時と同様に、 symlink_config_create までしか処理されません。

 04.02.03 試したこと その3 タスクの依存関係を考慮

他にも symlink が symlink_config_create に依存しているのではないかという理由で、第2引数に'symlink_config_create'を入れてみました。

./gulpfile.js

gulp.task('pj_init_3', ['symlink_config_create'], function() {
    gulp.run('symlink');
});

しかしながら、こちらもまた pj_init_1 や pj_init_2 と同様に、 symlink_config_create までしか処理されませんでした。

正常に処理させるためにはどうしたら良いでしょうか?
また、見落としやご指摘、アドバイスなどがあればご教示頂きたいです。
よろしくお願いいたしますm(_ _)m

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

check解決した方法

0

 自己解決

半ば強引ではありますが、下記のコードで希望していた動作が可能になりました。
※ 前述の pj_init 及び 'symlink_config_create' のタスクについては割愛しております。

./gulpfile.js

var child_process = require('child_process').exec;
gulp.task('pj_init', ['symlink_config_create'], function () {
    var cmd = "gulp symlink";
    child_process(cmd);
});

Node.js の child_process を使用しています。

参考 : これ便利!gulpfile.js でLinuxコマンドを記述して実行できるプラグ...

上記のコードでは symlink_config_create を実行する際に、用意してある symlink というタスクを Linux コマンドで実行させるものになります。
本来やりたかったタスクのグルーピングという手段とは若干ニュアンスが異なりますので、もしこれ以外に良い方法をご存知の方は以降もぜひご教示いただければと思います。

なお、本投稿課題 04.02.01 及び 04.02.03 に記載の gulp.run は現在非推奨となっている様です。
処理はされますが、下記の様な警告が吐き出されます。

gulp.run() has been deprecated. Use task dependencies or gulp.watch task triggering instead.

そのため、 gulp.run ではなく gulp.task にタスク同士の依存関係を定義する方法があるので、そちらに書き換える必要がある様です。

参考 : gulpその0002 gulp.runが3.5からdeprecated(非推奨)...

gulp.run の代替手段として、 gulp.task の第二引数に依存関係にあるタスクを配列で記述します。
つまり、 04.02.01 及び 04.02.03 は同じ処理となります。
04.02.03 については知識が追いついておらず、新旧手段の入り交じったタスクを作成してしまっておりました。

もし、単純に並列処理をグルーピングしたタスクを作成するのであれば、現時点で推奨されている記述方法では下記のような記述になるでしょう。

gulp.task('pj_init_1', ['symlink_config_create', 'symlink']);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

 05. Gulp の該当の記述部分全体('18.05.11 20:46 追記)

Gulp の設定の記述がバラバラで見通しが悪いかと思いましたので、念の為 Gulp の該当の記述部分すべてを掲載しておきます。(なお、本文への追記が文字数の不足により出来なかったためこちらに掲載しております、ご了承ください。)

/.gulpfile.js

var gulp = require('gulp');
var symlink = require('gulp-sym');
var vfs = require('vinyl-fs');
var symlink_config = require('./symlink_config');
var runSequence = require('run-sequence');

/**
 * オリジンからシンボリック元のファイルパスを置換して生成
 */
gulp.task('symlink_config_create', function() {
    return gulp
        .src(['./.origin_files/symlink_config.js'])
        // .pipe(replace('FILEPATH', process.cwd()))
        .pipe(replace('FILEPATH', path.resolve()))
        .pipe(gulp.dest('./'));
});

/**
 * シンボリックリンクを生成させるためのタスク
 */
gulp.task('symlink', function () {
    return vfs.src(symlink_config.commonPath, {followSymlinks: false})
    .pipe(vfs.symlink('_template/_development/_assets/_symbolic/'));
});

/**
 * 一つのタスク化
 * その1 単純にグルーピング
 * 結果
 * 'symlink_config_create'まではうまくいくが'symlink'でエラーに。
 */
gulp.task('pj_init_1', function () {
    gulp.run('symlink_config_create');
    gulp.run('symlink');
});

/**
 * 一つのタスク化
 * その2 直列処理
 * 結果
 * 'runSequence'によって直列処理にしてみたが、結果は同じ
 */
gulp.task('pj_init_2', function () {
    return runSequence(
        'symlink_config_create',
        'symlink'
    );
});

/**
 * 一つのタスク化
 * その3 依存関係を考慮
 * 結果
 * 第2引数に'symlink_config_create'を入れてみたものの、、結果は同じ
 */
gulp.task('pj_init_3', ['symlink_config_create'], function() {
    gulp.run('symlink');
});

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Node.js

    1806questions

    Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

  • gulp

    266questions

    gulpは、Node.jsをベースとしたタスク自動化ツールの一つ。ストリームでファイルを処理することが特徴です。CSSプリプロセッサの使用時のコンパイルや、CSS・JavaScriptファイルの圧縮・結合などを自動的に行うことができます。

  • npm

    265questions

    npmは、Node Packaged Modulesの略。Node.jsのライブラリ・パッケージを管理できるツールです。様々なモジュールを簡単にインストールでき、自分でモジュールを作成し公開する際にも使用できます。