gulp

目前围绕Gulp、Grunt和npm脚本社区有很多争论,讨论是否有必要在项目中继续使用Gulp和Grunt。有人坚持认为Gulp和Grunt等前端构建工具仍然不可或缺,也有人认为Gulp和Grunt完全没有必要,增加了一层抽象,会导致很多问题。本文提供另一个观点,仅供参考。

众所周知,Gulp和Grunt是很多项目使用的构建工具,它们也有非常丰富的插件。但是,我认为Gulp和Grunt完全是不必要的抽象,npm脚本更强大,更容易使用。

我自己也是一个大口风扇。但是在上一个项目中,gulpfile实际上有100多行,使用了很多Gulp插件。我尝试通过Gulp整合Webpack、Browsersync、Hot Load、Mocha等工具。我为什么要这么做?这是因为有些插件的文档太不充分;有些插件只暴露了我需要的部分API。其中一个插件有一个奇怪的Bug,只能看到文件的部分内容。另一个插件在输出到命令行时失去了颜色。

当然,这些问题是可以解决的;然而,当我直接使用这些工具时,所有的问题都不复存在了。最近我注意到很多开源项目只用npm脚本。因此,我决定重新审视我的方法。我真的需要吞咽吗?答案是:一点也不。我决定在我的新开源项目中只使用npm脚本。我只使用npm脚本来构建React应用程序的开发环境和构建过程。想知道这个项目是什么样子的?看看React弹弓。现在相比Gulp,我更喜欢用npm脚本。原因如下。

吞咽和咕噜怎么了?

随着时间的推移,我发现Gulp、Grunt等任务跑者都存在以下三个核心问题:

对插件作者的依赖

令人沮丧的调试

断开的文档

下面我们来具体分析一下以上三个问题。

问题1:对插件作者的依赖

当使用更新的或不太流行的技术时,可能根本没有插件。可用的插件可能已经过时。比如前阵子发布的巴别塔6。它的API变化很大,所以很多Gulp插件都不兼容最新版本。在使用Gulp的时候,因为需要的Gulp插件没有更新,所以感觉深受伤害。使用Gulp或Grunt时,你必须等待插件维护者的更新,或者自己修复。这会妨碍你使用最新的现代工具。相反,在使用npm脚本时,我会直接使用工具,而不会添加额外的抽象层。这意味着当新版本的摩卡、伊斯坦布尔、巴别塔、Webpack、Browserify等。发布后,我可以立即使用新版本。就选择而言,没有什么能打败npm:

gulp

从上图可以看出,Gulp有近2100个插件;有将近5400个咕噜人;另一方面,Npm提供了超过227,000个包,并且还在以每天超过400个的速度增加。

使用npm脚本时,不需要搜索Grunt或Gulp插件;从超过227,000个npm包中选择即可。平心而论,如果所需的Grunt或Gulp插件不存在,当然可以直接使用npm包。然而,对于这种特殊的任务,不能再使用吞咽或咕哝了。

问题2:令人沮丧的调试

如果集成失败,在Grunt和Gulp中调试是令人沮丧的。因为您面对的是一个额外的抽象层,所以任何Bug都可能有更多的潜在原因:

基础工具有问题吗?

Grunt/Gulp插件有问题吗?

配置有问题吗?

使用的版本不兼容吗?

使用npm脚本可以消除上面的第二点,我发现第三点很少出现,因为我一般都是直接调用工具的命令行界面。最后,第4点很少出现,因为我直接用npm代替task runner抽象,减少了项目中的包数。

问题3:不连续的文档

一般来说,我需要的核心工具的文档质量总是比相关的Grunt和Gulp插件要好。比如用gulp-eslint,那么我会在gulp-ESLint文档和ESLint网站之间来回切换;您必须在插件和插件抽象的工具之间来回切换上下文。Gulp和Grunt的问题在于,仅仅理解所使用的工具是不够的。Gulp和Grunt要求您也理解插件的抽象。

大多数与构建相关的工具都提供了清晰、强大的命令行界面和高质量的文档。ESLint的CLI文档就是一个很好的例子。我发现在npm脚本中阅读和实现简短的命令行调用更容易,障碍更少,调试更容易(因为没有抽象层)。现在我们知道了痛点,下一个问题是,为什么我们认为我们仍然需要任务运行程序,如Gulp和Grunt?

