JavaScript构建(编绎)系统大比拼:Grunt vs. Gulp vs. NPM

 Nicolas Bevacqua进行了一个比较JavaScript构建(编绎)系统的任务。他对三巨头: Grunt, Gulp and NPM进行了比较,并讨论了每种的优缺点。

  By Nicolas Bevacqua

  决定采用何种技术总是很难的。一旦遇到问题,你不想推翻你之前的选择。但是你必须选一个,然后让它按照着你的思路做。实施一套构建(编绎)系也是一样的,你应该把它看作一个非常重要的选择,让我们以Grunt为例。

  • Grunt有一个完善的社区,即使是在Windows上
  • 它不仅仅应用在Node社区
  • 它简单易学,你可以随便安装插件并配置它们
  • 你不需要多先进的理念,也不需要任何经验

  这些都是用Grunt构建编绎工具的充分理由,但我想澄清一点,我不认为Grunt不是唯一最好的选择。还有一些同样流行的选择摆在那里,有些方面可能比Grunt做得更好。

  我写这篇文章,以帮助您了解Grunt,Gulp和npm之间的差异,这是我在前端开发工作中使用最多的三种构建工具。

 我们先来讨论Grunt擅长的方面

  Grunt:好的部分

  Grunt最好的一个方面是它的易用性。它能使程序员使用JavaScript构建编绎工具时,几乎不费吹灰之力。你只需要寻找合适的插件,阅读它们的文档,然后安装和配置它。这种易用性意味着大型开发团队,那些不同技能水平的成员,也可以没有任何麻烦的调整编绎流程,以满足项目的最新需求。而且团队并不需要精通Node,他们仅需要配置对象,将不同的任务添加到不同的序列构建编绎流程。

  这里有基础足够大的插件库,你会发现自己几乎不需要开发自己的编译任务,这能使您和您的团队能够快速构建开发工具,如果你要快速完成编绎过程这是至关重要的,你也可以采取小步走,逐步完善编译流程的策略。

  通过Grunt管理部署也是可行的,因为有许多包已经可以完成这些任务,如 grunt-git, grunt-rsync, 或 grunt-ec2 等等。

  那么,Grunt有什么缺陷吗?如果你有一个明显复杂的编绎过程,它可能会变得过于冗长。当开发一段时间以后,它往往很难将编绎过程作为一个整体。一旦你编绎流程任务到达两位数,几乎可以保证,你会发现自己不得不在多个目标(Targets)中跑同一个Task,以便你能够正确地执行任务流。由于任务是需要声明配置的,你也很难弄清楚任务真正的执行次序。

  除此之外,你的团队应该致力于编写可维护的代码,当涉及到你的编绎,比如在使用Grunt的情况下,这意味着你需要为每个任务(或者每个编绎流)编写一份独立的配置文件,供你的团队使用。

  现在,我们已经了解了Grunt好和不好的方面,以及在何种情况下,比较适合作为你项目的编绎工具。我们再来谈谈npm,它如何被用作构建工具,以及与Grunt有何不同。

 将npm视为构建工具

  为了将NPM用作构建工具,你需要一个package.json和npm。制定NPM任务就像在脚本中添加属性一样简单。该属性的名称将用作任务名和将要执行的命令。下面的这个build任务将预先检查我们的JavaScript代码中有没有语法错误,例子使用JSHint命令行接口来。在命令行中你可以运行任何你需要的shell。

{
  "scripts": {
    "test": "jshint . --exclude node_modules"
  },
  "devDependencies": {
    "jshint": "^2.5.1"
  }
}

  一旦定义完成,就可以通过下面的命令来运行

npm run test

  需要注意的是npm提供了运行特定任务的快捷方式。比如要运行test,你可以简单地使用npm test并省略动词run。您可以通过一个命令链来将一系列npm run的任务连在一起,构成你的编绎流程:

{
  "scripts": {
    "lint": "jshint . --exclude node_modules",
    "unit": "tape test/*",
    "test": "npm run lint && npm run unit"
  },
  "devDependencies": {
    "jshint": "^2.5.1",
    "tape": "~2.10.2"
  }
}

  您也可以安排一些后台完成的任务,然后让他们同步。假设我们有以下的包文件,我们将复制出一个目录用来放JavaScript文件,以及将我们用Stylus写的样式表文件编绎成CSS。在这种情况下,多个任务一起运行是比较理想的。也可以实现,使用&分隔符即可。

{
  "scripts": {
    "build-js": "cp -r src/js/vendor bin/js",
    "build-css": "stylus src/css/all.styl -o bin/css",
    "build": "npm run build-js & npm run build-css"
  },
  "devDependencies": {
    "stylus": "^0.45.0"
  }
}

  要了解关于将npm用作构建工具的更多内容,你应该先学学写一些Bash命令。

  安装NPM的任务依赖

  JSHint CLI并不一定要包含在你的系统中,这里有两种安装它的方式。如果你正在寻找直接从命令行中运行的工具,那么你应该在全局范围内安装,使用g标志,如下所示。

npm install -g jshint

  不过,如果您使用的是包在npm run中使用的,那么你就应该把它加到devDependency中,如下所示。这将让npm自动在系统中寻找它所依赖的JSHint安装在了哪里。这方法适用于任何命令行工具中和所有操作系统。

npm install --save-dev jshint

  你其实不仅局限使用CLI工具。事实上,npm能够运行任何shell脚本。让我们来挖一挖!

  在npm中使用shell脚本

  下面是一个运行在node的脚本,并显示一个随机的绘文字符串(emoji-random)。第一行指定运行环境,该脚本基于Node。

#!/usr/bin/env node
var emoji = require(‘emoji-random‘);
var emo = emoji.random();
console.log(emo);

  如果你将一个名为emoji的脚本文件放到你项目的根目录中,你必须将emoji-random申报为依赖关系,并将以下脚本命令添加到包文件中。

{
  "scripts": {
    "emoji": "./emoji"
  },
  "devDependencies": {
    "emoji-random": "^0.1.2"
  }
}

  一旦写成这样,你只需要在命令行运行 npm run emoji 即可。

  好和坏的方面

  使用NPM作为构建工具比Grunt有几大优势。你不会被Grunt的插件束缚,你可以利用NPM的所有优势,它有数以万计的模块可以选择。除了NPM,你不需要任何额外的命令行工具(CLI)或文件,你只需要在package.json添加依赖关系。由于NPM运行命令行工具(CLI 工具)和Bash命令,这比Grunt执行的方式更好。

  Grunt的最大缺点之一就是它的I/O限制。这意味着大多数Grunt的任务将从磁盘中读取,再写入到磁盘。如果你的多个任务需要操作同一个文件,那么该文件很有可能被从磁盘中多次读取。在bash中,命令通过管道直接传递给下一个任务,避免Grunt额外的I/O开销。

  也许NPM的最大的缺点是,在Windows环境中的应用可能没那么好。这意味着使用NPM运行的开源项目可能遇到问题。这也意味着Windows开发人员尝试使用npm的替代品。这缺点几乎将NPM从Windows上排除。

  Gulp,另一个构建工具,提出了与Grunt和npm相似的功能,一会你就会发现。

 Gulp的流式构建工具

  与Grunt类似,它依赖插件,并且是跨平台的,它也支持Windows。Gulp是一个代码驱动的构建工具,与Grunt的声明式定义任务相反,它的任务定义更容易阅读一点。Gulp也有类似于npm run的东西,因为它使用Node Stream来转化输入输出。这意味着,Gulp没有Grunt那种磁盘密集型I/O操作的问题。它也是它比Grunp更快的原因,更少的时间花在I/O上面。

  在使用Gulp的主要缺点是,它在很大程度上依赖于流,管道和异步代码。不要误解我的意思:如果你用在Node中,这绝对是一个优势。但是,除非你和你的团队非常精通Node,你很有可能会遇到处理流的问题,特别是如果你要建立你自己的Gulp任务插件。

  在团队工作的时候,Gulp不是望而却步的npm,因为大多数前端团队可能都懂JavaScript,但是他们可能对Bash脚本不那么熟练,其中一些可能是使用Windows的!这就是为什么我通常建议你在个人项目中运行NPM的原因。如果你的团队很熟悉Node,你可以使用Gulp。当然,这是我个人的建议,你应该找到最适合你和你团队的工具。此外,你应该不会把自己限制在Grunt,Gulp,或者npm run中,对你我来说这些都只是工具。尝试做一些小小的研究,也许你会发现,你喜欢的甚至比这三个更好的工具。

  让我们通过一些例子来看看Gulp中的任务看起来是什么样子的。

  在Gulp中运行测试

  有一些约定Gulp与Grunt极为相似。在Grunt中有一个定义Task的文件Gruntfile.js,在Gulp中叫Gulpfile.js。另一种微小的差别是,在Gulp中,CLI已经包含在同一个Gulp包中,你需要通过npm从本地和全局同时安装。

