web-dev-qa-db-ja.com

Gulp + WebpackまたはJUST Webpack?

私は人々がwebpackでgulpを使っているのを見ます。しかし、私はウェブパックを読んでgulpを置き換えることができますか?私はここで完全に混乱しています...誰かが説明できますか?

更新

最後に私はgulpから始めました。私は現代のフロントエンドには慣れておらず、すぐに立ち上がって実行したいと思っていました。 1年以上経っても足が濡れたので、webpackに移行する準備が整いました。私は同じ靴で始める人たちにも同じ道を提案します。あなたがwebpackを試すことができないと言っているのではなく、それが最初にgulpから複雑であるように思われるならばちょうどそれを言って...それについては何も悪いことではありません。

もしgulpが欲しくないなら、うんざりするでしょうが、最初に起動して実行するためだけに、package.jsonでコマンドを指定し、タスクランナーなしでコマンドラインからそれらを呼び出すこともできます。例えば:

"scripts": {
      "babel": "babel src -d build",
      "browserify": "browserify build/client/app.js -o dist/client/scripts/app.bundle.js",
      "build": "npm run clean && npm run babel && npm run prepare && npm run browserify",
      "clean": "rm -rf build && rm -rf dist",
      "copy:server": "cp build/server.js dist/server.js",
      "copy:index": "cp src/client/index.html dist/client/index.html",
      "copy": "npm run copy:server && npm run copy:index",
      "prepare": "mkdir -p dist/client/scripts/ && npm run copy",
      "start": "node dist/server"
    },
146
PositiveGuy

この答えは役に立つかもしれません。 タスクランナー(Gulp、Gruntなど)とバンドラー(Webpack、Browserify)。なぜ一緒に使うのですか?

...そして、これはgulpタスクの中からwebpackを使う例です。これはさらに一歩進んで、あなたのwebpack設定がes6で書かれていると仮定します。

var gulp = require('gulp');
var webpack = require('webpack');
var gutil = require('gutil');
var babel = require('babel/register');
var config = require(path.join('../..', 'webpack.config.es6.js'));

gulp.task('webpack-es6-test', function(done){
   webpack(config).run(onBuild(done));
});

function onBuild(done) {
    return function(err, stats) {
        if (err) {
            gutil.log('Error', err);
            if (done) {
                done();
            }
        } else {
            Object.keys(stats.compilation.assets).forEach(function(key) {
                gutil.log('Webpack: output ', gutil.colors.green(key));
            });
            gutil.log('Webpack: ', gutil.colors.blue('finished ', stats.compilation.name));
            if (done) {
                done();
            }
        }
    }
}

私はあなたのアプリがより複雑になるにつれて、あなたは上記の例のようにウェブパックタスクでgulpを使用したいと思うかもしれないと思うでしょう。これにより、Webpackローダーやプラグインでは実際にはできない、もっと面白いことを自分のビルドで行うことができます。簡潔に言うと、webpackは実際にこれらのことを実行できますが、長期的なニーズに合わせて制限されていることがあります。 gulp - > webpackから得られる最大の利点の1つは、さまざまな環境に合わせてWebpackの設定をカスタマイズし、gulpに適切なタイミングで適切なタスクを実行させることができることです。それは本当にあなた次第ですが、gulpからwebpackを実行しても問題はありません。実際、それを実行する方法のいくつかのすばらしい おもしろい 例があります。上記の例は基本的に jlong​​ster からのものです。

76
4m1r

NPMスクリプトはgulpと同じことができますが、コードが約50倍少なくなります。実際、コードはまったくなく、コマンドライン引数のみがあります。

たとえば、ユースケースでは、環境ごとに異なるコードが必要な場合について説明しました。

Webpack + NPMスクリプトでは、これは簡単です:

"prebuild:dev": "npm run clean:wwwroot",
"build:dev": "cross-env NODE_ENV=development webpack --config config/webpack.development.js --hot --profile --progress --colors --display-cached",
"postbuild:dev": "npm run copy:index.html && npm run rename:index.html",

"prebuild:production": "npm run clean:wwwroot",
"build:production": "cross-env NODE_ENV=production webpack --config config/webpack.production.js --profile --progress --colors --display-cached --bail",
"postbuild:production": "npm run copy:index.html && npm run rename:index.html",