我相信原因应该因人而异。毫无疑问,Gulp、Grunt等任务跑者已经存在很久了,围绕这些任务跑者的插件生态系统也呈现出欣欣向荣的景象。依靠这些插件,许多日常任务可以自动化并运行良好。这样人们就会认为只有通过这些任务运行器才能实现任务构造、文件打包、工作流运行良好等等。

另一个原因是人们对npm脚本的理解远远不够;npm脚本能完成的事情和任务也是表面的。这也进一步造成了很多人没有发现npm脚本可以实现很多日常开发任务。相信随着开发者对npm脚本的进一步了解,人们会逐渐发现,npm脚本也可以完成Gulp、Grunt等任务运行器所能完成的任务,而且配置更加简单直接,因为它会直接使用目标工具,而不需要对目标工具使用包装器。

为什么我们在构建时会忽略npm?

我认为诸如Gulp和Grunt这样的任务运行程序如此受欢迎有四个原因:

人们认为npm脚本需要很强的命令行技能。

人们认为npm脚本不够强大。

人们认为快速施工离不开Gulp的流量。

人们认为npm脚本不能跨平台运行。

我来按顺序解释一下这些误解。

误解1:使用npm脚本需要很强的命令行技能。

要体验npm脚本的强大功能,您并不需要非常了解操作系统的命令行。当然,grep、sed、awk、pipeline都是值得学习、造福众生的技能;但是,为了使用npm脚本,您不必是Unix或Windows命令行专家。您可以通过npm中1000多个记录良好的脚本来完成这项工作。

比如你可能不知道,在Unix中,命令rm -rf会强制删除一个目录,这没问题。你可以用rimraf做同样的事情(它也是跨平台的)。大多数npm包都提供了一些接口,这些接口假设你对操作系统的命令行了解不多。只需搜索你想在npm中使用的包,边做边学。以前经常搜Gulp插件,现在搜npm包。Libraries.io是一个很好的资源。

误解2: NPM剧本不够强。

Npm脚本本身其实非常强大。它提供了基于约定的预挂钩和后挂钩:

{

名称:“NPM-脚本-示例”,

版本:“1.0.0”,

描述:“npm脚本示例”,

脚本:{

prebuild:“在构建脚本之前运行echo I”,

build:“cross-ENV NODE _ ENV = production web pack”,

后期构建:“在构建脚本后运行echo”

}

}

你所要做的就是遵守协议。上述脚本将根据它们的前缀按顺序运行。预构建脚本将在构建脚本之前运行,因为它们具有相同的名称,但预构建脚本具有前缀“pre”。postbuild脚本将在构建脚本之后运行,因为它有一个“post”前缀。因此,如果创建了名为prebuild、build和postbuild的脚本,当我键入“npm run build”时,它们将自动按此顺序运行。

此外,您可以通过在一个脚本中调用另一个脚本来分解一个大问题:

{

“名称”:” NPM-脚本-示例”,

“版本”:” 1.0.0 “,

“描述”:” npm脚本示例”,

“脚本”:{

“干净”:“里姆拉夫。/dist & amp;& ampmkdir区”,

“预构建”:“npm干净运行”,

” build “:” cross-ENV NODE _ ENV = production web pack “

在上面的示例中,预构建任务调用清理任务。通过这种方式,可以将脚本分解成更小的、命名良好的、单责任和单行脚本。

可以用&;& amp连续调用多个脚本。在上面的示例中,清理步骤中的脚本将一个接一个地运行。如果你需要把任务列表里的任务一个一个囫囵吞枣地运行,那么这种简单性一定会吸引你。

如果命令很复杂,您也可以调用一个单独的文件:

” build”: “node build.js “

我在上面的构建任务中调用了一个单独的脚本。脚本将按节点运行,这样我可以使用任何我需要的npm包,同时我可以利用JaScript的能力。我可以列出更多,但是感兴趣的读者可以参考这个核心特性文档。此外,Pluralsight还有一门关于如何使用npm作为构建工具的课程。也可以看看React Slingshot,直观的了解它是怎么用的。

误区三:快速建造少不了Gulp的流。

Gulp出来后,人们很快被它吸引,放弃了Grunt,因为Gulp的内存流比Grunt基于文件的方法快得多。然而,为了享受强大的流媒体功能,你实际上并不需要吞咽。事实上,流早就内置在Unix和Windows命令行中了。管道(|)运算符将一个命令的输出作为另一个命令的输入。Redirect(>)运算符将输出重定向到文件。例如,在Unix中,我可以“grep”一个文件的内容,并将输出重定向到一个新文件:

grep ‘ Cory House ‘ bigFile.txt & gtlinesThatHeMyName.txt

上述进程是流式的,不会写入中间文件(想知道如何跨平台实现上述命令?请继续阅读)。

在Unix中,还可以使用” & “运算符同时运行两个命令:

npm运行脚本& ampnpm运行script2.js

以上两个脚本将同时运行。要跨平台地同时运行脚本,请使用npm-run-all。这就造成了以下的误解。

误解4: NPM脚本不能跨平台运行。

很多项目都绑定了特定的操作系统,所以跨平台并不是那么重要。但是,如果你需要以跨平台的方式运行,npm脚本仍然可以很好地工作。大量的开源项目就是证据。下面介绍一下实现方法。

操作系统的命令行将运行您的npm脚本。因此,在Linux和OS X上,npm脚本将在Unix命令行上运行。在Windows上,npm脚本在Windows命令行上运行。这样,如果希望构建脚本在所有平台上运行,就需要对Unix和Windows进行适配。以下是三种实现方式:

模式1:使用跨平台命令

我们可以使用许多跨平台的命令。以下是一些例子:

& amp& amp链式任务(一个接一个的任务)

& lt在命令中输入文件内容。

& gt将命令输出重定向到文件

|将一个命令的输出重定向到另一个命令。

模式2:使用节点包

您可以使用节点包来代替shell命令。比如用rimraf代替“RM-RF `”。使用cross-env以跨平台的方式设置环境变量。搜索Google、npm或者libraries.io找到你需要的,几乎都会有相应的节点包,以跨平台的方式实现你的目标。如果命令行调用太长,可以在单独的脚本中调用节点包,如下所示:

节点scriptName.js

上面的脚本是普通的JaScript,由Node运行。因为脚本是在命令行调用的,所以您不会受到。js文件。你可以运行任何操作系统可以执行的脚本,比如Bash、Python、Ruby或者Powershell。

模式3:使用ShellJS

ShellJS是一个npm包,它通过Node运行Unix命令。这允许您在所有平台上运行Unix命令,包括Windows。

我在React Slingshot上使用了方法1和2。

痛点?

显然,使用npm脚本存在一些问题:JSON规范不支持注释,因此无法在package.json中添加注释.但有一些方法可以突破这一限制:

编写小型的、命名良好的、单一用途的脚本

将文档与脚本分开(例如,在README.md中)。

叫一个单独的。js文件

我倾向于第一种解决方案。如果每个脚本都被分解成一个单独的责任,注释就变得不那么重要了。脚本的名字应该充分描述它的意图,就像任何简短和命名良好的函数一样。正如我在“干净的代码:为人类编写代码”中所说的,简短的、单一职责的功能几乎不需要注释。如果我觉得有必要添加注释,那么我会使用第三种方案,即把脚本移到一个单独的文件中。这样,您就可以利用JaScript组合的强大功能。

Package.json也不支持变量。这似乎是一个大问题,但事实并非如此,原因有二。首先,很多时候我们需要的变量和环境有关,可以通过命令行设置。其次,如果因为其他原因需要变量,可以单独调用。js文件。感兴趣的读者可以看看React-starter-kit来了解这种做法。

最后,存在使用长而复杂的命令行参数的风险,这些参数很难理解。代码审查和重构是一个很好的方法,可以确保npm脚本保持短小精悍,名字清晰,单一职责,易于每个人理解。如果脚本非常复杂,需要注释,那么您应该将一个脚本重新构造成几个命名良好的脚本,或者将它们提取到单独的文件中。

我们需要证明抽象是有意义的。

Gulp和Grunt是我使用的工具的抽象。抽象非常有用,但它是有代价的。它让我们过于依赖插件维护者和文档,同时,随着插件数量的不断增加,也引入了复杂性。我已经决定停止使用任务运行程序,如吞咽和咕哝。

事实上,除了我之外,已经有很多开发者和我持相同的观点,比如下面这些:

npm运行下的任务自动化—詹姆斯·霍利迪

使用npm脚本的高级前端自动化—凯特·哈德森

如何使用npm作为构建工具——Kieth Cirkel

介绍作为构建工具的npm马库斯·哈马尔贝格

吞咽很棒,但是我们真的需要它吗?—?贡托

构建工具的NPM脚本——Andrew Burgess

开发商的反应

Cory的文章一发表,就得到众多开发者的广泛响应,人们纷纷发表看法。以下是一些典型的观点供读者参考:

杰森颤声说道:

另一个好处是基于节点的项目的标准化。如果你能通过“npm run”来运行任务就太好了,尽管这些任务只是Gulp/Grunt的包装。

德韦恩·克鲁克斯说:

太好了。最近一直在思考工作流程中是否需要使用Gulp,在我的项目中使用的越来越少。这篇文章让我相信Gulp和其他构建工具完全没有必要。谢谢您们。

弗拉基米尔·阿加丰金说:

我们在Mapbox上有大量的JaScript仓库,它们都使用npm脚本,但是根本不用Gulp和Grunt。一点问题都没有,很容易构建,也很容易理解和管理。

马丁·奥尔森说:

一年前看了这篇文章http://blog . keithcirkel . co . uk/why-we-should-stop-using-grunt/然后开始使用npm脚本,逐渐放弃Gulp。我喜欢npm脚本的简单性。恕我直言,唯一的痛点是不能给脚本添加注释,而且必须转义双引号。

蒂姆·维斯涅夫斯基说:

我也是这么做的,文章的观点和我不谋而合。

阿克谢·毕斯特说:

不仅是节点包,您还可以运行操作系统可以执行的任何脚本。因此,您也可以运行python、bash脚本等等。

塞西尔·麦格雷戈说过:

我真的很感激。虽然我在工作中必须使用Grunt,但我在家里大部分时间都使用npm脚本。很多插件都有一些问题,浪费了我很多时间去探究问题。

杰斯·海因斯说:

我真的很感激。通常,我们都认为抽象会使事情变得更简单,但是我发现npm脚本足够友好并且非常强大。如果有必要,我会尝试本文中的方法来加深我的理解。

亚当·塞尔丹说:

我完全同意文章中的观点。我最近一直在用npm package.json脚本,尤其是那些大量使用Node.js的项目,完全不需要复杂的转换链。如果你觉得不舒服(现在还没有出现,通常情况下,你会提前知道你正在做的项目的规模和建设步骤),那么介绍和学习Webpack是一个很好的方法,在某种程度上比Grunt和Gulp要好。

迪伦·J·哈里斯说过:

谢谢你。作为一个新手任务跑者,我遇到过文中提到的三个问题,所以我非常讨厌这种抽象。我打算在下一个项目中直接使用npm脚本,这是一篇很棒的文章。

杰森·卡恩斯说:

直接使用npm脚本会给我们更多的配置选项;Npm会将package.json对象公开为带有前缀npm_package的环境变量;;Npm有一个定义良好的配置查找方法,所以可以在不同的地方定义各种选项,必要时会覆盖这些选项。

小Q说:InfoQ的读者朋友们怎么看?欢迎在评论区告诉我们你的想法!

老司机游戏攻略

科里·豪斯(Cory House)是《用反应和流动构建应用程序》(Building Applications with Reaction and Flux)和《干净的代码:为人类编写代码》(Clean Code: Writing Code for Humans)的作者,也是Pluralsight上许多课程的讲师。他是VinSolutions的软件架构师,在世界各地培养了大量的软件开发人员。他的主要领域是前端开发和干净代码等软件开发实践。科里是微软MVP,Telerik开发者专家,outlierdeveloper.com创始人。

本文由InfoQ原创发布,未经授权谢绝转载。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。

发表回复

登录后才能评论