内容简介:为什么我放弃 Gulp 和 Grunt 而使用 npm Scripts
我知道你在想什么。 什么?!Gulp不是刚刚干掉了Grunt吗? 为什么我们不能在Javascript的地盘上消停一会儿呢?我知道,但是…
我发现Gulp和Grunt是没有必要的抽象,npm Script 已经足够强大,并且通常更好用。
让我们从一个例子开始
我原来是一个Gulp的超级粉丝。但是在我的最近一个项目中, 最终我的 gulpfile 中有几百行代码和一大堆 Gulp 插件。我曾经为了用 Gulp 整合 Webpack、Browsersync、hot reloading、Mocha等等东西而需要花费很多尽力。为什么? 好吧,有些插件的文档没覆盖到我的使用场景。有些插件只公开了部分我需要的API。有个插件有一个奇怪的bug,它能监视的文件数很小。另一个插件则在命令行中输出信息时把颜色都给去掉了。
这些都是可以解决的问题, 但是我在直接调用这些 工具 的时候,一个问题也没有出现。
后来我注意到很多开源的项目都直接使用了 npm Scripts 。我决定退一步重新评估,我真的需要Gulp吗?结果证明我不需要。
我决定在我新的开源项目上尝试使用 npm Scripts。我创建了一个富开发环境,并只用 npm Scripts 为 React 应用创建了一个进程。好奇是什么样子? 请查看 React Slingshot 。 我将在 Pluralsight (愚人码头注:一家美国软件开发在线教育网站) 的 “ 构建JavaScript开发环境 ” 中介绍如何使用 npm Scripts 来创建构建过程。
令人惊讶的是,相比Gulp,我现在更喜欢使用 npm Scripts 来 Gulp。 这是为什么。
Gulp和Grunt有什么问题?
用了一段时间后,我发现类似 Gulp 和 Grunt 的任务执行工具有三个主要的问题:
- 依赖插件作者
- 难以调试
- 脱节的文档
我们先来思考一下这些问题。
问题#1: 依赖插件作者
当你使用新技术或者不流行的技术时,可能根本没有相关的插件。即使有插件,它可能已经过时了。例如,Babel 6 最近发布了。API改变了不少,所以很多 Gulp 插件不兼容最新的版本。使用 Gulp 的时候,我经常束手无策,因为我需要的 Gulp 插件还没更新。
Gulp 和 Grunt 遇到问题你通常都要等作者提供更新,或者自己修复。这会延迟您使用新版本的现代工具。这限制了你使用很多流行工具的最近版本。相比之下, 当我使用 npm Scripts 时,我直接使用工具,而没有额外的抽象层。 这意味着,当Mocha,Istanbul,Babel,Webpack,Browserify等工具新版本发布时,我可以立即使用新版本。
在插件数量方面,跟 npm 没有相比性:
Gulp 大约有 2,100个插件。 Grunt 大约有 5,400 个。 npm提供超过227,000个包,而且每天以400+的速度增长。
当您使用 npm Scripts 时,您不需要搜索 Grunt 或 Gulp 插件。您可以选择 227,000+ 的 npm 包。
公平起见,如果你需要的 Grunt 或 Gulp 插件不可用,你可以直接使用 npm 包。但是,你不再需要利用 Gulp 或 Grunt 来完成这个特定的任务。
问题#2: 难以调试
使用 Grunt 和 Gulp 构建失败时,调试是比较麻烦的。因为你是多了一层额外的抽象层,所以引发bug的潜在原因将更多:
- 是不是基础工具出错了?
- 是不是 Grunt / Gulp 插件出错了?
- 是不是我的配置错了?
- 是不是我用了不兼容的版本?
使用 npm Scripts 不会出现问题2,并且我发现问题3也很少出现,因为我一般直接调用工具的命令行接口。最重要的是,我直接使用 npm 代替任务运行器的抽象后,我项目中包的数量减少了,因此问题4也很少出现。
问题#3:脱节的文档
我需要的核心工具的文档几乎总是比相应的 Grunt 和 Gulp 插件文档的要好。例如,如果我使用 gulp-eslint 时,我需要将时间分别花在 gulp-eslint 文档和 ESLint 网站上。 我必须在插件和它抽象的工具之间来回切换上下文。 Gulp 和 Grunt 中的核心的痛点是:
只了解工具是远远不够的。Gulp 和 Grunt 还要求你理解插件的抽象概念。
大多数构建相关的工具提供了清晰,强大和具有完善文档的命令行接口。看看 ESLint 的 CLI 文档 就是一个很好的例子。我发现在 npm Scripts 中阅读并且实现一个简短的命令行调用会更清晰,低冲突,并且更容易调试(因为没有了一层抽象).
现在我已经列出了所有痛点,问题是,为什么我们还会认为我们需要像 Gulp 和 Grunt 之类的任务执行器?
为什么我们忽略了npm的构建功能?
我认为有四个关键的误解导致 Gulp 和 Grunt 变得这么流行:
- 人们认为使用 npm Scripts 需要很高的命令行编写能力
- 人们认为 npm Scripts 不够强大
- 人们认为 Gulp 的流处理对快速构建来说是必不可少的
- 人们认为 npm Scripts 不能跨平台运行
让我们一个一个消除这些误解。
误解#1:npm Scripts 需要很高的命令行编写能力
要享受使用 npm Scripts 的力量,你不需要掌握很多有关操作系统的命令行。当然, grep,sed,awk 和 pipe 是值得学习终身受用的技能,但要使用 npm Scripts 你也不用成为 Unix 或者 Windows 命令行大师。你也可以使用 npm 中的数千个包来完成工作。
例如,你可能不知道在 Unix 中强制删除的命令行是:rm -rf。不过没关系。 你可以使用 rimraf 来完成相同的工作(并且它可以跨平台使用)。大多数 npm 包是在假设你对操作系统命令行知识知之甚少的前提下提供接口。当你要用某个功能的时候,只需要在 npm 上搜索你需要的包,阅读文档,学习即可。我之前都是搜索Gulp插件,现在我搜索 npm 包。顺便提供一个不错的资源: libraries.io
误解#2: npm Scripts 不够强大
npm Scripts 其实是很强大的。这些是常规的 pre和post钩子 :
{ "name": "npm-scripts-example", "version": "1.0.0", "description": "npm scripts example", "scripts": { "prebuild": "echo I run before the build script", "build": "cross-env NODE_ENV=production webpack", "postbuild": "echo I run after the build script" } }
你所需要做的就是遵循约定。上面的脚本会根据前缀按顺序执行。prebuild 脚本会在 build 脚本之前执行,它对比 build 脚本有前缀 ”pre”,而 post 脚本会在 build 脚本后面执行因为有前缀 ”post” 。所以如果我创建了 Scripts : prebuild
, build
和 postbuild
,当我输入 npm run build
时,它们将会自动按顺序执行。
你也可以通过调用另一个脚本,把一个大任务拆分:
{ "name": "npm-scripts-example", "version": "1.0.0", "description": "npm scripts example", "scripts": { "clean": "rimraf ./dist && mkdir dist", "prebuild": "npm run clean", "build": "cross-env NODE_ENV=production webpack" } }
上面的例子中, prebuild
任务调用了 clean
任务。这允许你把你的脚本拆分成更小、命名更恰当、单一职责、一行内完成。
你可以使用 &&
操作符将多个 Scripts 串联成一行。 在上述的 clean
步骤将会顺序执行各个 Scripts 。如果你曾经为了让任务列表能在 Gulp 中按顺序执行而苦苦挣扎过,那么这种简洁真的会让你笑出声来。
并且如果一个命令实在太复杂了,你也可以调用其他的文件:
{ "name": "npm-scripts-example", "version": "1.0.0", "description": "npm scripts example", "scripts": { "build": "node build.js" } }
上面的例子中,我在 build
任务中调用了一个独立的脚本。这个脚本将会通过Node执行, 而且因此我可以应用任何我需要的 npm 包, 并且应用所有 JavaScript 中的功能。
我就不继续说了, 主要的特性都在这里 。还有,这里还有 一个 npm 作为构建工具的简短介绍 , 或者查看 React Slingshot 项目并将其当作所有这些行为的一个例子。
误解#3: Gulp 的流处理对快速构建来说是必不可少的
Gulp可以从Grunt上快速取得市场主导权,一个原因就是 Gulp 基于内存操作的stream操作要比Grunt的文件操作要快。但是但其实要使用stream的力量你完全可以不用 Gulp。 事实上,流功能早就已经内置到了 Unix 和 Windows 的命令行中。 管道( |
)操作符可以将一个命令以流的形式输出作为另一个命令的输入。 而重定向( >
)操作符可以将定向输出到一个文件中。
所以, 举个例子, 在Unix中我可以使用 grep
读取一个文件的内容,并将其输出输出到一个新文件中:
grep 'Cory House' bigFile.txt > linesThatHaveMyName.txt
上面所做的就是流,没有中间的文件被写。(想知道上面的命令怎么跨平台使用吗?那继续读下去…)
你同样可以使用’&’操作符在Unix上同时执行两个命令:
npm run script1.js & npm run script2.js
上面两个脚本将同时执行,想要跨平台的同时执行脚本,使用 npm-run-all 。这引出了我们的下一个误解…
误解#4: npm Scripts 不能跨平台运行
很多项目都是在特定的操作系统使用,所以没有跨平台的忧虑。但如果你需要跨平台运行,npm Scripts 也能够很好的工作。无数的开源项目就是证明。接下来就是怎么做了。
你的操作系统命令行执行 npm Scripts ,所以在 Linux 和OSX,你的 npm Scripts 通过Unix命令行执行。而在 Windows 上,npm Scripts 通过 Windows 命令行执行。因此,如果你要你的构建脚本可以在所有平台上执行,你需要同时让Unix和Windows开心。 这里有3个方法:
方法1:使用 跨平台的命令 。很幸运的是竟然有如此多的跨平台命令,以下是其中一小部分:
- `&&` 串联任务 (运行一个任务后,再运行另一个任务)
- `<` 输入文件内容到命令
- `>` 重定向命令输出到一个文件
- `|` 重定向命令输出到另一个命令
方法2:使用 node packages 。你可以使用 node packages 来取代 shell 命令。例如,使用 rimraf 取代 rm -rf
。使用 cross-env 来跨平台地设置环境变量。在 Google , npm 或者 lirbraries.io 上搜索你所需要的 node package ,一般都能找到一个可以跨平台的。另外,如果你的命令行调用过长,你可以调用单独脚本中的 node packages,类似这样:
node scriptName.js
上面脚本是一个普通的老的 javascript 文件,通过 Node 执行。 如果你仅仅是想用命令行调用一个脚本,你可以不使用 .js
文件。你可以运行任何你的操作系统能执行的脚本, 例如 Bash 、 Python 、 Ruby 或 Powershell 等等。
方法3:使用 ShellJS 。ShellJS是一个通过 Node 执行 Unix 命令行的 npm package。所以这可以让你在任何平台上面执行 Unix 命令,包括 Windows。
我在 React Slingshot 项目中使用了方法1和方法2。
痛点
不可否认地是, npm Scripts 也存在一些缺点:因为 JSON 规范不支持添加注释,所以你不能在 package.json
里添加注释。有几个方法可以用来处理这个限制:
- 简短、命名良好、目的单一的 Scripts
- 单独为 Scripts 提供文档(例如写在一个 `README.md` 文件中)
- 调用单独的`.js`文件
我更倾向于第1种方法。如果你将每个脚本都分解成只有单一职责, 将很少再需要注释。 脚本的名字可以完全描述其意图,就好像所有简短且命名良好的函数一样。 就像我在《 简洁代码:编写人能看懂的代码 》中的讨论一样,短小且单一职责的函数很少需要注释。当我觉得注释是必要的时,我使用方法3,并将脚本移到单独的文件中。这让我在需要时可以使用javascript的所有能力。
package.json
也不支持变量。这听起来像是一个大问题,但由于以下两个原因,它不再是问题。 首先,最通常的需要变量的情况是要解决环境问题,但这你可以在命令行中设置。其次,如果你因为其他原因需要用到变量,你完全可以调用一个单独的js文件。 在React-starter-kit项目中你可以找到该做法的一个优雅的例子。
总之,仍然会有可能创建让人很难看懂的又长又臭的命令行参数。而确保 npm Scripts 分离成简洁、单一职责并且命名规范容易理解的小功能,代码审查和不断的重构是一个不错的方法。而如果 Scripts 复杂到真的需要注释,你应该把单一的脚本分离成多个命名规范的脚本,或者抽离到分离的文件。
抽象要恰当
Gulp 和 Grunt 都是我使用过的抽象工具。抽象是有用的,但是也有代价。它们让我们依赖于插件的维护者和文档,并且越来越多的依赖使他们更复杂。我已经觉得我不再需要 Gulp 和 Grunt 这样的任务执行器了。
想要更多细节?在 Pluralsight 网站上 “ 构建JavaScript开发环境 ”中从头开始学习如何使用npm脚本创建构建过程。
评论? 可以在文章底部、 Reddit 或 Hacker News 上进行评论。
最后, 我离第一个建议这么做的人已经很遥远。 下面是一些非常棒的链接:
- 用npm run完成任务自动化 — James Holliday
- 使用npm脚本实现进阶前端自动化 — Kate Hudson
- 如何将npm用成一个构建工具 — Kieth Cirkel
- npm作为构建工具介绍 — Marcus Hammarberg
- Gulp非常棒,但是我们真的需要它吗? — Gonto
- NPM脚本之于构建工具 — Andrew Burgess
原文地址:https://medium.freecodecamp.com/why-i-left-gulp-and-grunt-for-npm-scripts-3d6853dd22b8#.an2bjgxt8
以上所述就是小编给大家介绍的《为什么我放弃 Gulp 和 Grunt 而使用 npm Scripts》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 我承认,要放弃使用Lombok了!
- 和 Pipelining 说再见,cURL 放弃使用管道技术
- Elasticsearch 从入门到放弃:索引基本使用方法
- 为什么我放弃 Gulp 和 Grunt 而使用 npm Scripts
- GO 从入门开始放弃
- Elixir 从入门到放弃
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Spring 3.x企业应用开发实战
陈雄华 / 电子工业出版社 / 2012-2-1 / 90.00元
内容简介 Spring 3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。 Spring 3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架、REST风格的Web编程模型等。这些新功能实用性强、易用性高,可大幅降低Java应用,特别是Java Web应用开发的难度,同时有效......一起来看看 《Spring 3.x企业应用开发实战》 这本书的介绍吧!