"clean:wwwroot": "rimraf -- wwwroot/*",
"copy:index.html": "ncp wwwroot/index.html Views/Shared",
"rename:index.html": "cd ../PowerShell && elevate.exe -c renamer --find \"index.html\" --replace \"_Layout.cshtml\" \"../MyProject/Views/Shared/*\"",

開発モード用のwebpack.development.jsと本番モード用のwebpack.production.jsの2つのwebpack設定スクリプトを管理するだけです。私はまた、すべての環境で共有されるwebpack設定を格納するwebpack.common.jsを利用し、それらをマージするためにwebpackMergeを使用します。

NPMスクリプトはクールなので、Streams/pipeのgulpと同じように、簡単にチェーニングできます。

上の例では、開発用にビルドするために、あなたは単にあなたのコマンドラインに行き、npm run build:devを実行するだけです。

  1. NPMは最初にprebuild:devを実行します。
  2. build:dev
  3. そして最後にpostbuild:dev

preおよびpostの接頭部は、NPMに実行順序を指示します。

気付いたら、Webpack + NPMスクリプトを使えば、gulp-rimrafのようなネイティブプログラムのためのgulp-wrapperの代わりにrimrafのようなネイティブプログラムを実行することができます。私がここでelevate.exeを使って行ったようにネイティブのWindows .exeファイルを実行することも、LinuxまたはMac上でネイティブの* nixファイルを実行することもできます。

Gulpで同じことをやってみてください。誰かがやってくるのを待って、あなたが使いたいネイティブプログラムのためのgulp-wrapperを書く必要があるでしょう。さらに、たぶん次のような複雑なコードを書く必要があるでしょう。( angular2-seed repoから直接引用)

Gulp Development code

import * as gulp from 'gulp';
import * as gulpLoadPlugins from 'gulp-load-plugins';
import * as merge from 'merge-stream';
import * as util from 'gulp-util';
import { join/*, sep, relative*/ } from 'path';

import { APP_DEST, APP_SRC, /*PROJECT_ROOT, */TOOLS_DIR, TYPED_COMPILE_INTERVAL } from '../../config';
import { makeTsProject, templateLocals } from '../../utils';

const plugins = <any>gulpLoadPlugins();

let typedBuildCounter = TYPED_COMPILE_INTERVAL; // Always start with the typed build.

/**
 * Executes the build process, transpiling the TypeScript files (except the spec and e2e-spec files) for the development
 * environment.
 */
export = () => {
  let tsProject: any;
  let typings = gulp.src([
    'typings/index.d.ts',
    TOOLS_DIR + '/manual_typings/**/*.d.ts'
  ]);
  let src = [
    join(APP_SRC, '**/*.ts'),
    '!' + join(APP_SRC, '**/*.spec.ts'),
    '!' + join(APP_SRC, '**/*.e2e-spec.ts')
  ];

  let projectFiles = gulp.src(src);
  let result: any;
  let isFullCompile = true;

  // Only do a typed build every X builds, otherwise do a typeless build to speed things up
  if (typedBuildCounter < TYPED_COMPILE_INTERVAL) {
    isFullCompile = false;
    tsProject = makeTsProject({isolatedModules: true});
    projectFiles = projectFiles.pipe(plugins.cached());
    util.log('Performing typeless TypeScript compile.');
  } else {
    tsProject = makeTsProject();
    projectFiles = merge(typings, projectFiles);
  }

  result = projectFiles
    .pipe(plugins.plumber())
    .pipe(plugins.sourcemaps.init())
    .pipe(plugins.TypeScript(tsProject))
    .on('error', () => {
      typedBuildCounter = TYPED_COMPILE_INTERVAL;
    });

  if (isFullCompile) {
    typedBuildCounter = 0;
  } else {
    typedBuildCounter++;
  }

  return result.js
    .pipe(plugins.sourcemaps.write())
// Use for debugging with Webstorm/IntelliJ
// https://github.com/mgechev/angular2-seed/issues/1220
//    .pipe(plugins.sourcemaps.write('.', {
//      includeContent: false,
//      sourceRoot: (file: any) =>
//        relative(file.path, PROJECT_ROOT + '/' + APP_SRC).replace(sep, '/') + '/' + APP_SRC
//    }))
    .pipe(plugins.template(templateLocals()))
    .pipe(gulp.dest(APP_DEST));
};