touch Gulpfile.js
npm install -g gulp
npm install --save-dev gulp

  在开始之前,我将创建一个Grulp任务处理一个JavaScript文件,就像你已经在Grunt和NPM中看到的那样使用JSHint,你需要先安装gulp-jshint,Gulp的JSHint插件。

npm install --save-dev gulp-jshint

  现在你已经同时在全局和本地中装好CLI了,本地已经安装了gulp和gulp-jshint插件,你可以将这些构建任务合成一个。你可以在Gulpfile.js文件中写出来。

  首先,您将使用gulp.task定义一个任务和功能。该功能包含了所有必要的代码来运行这项测试。在这里,你应该使用gulp.src创建一个读取你源文件的流,这个数据流会被管道输送进JSHint插件。然后,所有你需要做的就是管道中的JSHint任务打印到终端。下面是Gulpfile中展示的结果。

var gulp = require(‘gulp‘);
var jshint = require(‘gulp-jshint‘);
gulp.task(‘test‘, function () {
  return gulp
    .src(‘./sample.js‘)
    .pipe(jshint())
    .pipe(jshint.reporter(‘default‘));
});

  还有一点需要提一下,Grulp流会在一个任务完全结束之后再转到下一个任务。你可以使用一个JSHint Reporter使输出更加简洁,从而更易于阅读。 JSHint Reporter并不需要Grulp插件,例如jshint-stylish,让我们在本地直接安装。

npm install --save-dev jshint-stylish

  更新后的Gulpfile应如下所示。它会加载jshint-stylish模块,按报表格式输出。

var gulp = require(‘gulp‘);
var jshint = require(‘gulp-jshint‘);
gulp.task(‘test‘, function () {
  return gulp
    .src(‘./sample.js‘)
    .pipe(jshint())
    .pipe(jshint.reporter(‘jshint-stylish‘));
});

  大功告成!这是所有一个命名为test的Gulp的任务。它可以使用下面的命令运行,只要你安装了全局的CLI。

gulp test

  这是一个相当简单的例子。你也可以通过使用gulp.dest,创建了一个写数据流到磁盘中。让我们看看另外一个构建任务。

  在Grulp中创建一个库

  在开始之前,让我们明确任务:从磁盘gulp.src读取源文件并通过磁盘管道写回内容到gulp.dest,你可以理解成只是将文件复制到另一个目录。

var gulp = require(‘gulp‘);
gulp.task(‘build‘, function () {
  return gulp
    .src(‘./sample.js‘)
    .pipe(gulp.dest(‘./build‘));
});

  复制文件完成了,但是它没有压缩这个JS文件。要做到这一点,你必须使用一个Gulp插件。在这种情况下,你可以使用gulp-uglify,流行的UglifyJS压缩编绎插件。

