Pos*_*Guy 151 node.js gulp webpack
我看到人们使用gulp和webpack.但后来我读到webpack可以取代gulp?我在这里完全糊涂了......有人可以解释一下吗?
UPDATE
最后我开始喝了一口气.我是现代前端的新手,只是想快速起步和跑步.现在,经过一年多的时间,我的脚已经湿透了,我已准备好转向webpack了.对于那些以同样的鞋子开始的人,我建议采用相同的方法.不是说你不能尝试webpack而只是说如果它看起来很复杂,那么先从gulp开始......没有错.
如果你不想要gulp,是的,那就是grunt,但是你也可以在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"
},
Run Code Online (Sandbox Code Playgroud)
4m1*_*m1r 78
这个答案可能有帮助. 任务运行者(Gulp,Grunt等)和Bundlers(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();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想你会发现,随着你的应用变得越来越复杂,你可能想要使用gulp和webpack任务,如上例所示.这允许你在你的构建中做一些更有趣的事情,webpack加载器和插件真的不做,即.创建输出目录,启动服务器等.嗯,简洁起来,webpack实际上可以做这些事情,但你可能会发现它们仅限于你的长期需求.从gulp - > webpack获得的最大优势之一是,您可以针对不同的环境自定义webpack配置,并让gulp在正确的时间执行正确的任务.它真的取决于你,但从gulp运行webpack没有任何问题,事实上有一些非常有趣的例子说明了如何做到这一点.上面的例子基本上来自jlongster.
Tet*_*Dev 78
NPM脚本可以像gulp一样运行,但代码少了50倍.实际上,根本没有代码,只有命令行参数.
例如,您描述的用例,您希望在不同环境中使用不同的代码.
使用Webpack + NPM Scripts,就是这么简单:
"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/*\"",
Run Code Online (Sandbox Code Playgroud)
现在您只需维护两个webpack配置脚本,一个用于开发模式,webpack.development.js另一个用于生产模式webpack.production.js.我还利用了一个webpack.common.js在所有环境中共享webpack配置的东西,并使用webpackMerge来合并它们.
由于NPM脚本很酷,它允许轻松链接,类似于吞咽/管道吞咽的方式.
在上面的示例中,要构建开发,只需转到命令行并执行即可npm run build:dev.
prebuild:dev,build:dev,postbuild:dev.在pre和post前缀告诉NPM其顺序执行.
如果您注意到,使用Webpack + NPM脚本,您可以运行本机程序,例如rimraf,而不是本机程序的gulp -wrapper,例如gulp-rimraf.您也可以像在此处使用本机Windows .exe文件一样运行elevate.exeLinux或Mac上的本机*nix文件.
尝试用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));
};
Run Code Online (Sandbox Code Playgroud)
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));
};
Run Code Online (Sandbox Code Playgroud)
实际的gulp代码要复杂得多,因为这只是repo中几十个gulp文件中的两个.
那么,哪一个更容易?
在我看来,NPM脚本在效率和易用性方面远远超过gulp和grunt,并且所有前端开发人员都应该考虑在他们的工作流程中使用它,因为它节省了大量时间.
UPDATE
我遇到过一个场景,我想将Gulp与NPM脚本和Webpack结合使用.
例如,当我需要在iPad或Android设备上进行远程调试时,我需要启动额外的服务器.在过去,我将所有服务器作为单独的进程运行,从IntelliJ IDEA(或Webstorm)中,使用"复合"运行配置很容易.但是,如果我需要停止并重新启动它们,必须关闭5个不同的服务器选项卡,加上输出分布在不同的窗口上是很繁琐的.
gulp的一个好处是可以将来自独立独立进程的所有输出链接到一个控制台窗口,该窗口成为所有子级服务器的父级.
所以我创建了一个非常简单的gulp任务,它只是直接运行我的NPM脚本或命令,因此所有输出都出现在一个窗口中,我可以通过关闭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'));
Run Code Online (Sandbox Code Playgroud)
在我看来,还有相当多的代码只是为了运行5个任务,但它可以用于此目的.一个问题是,gulp-shell似乎没有正确运行某些命令,例如ios-webkit-debug-proxy.所以我必须创建一个只执行相同命令的NPM脚本,然后它才能工作.
所以我主要使用NPM脚本完成我的所有任务,但偶尔当我需要同时运行一堆服务器时,我会启动我的Gulp任务来帮忙.为正确的工作选择合适的工具.
更新2
我现在使用一个名为concurrently的脚本,它与上面的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"
Run Code Online (Sandbox Code Playgroud)
这会将所有5个脚本并行传输到一个终端.真棒!所以在这一点上,我很少使用gulp,因为有很多cli脚本可以执行相同的任务而无需代码.
我建议你阅读这些文章,深入比较它们.
我在不同的项目中使用了这两个选项.
这里是一个样板,我放在一起用gulp用webpack- https://github.com/iroy2000/react-reflux-boilerplate-with-webpack.
我有一些其他项目只webpack用于npm tasks.
他们都完美无缺.而且我认为这可以归结为您的任务有多复杂,以及您希望在配置中拥有多少控制权.
例如,如果你的任务很简单,让我们说dev,build,test...等(这是非常标准的),你只需简单的完全正常webpack使用npm tasks.
但是如果你有非常复杂的工作流程并且你想要更多地控制你的配置(因为它是编码),你可以选择gulp route.
但根据我的经验,webpack生态系统提供了我需要的足够的插件和加载器,所以我喜欢使用最小的方法,除非你只能做一些事情.而且,如果您的系统中少了一些东西,它将使您的配置更容易.
很多时候,如今,我看到人们实际上gulp and browsify一起webpack单独替换所有人.
| 归档时间: |
|
| 查看次数: |
62042 次 |
| 最近记录: |