Gulp Production code

import * as gulp from 'gulp';
import * as gulpLoadPlugins from 'gulp-load-plugins';
import { join } from 'path';

import { TMP_DIR, TOOLS_DIR } from '../../config';
import { makeTsProject, templateLocals } from '../../utils';

const plugins = <any>gulpLoadPlugins();

const INLINE_OPTIONS = {
  base: TMP_DIR,
  useRelativePaths: true,
  removeLineBreaks: true
};

/**
 * Executes the build process, transpiling the TypeScript files for the production environment.
 */

export = () => {
  let tsProject = makeTsProject();
  let src = [
    'typings/index.d.ts',
    TOOLS_DIR + '/manual_typings/**/*.d.ts',
    join(TMP_DIR, '**/*.ts')
  ];
  let result = gulp.src(src)
    .pipe(plugins.plumber())
    .pipe(plugins.inlineNg2Template(INLINE_OPTIONS))
    .pipe(plugins.TypeScript(tsProject))
    .once('error', function () {
      this.once('finish', () => process.exit(1));
    });


  return result.js
    .pipe(plugins.template(templateLocals()))
    .pipe(gulp.dest(TMP_DIR));
};

実際のGulpコードはこれよりはるかに複雑です。これはリポジトリにある数十のGulpファイルのうちの2つにすぎないからです。

だから、どちらがあなたにとって簡単ですか?

私の意見では、NPMスクリプトは有効性と使いやすさの両面でgulpとgruntをはるかに凌駕しています。フロントエンドの開発者は全員、ワークフローでの使用を検討する必要があります。

UPDATE

GulpをNPMスクリプトやWebpackと組み合わせて使用​​したいというシナリオが1つあります。

たとえばiPadやAndroidデバイスでリモートデバッグする必要がある場合は、追加のサーバーを起動する必要があります。これまで、IntelliJ IDEA(またはWebstorm)内からすべてのサーバーを別々のプロセスとして実行していましたが、これは "Compound"実行構成で簡単です。しかし、停止して再起動する必要がある場合は、5つの異なるサーバータブを閉じる必要があり、さらに出力が異なるウィンドウに分散されていました。

Gulpの利点の1つは、別々の独立したプロセスからのすべての出力を1つのコンソールウィンドウにチェーンできることです。これは、すべての子サーバーの親になります。

NPMスクリプトまたはコマンドを直接実行するだけの非常に単純なgulpタスクを作成したので、すべての出力が1つのウィンドウに表示され、gulpタスクウィンドウを閉じることによって5つのサーバーすべてを一度に簡単に終了できます。

Gulp.js

/**
 * Gulp / Node utilities
 */
var gulp = require('gulp-help')(require('gulp'));
var utils = require('gulp-util');
var log = utils.log;
var con = utils.colors;

/**
 * Basic workflow plugins
 */
var Shell = require('gulp-Shell'); // run command line from Shell
var browserSync = require('browser-sync');

/**
 * Performance testing plugins
 */
var ngrok = require('ngrok');

// Variables
var serverToProxy1 = "localhost:5000";
var finalPort1 = 8000;


// When the user enters "gulp" on the command line, the default task will automatically be called. This default task below, will run all other tasks automatically.

// Default task
gulp.task('default', function (cb) {
   console.log('Starting dev servers!...');
   gulp.start(
      'devserver:jit',
      'nodemon',
      'browsersync',
      'ios_webkit_debug_proxy'
      'ngrok-url',
      // 'vorlon',
      // 'remotedebug_ios_webkit_adapter'
   );
});

gulp.task('nodemon', Shell.task('cd ../backend-nodejs && npm run nodemon'));
gulp.task('devserver:jit', Shell.task('npm run devserver:jit'));
gulp.task('ios_webkit_debug_proxy', Shell.task('npm run ios-webkit-debug-proxy'));
gulp.task('browsersync', Shell.task(`browser-sync start --proxy ${serverToProxy1} --port ${finalPort1} --no-open`));
gulp.task('ngrok-url', function (cb) {
   return ngrok.connect(finalPort1, function (err, url) {
      site = url;
      log(con.cyan('ngrok'), '- serving your site from', con.yellow(site));
      cb();
   });
});
// gulp.task('vorlon', Shell.task('vorlon'));
// gulp.task('remotedebug_ios_webkit_adapter', Shell.task('remotedebug_ios_webkit_adapter'));