var gulp = require(‘gulp‘);
var uglify = require(‘gulp-uglify‘);
gulp.task(‘build‘, function () {
  return gulp
    .src(‘./sample.js‘)
    .pipe(uglify())
    .pipe(gulp.dest(‘./build‘));
});

  正如你可能意识到的那样,流使可以让您添加更多的插件,而只需要读取和写入磁盘一次。你也可以指定缓冲器中内容的大小。需要注意的是,如果你在压缩之前添加它,那么你得到的大小是unminified。

var gulp = require(‘gulp‘);
var uglify = require(‘gulp-uglify‘);
var size = require(‘gulp-size‘);
gulp.task(‘build‘, function () {
  return gulp
    .src(‘./sample.js‘)
    .pipe(uglify())
    .pipe(size())
    .pipe(gulp.dest(‘./build‘));
});

  为了增强这种组合,满足添加或删除管道的需要,让我们添加最后一个插件。这一次,我会用gulp-header在头文件添加一段版权信息的代码,如名称,版本和许可证类型。

var gulp = require(‘gulp‘);
var uglify = require(‘gulp-uglify‘);
var size = require(‘gulp-size‘);
var header = require(‘gulp-header‘);
var pkg = require(‘./package.json‘);
var info = ‘// <%= pkg.name %>@v<%= pkg.version %>, <%= pkg.license %>\n‘;
gulp.task(‘build‘, function () {
  return gulp
    .src(‘./sample.js‘)
    .pipe(uglify())
    .pipe(header(info, { pkg : pkg }))
    .pipe(size())
    .pipe(gulp.dest(‘./build‘));
});

  就像Grunt一样,在Grulp中你可以通过传递一组任务到gulp.task来定义流程。在这方面,Grunt和Grulp之间的主要区别在于,Grunt是同步的,而Grulp是异步的。

gulp.task(‘build‘, [‘build-js‘, ‘build-css‘]);

  在Gulp,如果你要让任务同步运行,你必须声明一个任务。你的任务开始之前执行。

gulp.task(‘build‘, [‘dep‘], function () {
  // 执行dep所依辣的任务
});

  如果你有任何收获,先看看这段话。

你使用哪种工具并不重要,只要保证:流程构建(编绎)好用就行了,用起来不要太辛苦。

  原文地址: http://modernweb.com/2014/08/04/choose-grunt-gulp-npm

时间: 2024-11-09 02:41:19

JavaScript构建(编绎)系统大比拼:Grunt vs. Gulp vs. NPM的相关文章

Grunt javascript世界的构建工具(一)——Grunt使用入门 (by vczero)

一.前言 项目中一直在使用Grunt,只是对Grunt的基本使用,却未系统的总结过.为什么要构建工具?一句话:自动化.对于需要反复重复的任务,例如压缩(minification).编译.单元测试.linting等,自动化工具可以减轻你的劳动,简化你的工作.当你正确配置好了任务,任务运行器就会自动帮你或你的小组完成大部分无聊的工作.为什么要使用Grunt.Grunt生态系统非常庞大,并且一直在增长.由于拥有数量庞大的插件可供选择,因此,你可以利用Grunt自动完成任何事,并且花费最少的代价.如果找

Grunt javascript世界的构建工具(二)——Grunt项目实战 (by vczero)

一.前言 继上篇:Grunt javascript世界的构建工具(一)——Grunt使用入门,这次用一个开源项目的Grunt例子作为述说.现在互联网公司大型的JS项目,如web app.PC.前端工程庞大的项目都在使用Grunt,有了Grunt利剑在手你才能说自己能够快速的构建前端功能,当然不是专职的前端团队除外,不过呢,还是极力向你推荐Grunt.如今,Grunt作为团队的前端工具已是标配了,不论是JS API.还是web app等等.废话不多说,这里举的例子是heatmap.js的grunt

前端开发自动化工作流工具:JavaScript自动化构建工具grunt、gulp、webpack介绍

