Gulp + Webpack или JUST Webpack?
Я вижу людей, использующих gulp с webpack. Но тогда я читаю, что webpack может заменить gulp? Я здесь полностью смущен... может кто-нибудь объяснить?
ОБНОВЛЕНИЕ
В конце я начал с gulp. Я был новичком в современном интерфейсе и просто хотел встать и бежать быстро. Теперь, когда у меня уже достаточно ноги, я готов переехать в webpack. Я предлагаю тот же маршрут для людей, которые начинаются в одной обуви. Не сказать, что вы не можете попробовать webpack, но просто говорите, если сначала кажется, что это сложно начать с gulp... ничего плохого в этом.
Если вы не хотите gulp, да там хрюкать, но вы также можете просто указать команды в своем пакете .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"
},
Ответы
Ответ 1
Этот ответ может помочь. Task Runners (Gulp, Grunt и т.д.) и Bundlers (Webpack, Browserify). Зачем использовать вместе?
... и вот пример использования webpack из задачи gulp. Это делается еще дальше и предполагает, что ваш конфигуратор 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, как показано выше. Это позволяет сделать еще несколько интересных вещей в вашей сборке, что загрузчики и плагины веб-пакетов действительно не делают, т.е. создание выходных каталогов, запуск серверов и т.д. Ну, чтобы быть кратким, веб-пакет действительно может делать эти вещи, но вы можете найти их ограниченными для своих долгосрочных потребностей. Одним из самых больших преимуществ, которые вы получаете от gulp → webpack, является то, что вы можете настроить свою конфигурацию webpack для разных сред и gulp сделать правильную задачу в нужное время. Это действительно зависит от вас, но нет ничего плохого в запуске webpack от gulp, на самом деле есть некоторые интересные интересные примеры того, как это сделать. Пример выше в основном состоит из jlongster.
Ответ 2
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, один для режима разработки, webpack.development.js
и один для режима производства webpack.production.js
. Я также использую webpack.common.js
, в котором размещена конфигурация webpack, доступная для всех сред, и используйте webpackMerge для их объединения.
Из-за прохлады сценариев NPM он позволяет легко связывать, подобно тому, как gulp выполняет потоки/трубы.
В приведенном выше примере, чтобы построить для разработки, просто перейдите в свою командную строку и выполните npm run build:dev
.
- NPM сначала запускает
prebuild:dev
,
- Затем
build:dev
,
- И, наконец,
postbuild:dev
.
Префиксы pre
и post
указывают NPM, который должен выполнить выполнение.
Если вы заметили, что с помощью сценариев Webpack + NPM вы можете запускать собственные программы, такие как rimraf
, вместо gulp -wrapper для собственной программы, например gulp-rimraf
. Вы также можете запускать родные файлы Windows.exe, как я здесь, с elevate.exe
или родными * nix файлами на Linux или Mac.
Попробуйте сделать то же самое с gulp. Вам придется подождать, пока кто-нибудь придет и напишет gulp -wrapper для собственной программы, которую вы хотите использовать. Кроме того, вам, скорее всего, понадобится написать свернутый код следующим образом: (взято прямо из angular2-seed repo)
Gulp Код разработки
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 Производственный код
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 код намного сложнее, так как это всего лишь 2 из нескольких десятков файлов gulp в репо.
Итак, какой из них вам легче?
По-моему, сценарии NPM намного превосходят gulp и хрюкают как по эффективности, так и по простоте использования, и все разработчики front-end должны рассмотреть возможность использования этого в своем рабочем процессе, потому что это важная экономия времени.
ОБНОВЛЕНИЕ
Существует один сценарий, с которым я столкнулся, когда хотел использовать gulp в сочетании с NPM-скриптами и Webpack.
Когда мне нужно выполнить удаленную отладку на устройстве iPad или Android, например, мне нужно запустить дополнительные серверы. Раньше я запускал все серверы как отдельные процессы, начиная с IntelliJ IDEA (или Webstorm), что легко с помощью "Настройка соединения". Но если мне нужно остановить и перезапустить их, было бы утомительно закрыть 5 разных вкладок сервера, плюс выход был распространен в разных окнах.
Одним из преимуществ gulp является то, что он может объединить все выходные данные от отдельных независимых процессов в одно консольное окно, которое становится родительским для всех дочерних серверов.
Итак, я создал очень простую задачу gulp, которая просто запускает мои сценарии NPM или команды напрямую, поэтому весь вывод появляется в одном окне, и я могу легко завершить все 5 серверов одновременно, закрыв задачу gulp окно.
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 задач, на мой взгляд, но это работает для этой цели. Одно из условий: gulp-shell
, похоже, не выполняет некоторые команды правильно, например ios-webkit-debug-proxy
. Поэтому мне пришлось создать NPM Script, который просто выполняет ту же команду, а затем он работает.
Поэтому я в первую очередь использую скрипты NPM для всех своих задач, но иногда, когда мне нужно запускать несколько серверов одновременно, я запускаю свою задачу gulp, чтобы помочь. Выберите подходящий инструмент для правильной работы.
Предлагаю вам ознакомиться с этими статьями, в которых их можно сравнить по глубине.
Ответ 3
Я использовал оба варианта в разных проектах.
Вот один шаблон, который я собрал, используя gulp
с webpack
- https://github.com/iroy2000/react-reflux-boilerplate-with-webpack.
У меня есть другой проект, который используется только webpack
с npm tasks
.
И они оба прекрасно работают. И я думаю, что это сгорит до того, насколько сложна ваша задача и какой контроль вы хотите иметь в своей конфигурации.
Например, если ваши задачи просты, скажем dev
, build
, test
... и т.д. (что очень стандартно), вы совершенно в порядке с простым webpack
с npm tasks
,
Но если у вас очень сложный рабочий процесс, и вы хотите иметь больше контроля над своей конфигурацией (потому что это кодирование), вы можете пойти на маршрут gulp.
Но, по моему опыту, экосистема webpack обеспечивает более чем достаточно плагинов и загрузчиков, которые мне понадобятся, и поэтому мне нравится использовать минимальный минимальный подход, если только в gulp вы ничего не можете сделать. Кроме того, это упростит вашу конфигурацию, если в вашей системе будет меньше всего.
И много раз, в настоящее время, я вижу, что люди фактически заменяют gulp and browsify
все вместе с webpack
.