私の意見では、まだ5つのタスクを実行するためのかなりのコードがまだありますが、それは目的のために機能します。 1つ注意すべきことは、gulp-Shellios-webkit-debug-proxyのように、いくつかのコマンドを正しく実行していないようです。だから私はちょうど同じコマンドを実行するNPMスクリプトを作成しなければならなかった、そしてそれはうまくいく。

したがって、私は主にすべてのタスクにNPMスクリプトを使用しますが、一度に多数のサーバーを実行する必要があるときには、解決するためにGulpタスクを起動することがあります。正しい仕事のための正しい道具を選びなさい。

アップデート2

私は今、 同時に というスクリプトを使います。これは上記のgulpタスクと同じことをします。複数のCLIスクリプトを並行して実行し、それらすべてを同じコンソールウィンドウにパイプ接続します。非常に簡単に使用できます。繰り返しますが、コードは必要ありません(コードは同時にnode_module内にありますが、それを気にする必要はありません)。

// NOTE: If you need to run a command with spaces in it, you need to use 
// double quotes, and they must be escaped (at least on windows).
// It doesn't seem to work with single quotes.

"run:all": "concurrently \"npm run devserver\" nodemon browsersync ios_webkit_debug_proxy ngrok-url"

これは5つすべてのスクリプトを1つの端末にパイプで並列に実行します。驚くばかり!そのため、コードなしで同じタスクを実行するためのcliスクリプトが多数あるため、この時点では、gulpを使用することはめったにありません。

これらの記事を詳しく比較することをお勧めします。

77
TetraDev

私は私の異なるプロジェクトで両方のオプションを使用しました。

これはgulpwebpack - https://github.com/iroy2000/react-reflux-boilerplate-with-webpack を使ってまとめた定型句です。

私は他のプロジェクトでwebpacknpm tasksのみを使用しています。

そして、どちらもまったく問題なく動作します。そして、それはあなたのタスクがどれほど複雑か、そしてあなたがあなたの設定でどれだけのコントロールをしたいかにかかっていると思います。

たとえば、タスクが単純であれば、devbuildtest ...など(これは非常に標準的なものです)としましょう。単純なwebpacknpm tasksでまったく問題ありません。

しかし、あなたが非常に複雑なワークフローを持っていて、あなたがあなたの設定をもっと制御したいのであれば(それがコーディングされているので)、あなたはgulp routeに行くことができます。

しかし、私の経験からすると、webpackエコシステムは私が必要とするだけの十分な数のプラグインとローダーを提供しているので、gulpでしかできないことがない限り、最低限のアプローチを使うのが大好きです。また、システムに1つ少ないものがあれば、設定が簡単になります。

そして今日では、多くの人が実際にgulp and browsifyをすべてwebpackと一緒に置き換えているだけです。

8
R.R

正直なところ、両方を使用するのが最善だと思います。

  • Webpackすべての場合javascript関連しています。
  • Gulpすべての--- css関連しています。

私はまだwebpackでcssをパッケージ化するための適当な解決策を見つける必要があります、そして今のところ私はcssのためのgulpとjavascriptのためのwebpackを使用して満足です。

説明したように、私はnpmスクリプトを@Tetradevとしても使用します。特に私はVisual Studioを使っているので、そしてNPM Task runnerはきれいですが信頼できるWebpack Task Runnerはきれいですバグがある

2
Max Favilli

GulpとWebpackの概念はまったく異なります。 Gulpにフロントエンドコードを段階的にまとめる方法を指示しますが、Webpackに何を指示しますあなたは設定ファイルを通して欲しい。

これは私が違いについての私の理解を説明するために書いた短い記事(5分読む)です: https://medium.com/@Maokai/compile-the-front-end-from-gulp-to-webpack-) c45671ad87fe

当社はこの1年でGulpからWebpackに移行しました。時間がかかりましたが、Gulpで行ったことをすべてWebpackに移行する方法を見つけました。だから私たちにとって、GulpでしたことはすべてWebpackを通してもできるが、その逆はできない。

今日の時点では、Webpackを使用し、GulpとWebpackの混在を避けることをお勧めします。そうすることで、あなたとあなたのチームは両方を学び維持する必要がなくなります。

1
Maokai