前端开发自动化工作流工具,JavaScript自动化构建工具grunt.gulp.webpack介绍 前端自动化,这样的一个名词听起来非常的有吸引力,向往力.当今时代,前端工程师需要维护的代码变得及为庞大和复杂,代码维护.打包.发布等流程也变得极为繁琐,同时浪费的时间和精力也越来越多,当然人为的错误也随着流程的增加而增加了更多的出错率.致使每一个团队都希望有一种工具,能帮助整个团队在开发中能精简流程.提高效率.减少错误率.随之讨论自动化部署也越来越多,并且国内很多大型团队也都有自己成熟的自动化部

JavaScript自动化构建工具入门----grunt、gulp、webpack

蛮荒时代的程序员: 做项目的时候,会有大量的js 大量的css   需要合并压缩,大量时间需要用到合并压缩 在前端开发中会出现很多重复性无意义的劳动 自动化时代的程序员: 希望一切都可以自动完成 安装 常用插件.压缩插件.合并插件等.  用插件实现 功能无限扩展 简单介绍三种工具 grunt 是js任务管理工具(自动化构建工具)    -- Grunt官网 戳这里 优势:出来早 社区成熟  插件全 缺点:配置复杂   效率低 (cpu占用率高) -------------------------

ASP.NET5之客户端开发:Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用

Grunt和Gulp是Javascript世界里的用来做自动压缩.Typescript编译.代码质量lint工具.css预处理器的构建工具,它帮助开发者处理客户端开发中的一些烦操重复性的工作.Grunt和Gulp都在Visual studio 2015中得到支持.ASP.NET 项目模板默认使用Gulp. Grunt和Gulp Grunt和Gulp有什么区别?Gulp虽然是稍微晚一点登场的,但是它因crisp performance和优雅的语法受到欢迎.与Grunt不同,Grunt往往在硬盘上是

121-基于TI DSP TMS320DM8148的全高清1080P 60fs的视频编解码系统 机器人主板

基于TI DSP TMS320DM8148的全高清1080P 60fs的视频编解码系统 一.板卡概述 本系统基于最先进的DSP技术,构建一个全高清的视频编解码系统,采用TI的芯片.借助TI的DaVinci™ 处理器技术来满足处理包括: 高清视频会议网络电话终端, 视频监控用数字视频录像机(DVR), IP 网络摄像机(Netcam), 数字标识, 媒体播放器/适配器,便携医疗成像, 网络投影仪, 和家庭音频/视频设备等情况下的广泛应用.  TMS320DM814x DaVinci™ 数字媒体处理

Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用

Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用 Grunt和Gulp是Javascript世界里的用来做自动压缩.Typescript编译.代码质量lint工具.css预处理器的构建工具,它帮助开发者处理客户端开发中的一些烦操重复性的工作.Grunt和Gulp都在Visual studio 2015中得到支持.ASP.NET 项目模板默认使用Gulp. Grunt和Gulp Grunt和Gulp有什么区别?Gulp虽然是稍微晚一点登场的,但是它因crisp pe

构建前端用户系统之登录退出

前端页面中难免会有一些静态HTML文件, 这时就会遇到用户状态的判断问题, 于是想到使用js的ajax请求来处理整个前端用户相关的东东...版本一 思路是在页面中指定位置预留一个js钩子, 然后在页面加载完成后向后端发送ajax请求, 判断用户是否登录, 并写到钩子里相应文本. 于是版本一产生了... (function($){ var user = window.user = {}; // 用户数据 user.data = {}; // 用户状态, 0未登录, 非0则视为已登录, 可扩展为用户

基于 VNCServer + noVNC 构建 Docker 桌面系统

by Falcon of TinyLab.org 2015/05/02 简介 基于 ssh + Xpra 构建 Docker 桌面系统 刚介绍了如何通过 Ssh + Xpra 构建 C/S 架构的 Docker 桌面系统. 本文介绍另外一种 B/S 架构的 Docker 桌面系统,即基于 VNCServer + noVNC 构建一个可以通过浏览器直接访问的 Docker 桌面系统. noVNC VNCServer 是一个为了满足分布式用户共享服务器资源,而在服务器开启的一项服务,对应的客户端软件