五、高级 Grunt

到目前为止,这本书已经涵盖了有效使用 Grunt 所需的核心概念。在本章中,我们将介绍一些额外的想法、插件和工具,以将前端开发提升到一个新的水平。我们将通过 Grunt、与 Grunt的持续集成、外部任务Grunt 插件测试中获得一个潜行高峰。

最后,我们将回顾一系列的JavaScript 资源开发工具

使用 Grunt进行测试

执行自动化测试是 Grunt 的另一个主要用例。假设我们的构建过程包括编译、分析、优化,然后部署应用。Grunt 的这种顺序性质很有用,因为如果上述过程中的任何链接失败,Grunt 将不会继续,也就是说,任何后续任务都不会运行。

这一点很重要,因为当构建任务无法创建需要分析的文件时,它会阻止分析任务的运行。然而,静态分析不会发现构建文件中的逻辑错误,因此尽管构建成功,我们仍可能部署有缺陷的应用。我们可以通过在应用中包含一个测试套件来防止这种情况——将新的测试任务放在部署任务之前。即使我们有一个质量保证(QA)团队,手动测试我们的应用,使用测试套件也可以通过快速捕获逻辑错误来节省 QA 迭代。

测试套件对于捕获回归错误也很有用。我们的 QA 团队可能会花费数周的时间来测试我们的应用,但是,在多次没有测试套件的开发迭代之后,他们被迫返回并再次执行相同的测试,以确保我们的新代码没有破坏旧的功能。因此,我们整个团队的开发周期可以通过实施有效的自动化测试来改进。

www.it-ebooks.info

高级 Grunt

JavaScript 测试框架种类繁多,但最流行的两个框架是JasmineMocha。摩卡咖啡(http://gswg.io#mocha)由TJ Holowaychuk撰写,这位多产的开发者还为我们带来了翡翠、触控笔和 Express。Mocha 拥有所有测试框架中最广泛的特性集之一,对异步 API 提供了一流的支持。

下面是一个使用 Mocha 的行为驱动设计BDD语法编写的简单测试:

//代码示例 01 测试

//test/array-tests.js

描述('Array',function()){

描述(“#indexOf()”,函数(){

它('不在数组中时应返回-1',函数(){

expect([1,2,3].indexOf(5)).to.equal(-1);

expect([1,2,3].indexOf(0)).to.equal(-1);

});

});

});

在这里,我们可以看到 BDD 语法包含一个 descripe 和一个 it 函数:

•descripe 用于为单个测试创建命名容器(或命名空间)。当我们运行测试套件时,会传递这些容器,以帮助我们了解哪些类型的测试通过或失败。

•它用于定义测试。此函数接受我们选择的字符串,该字符串表示一个应为 true 的行为,例如,它(“应执行 foo 和 bar”,…)。

除了摩卡咖啡,我们还提供了一个图书馆(http://gswg.io#chai)它允许我们使用它的 expect 函数——一个用于执行断言并抛出适当错误以供 Mocha 捕获的函数。

在代码示例 01 测试中,我们使用 Grunt 插件 Grunt mocha(http://gswg.io#grunt-mocha)在名为PhantomJS的无头浏览器中运行 mocha(http://gswg.io#phantomjs). PhantomJS 是一种没有用户界面的 Web 浏览器。这个 API–only 浏览器是可编程的,允许它通过插件与 Grunt 通信。让我们给出代码示例 01 测试:try:$grunt

运行“mocha:test”(mocha)任务

测试:test/runner.html

1 个测试完成(2 毫秒)

我通过了!(0.00s)

完成,没有错误。

[102]

www.it-ebooks.info

第五章

我们可以看到 grunt mocha 正在测试 test/runner.html,我们有一个简单的 test/array-tests.js 文件的参考,该文件提供了一个测试用例。运行时,我们应该看到通过或失败的每个测试都有绿色或红色的点。在这个例子中,我们有一个绿点用于我们的单一通过测试用例。然而,如果我们打开测试/

在 Web 浏览器中,我们应该看到 Mocha 内置的 TestReporter,而不是 Grunt(PhantomJS)。有关 Mocha 浏览器测试运行程序的示例,请访问 http://gswg.io#mocha-浏览器示例。

由于 Grunt 主要用于前端 Web 开发,所以我们使用 Mocha 测试浏览器 JavaScript 代码。但是,Mocha 也可以用于测试 Node.js JavaScript 代码。

JavaScript 中有效的测试方法是一个很大的主题,因此这篇简短的介绍应该让我们了解测试的外观,以及如何使用 Grunt 将测试步骤集成到构建中。

与 Grunt持续集成

简单地说,持续集成(或 CI)服务器是一台专用机器,其唯一目的是运行构建,也就是说,它将持续地将新构建集成到给定系统中。通常,CI 服务器通过创建 HTTP

服务器并侦听要发送给它的数据。然后,HTTP 客户端可以将数据发布到此服务器,从而触发服务器启动构建。例如,您可以让 GitHub 在每次提交时触发 CI 服务器(http://gswg.io#github-webhooks),然后在新代码到达时,在 CI 上使用 Grunt 连续执行任务(例如分析、编译、测试和部署构建)。正确设置后,提交到存储库中主分支的行为可以分析、编译、测试和部署应用。这种简化的部署方法非常有价值,因为它减少了开发迭代时间。有关持续集成服务器的列表,请参见此 Wikipedia 页面 http://gswg.io#ci-名单。

外部任务

在许多情况下,我们的 Gruntfile.js 文件可能会变得非常大和复杂,特别是当我们开始将自己的自定义任务包含到混合中时。Grunt 提供了将自定义任务拆分为各自的文件的方法,从而降低了 Gruntfile.js 的复杂性并提高了可重用性,因为这个新任务文件也可以用于其他 Grunt 项目。在第 3 章使用 Grunt中,我们学习了如何使用 Grunt.registerTask 创建我们自己的自定义任务;但是,要将这些对 registerTask 的调用移动到另一个文件中,我们需要对 grunt 对象的引用(因为 grunt 被传递到我们的 GrunFile.js 中)。

[103]

www.it-ebooks.info

高级 Grunt

这正是 grunt.loadTasks 函数所做的:以目录路径作为参数调用它,然后运行给定目录中的每个 JavaScript 文件,就像它是一个“mini”GrunFile.js 文件一样(同时将当前 grunt 对象传递给它)。以下示例演示了这一点:

//代码示例 02 外部任务

//Grunfile.js

module.exports=函数(grunt){

grunt.loadTasks(“/任务”);

grunt.initConfig({

傅:{

酒吧:42

}

});

registerTask(“default”[“foo”]);

};

//tasks/foo.js

module.exports=函数(grunt){

registerTask(“foo”,function()){

log(“foo 说 bar 是:”+grunt.config(“foo.bar”);

});

};

在上面的示例中,我们在一个 foo.js 文件中定义了 foo 任务,任务目录中的。除了 foo.js 之外,我们还可以包含任意多的其他 JavaScript 文件,并执行我们在 Gruntfile.js 中可以执行的任何操作。

Grunt 插件

有了以上部分的概念,就很容易理解 Grunt 插件是如何工作的。Grunt 插件只是普通的 Node.js 模块(即,包含 package.json 文件的任何目录),此外,它们还包含一个任务目录,其中包含要加载的 JavaScript 文件。正如我们在本书中所看到的,当我们希望加载 Grunt 插件提供的任务时,我们使用模块名调用 Grunt.loadNpmTasks 函数。这个 loadNpmTasks 函数与前面描述的 loadTasks 函数非常相似,但是,它不使用目录查找 JavaScript 文件,而是使用模块的名称,然后在该模块内查找任务文件夹。因此,以下两行是等效的:

//代码示例 03 加载插件

grunt.loadNpmTasks(“grunt contrib 副本”);grunt.loadTasks(“./node_modules/grunt contrib copy/tasks”);

[104]

www.it-ebooks.info

第五章

现在,考虑到这一点,如果我们想创建并共享我们自己的任务,我们可以将它们作为插件发布。我们需要做的就是:

1.使用 registerTask 编写自定义任务。

2.将其放置在任务目录中的文件中。

3.在此任务目录旁创建一个新的 package.json 文件。

4.最后,使用 npm publish 将其发布到 npm。

简而言之,这就是我们公开共享 Grunt 插件所需要做的一切。但是,我们将仔细地完成每个步骤,并添加一些额外的步骤,以使其他人更容易访问。

首先,让我们编写自定义任务并将其放置在新任务目录中:

//代码示例 04 示例插件

//tasks/gswg.js

module.exports=函数(grunt){

registerTask(“gswg”,function()){

ok(“您好,您已经成功运行了'gswg'任务。”);

});

};

我们会注意到,我们已经将新任务文件命名为 gswg.js(因为它提供了 gswg 任务),尽管它看起来像一个 Gruntfile.js。如前所述,loadTasks 将运行每个文件,就像它是一个“mini”Gruntfile.js 一样–允许我们扩展称为 loadTasks 的 Gruntfile.js。

Grunt 提供了一个 API 来创建各种类型的日志消息。

Grunt API 文档包含有关 Grunt 的信息。

日志,可在 http://gswg.io#grunt-日志。

接下来,我们将创建 package.json。我们可以手动创建,也可以使用 npminit 创建。

为了让 npm 接受我们的模块,需要两个字段:名称和版本。因此,在本例中,我们将给它命名为 grunt gswg,并给它 0.1.0 的初始版本。还请注意,我们在模块名称前面加了 grunt 前缀,以便 grunt 用户可以将其识别为 grunt 插件。

[105]

www.it-ebooks.info

高级 Grunt

除了这两个必填字段外,我们还将告诉 npm,我们的模块是使用 peerDependencies 属性的 grunt 模块的插件(或扩展)。尽管我们可以使用 dependencies 属性,但这样做会导致每个 Grunt 插件都安装自己的 Grunt 模块副本。peerDependencies 属性通过使用父模块的 node_modules 目录而不是当前模块的 node_modules 目录来解决此问题。

为了让我们的模块被视为 Grunt 插件,我们还需要添加一个关键字数组属性并包含“gruntplugin”。关键字数组列出了帮助 npm 用户查找模块的搜索词。例如,如果我们制作了一个 Grunt 插件来创建一个数据库的副本,我们可能还包括“复制”、“克隆”,

“复制”、“数据库”和“数据库”。这将允许用户找到我们的插件,即使他们使用了一个等价的搜索词分类。

为了最终确定 package.json,我们还将包括:

•作者财产,包含我们的联系信息。在本例中,我使用了“Jaime Pillora。

•许可证属性,指定我们希望应用于模块的软件许可证。在本例中,我们将使用“MIT”,它表明我们的模块是免费的,每个人都可以以任何方式使用。

•主页属性,提供 URL,用户可以从中了解更多关于我们模块的信息。

此时,我们的 package.json 文件现在应该如下所示:

{

“名称”:“grunt gswg”,

“版本”:“0.1.0”,

“作者”:“詹姆·皮洛拉,

“主页”:https://github.com/jpillora/gswg-examples/tree/master/5/04-sample-plugin",

“对等关系”:{

“咕噜”:“~0.4.0”

},

“关键词”:[

“gruntplugin”,

“示例”,

“样本”,

“gswg”

],

“许可证”:“麻省理工”

}

[106]

www.it-ebooks.info

第五章

现在我们有了新的 gswg 任务和一个有效的 package.json 文件,我们可以发布到 npm 了。然而,在我们做之前,让我们做一些家务。如果没有文档告诉每个人如何使用代码,那么发布供每个人使用的代码是没有意义的。因此,让我们创建一个 README.md 文件,它将通知用户该插件提供的任务以及每个任务的可用选项。此文件采用标记文件格式,我们可以在此处了解更多信息:http://gswg.io#markdown. 我们可以在代码示例 04 示例插件目录中找到该示例的 README.md 文件。

现在,我们已经创建了足够的代码来保证备份。让我们将代码放入一个版本控制系统,比如 Git。拥有插件修改历史的可导航历史非常重要,这样我们可以在删除旧代码时恢复旧代码,因此当我们希望与其他人协作时,就可以分支和合并我们的代码。在本例中,让我们将目前为止的内容提交到 GitHub 中。要在 GitHub 上创建新的 Git 存储库,我们需要:

•创建 GitHub(http://gswg.io#github)帐户并登录。

•点击右上角的创建新存储库图标。

•使用插件名称作为存储库名称,并提供简短描述,然后单击创建存储库

•我们将被带到新的空存储库,在那里我们将找到如何在本地设置此存储库的说明,并进行首次提交。

要了解有关使用 Git 的更多信息以及如何充分利用 Git,请访问此页面:http://gswg.io#git-资源。

在发布我们的插件供一般使用之前,我们希望确保它能正常工作。如前所述,最好创建一个自动化测试套件,以确认我们所需的功能确实是功能性。然而,对于这个示例插件,我们将只使用一个伪 Gruntfile.js 文件并手动确认它是否工作。我们的插件的用户也可以查看这个文件,作为我们的插件运行的一个例子。

我们将首先在示例目录中创建一个 Gruntfile.js:

//代码示例 04 示例插件

//示例/grunfile.js

module.exports=函数(grunt){

grunt.loadTasks(“../tasks”);

registerTask(“default”[“gswg”]);

};

[107]

www.it-ebooks.info

高级 Grunt

在这里,我们使用 loadTasks 并直接引用 tasks 文件夹来复制 LoadNPMTask。但是,在运行这个 Gruntfile.js 之前,它需要安装 grunt 模块。由于我们使用的是 peerDependencies 属性,我们还需要使用 devDependencies 属性来告诉 npm 安装 grunt 进行本地测试。因此,我们将首先使用以下命令:$npm install——save dev grunt

然后,我们可以使用以下命令运行我们的虚拟 Gruntfile.js:

$cd 示例

$grunt

正在运行“gswg”任务

>>您好,您已经成功运行了“gswg”任务。

完成,没有错误。

正如我们所看到的,我们的 gswg 任务已经成功运行,我们现在准备发布它。现在让我们用 npm adduser 登录到 npm。此命令用于登录和帐户创建。它会给我们三个提示:姓名、电子邮件和密码。登录后,我们可以进入 npm publish,我们应该看到:$npm publish

npm http PUThttps://registry.npmjs.org/grunt-gswg npm http 201https://registry.npmjs.org/grunt-gswg npm http GEThttps://registry.npmjs.org/grunt-gswg npm http 200https://registry.npmjs.org/grunt-gswg npm http PUThttps://registry.npmjs.org/grunt-gswg/-/grunt-gswg-0.1.0.tgz/-rev/1-0d89dbcc01a9b9d154a7f43bc103c411

npm http 201https://registry.npmjs.org/grunt-gswg/-/grunt-gswg-0.1.0.tgz/-rev/1-0d89dbcc01a9b9d154a7f43bc103c411

npm http PUThttps://registry.npmjs.org/grunt-gswg/0.1.0/-tag/latest npm http 201https://registry.npmjs.org/grunt-gswg/0.1.0/-tag/latest

+Grunt-gswg@0.1.0

这个示例插件现在已经发布到 npm,我们可以用 npm info grunt gswg 命令确认。

实用插件

下面是 Grunt 插件的列表,这些插件虽然不是绝对必要,但有时非常有用:

[108]

www.it-ebooks.info

第五章

同时运行 Grunt 任务:http://gswg.io#grunt-使用 grunt 并发插件,我们可以创建任务组,这些任务组将彼此独立运行,从而加快构建速度。

自动加载所有 Grunt 插件:http://gswg.io#load-grunt 任务使用 load grunt 任务插件,您可以替换 grunt.loadNpmTask(…)的所有实例;对于单行,require('load-grunt-tasks')(grunt)。此函数搜索 package.json 的 devDependency 字段,并自动为每个以 grunt 为前缀的模块调用 grunt.loadNpmTask。

使用 Grunt运行基本文件服务器:http://gswg.io#grunt-contrib connect 在某些情况下,我们将构建 Web 应用或网站的前端部分,而不需要后端为我们的文件提供服务。使用 grunt contrib connect 插件,我们可以在选择的端口上运行自己的简单文件服务器。这个插件与 grunt contrib watch 插件配合得很好,因为它允许我们同时运行构建和本地服务新构建的文件,所有这些都在 grunt 中。

JavaScript 资源

由于标准和浏览器的不断发展,网络不断发展。

随着浏览器引入新功能,我们可以看到浏览器变成了一个伪操作系统,完成了对硬件和文件系统的访问。在决定本机桌面应用和 web 应用时,必须考虑我们的用途。由于浏览器的通用性和强大功能,再加上易于访问,这一决定非常简单。未来是由 JavaScript 驱动的 web 应用。下面是一个有用的资源列表,对于 JavaScript 熟练工,对于 JavaScript 精英来说:

Mozilla 开发者网络(每个人)http://gswg.io#mdn Mozilla 开发者网络是前端开发中的一个很好的资源。它包含几乎所有浏览器 API 的文档,包括传统和现代功能。

代码学院(初学者)http://gswg.io#codeacademy 为了获得基于交互的 JavaScript 学习体验,CodeAcademy 构建了一个 web 应用,纯粹是为了向潜在的开发人员教授编程。

雄辩的 JavaScript(初学者)http://gswg.io#eloquent-javascript 除了是对 javascript 编程语言的一个很好的介绍外,它还是一本关于一般编程的好书。作者MarijnHaverbeke已在知识共享许可证下以 HTML 格式在线发布了雄辩的 JavaScript。由于 HTML 版本显示在浏览器(有 JavaScript 引擎)中,因此他包含了可运行和可编辑的代码示例,您可以在阅读时进行实验。

[109】

www.it-ebooks.info

高级 Grunt

JavaScript:好的部分(中间)http://gswg.io#the-好的部分被一些人视为“JavaScript 圣经”,好的部分讨论 JavaScript 的历史,以及 JavaScript 的好的和坏的部分。这本书的目标是希望获得更深入的语言知识的中级开发人员。作者道格拉斯·克罗克福德也做了一些很棒的演讲,涵盖了书中的各种主题,可在 http://gswg.io#crockford-在 javascript 上。

学习 JavaScript 设计模式(高级)http://gswg.io#javascript-设计模式Addy Osmani撰写的这本知识共享书面向希望提高设计模式知识以及如何将其应用于 JavaScript 编程语言的专业开发人员。

阅读完这些书籍和资源后,您可以访问 http://gswg.io#js-books,其中维护有组织的、可排序的 JavaScript 书籍列表。

开发工具

在本节中,我们将介绍一些开发工具,它们直接或间接地与一般的 Grunt 开发工作流相关。

作者选择

在本节中,我将介绍我自己的开发环境的工具,以及我认为每种工具都有用的原因。

Mac OS X

在我看来,MacOSX(http://gswg.io#osx)提供最佳的开发环境。Mac OS X 将基于 Unix 的操作系统与卓越的用户体验相结合,允许您使用大量基于 Unix 的开发工具,而无需担心系统级的复杂性和不兼容性。自制(http://gswg.io#brew)是 Linux 的 apt get 的 OS X 替代品,为安装命令行工具提供了一种简单易用的方法。

如果在 Microsoft 堆栈(.NET、C#等)上开发,则 Windows 非常有用。

然而,MacOSX 更适合前端开发。因为,除了 Unix 开发人员工具之外,还有许多功能强大的图形和设计工具。如果 Mac OS

X 不可用,我的下一个选择是流行的 Linux 风格,Ubuntu。

[110]

www.it-ebooks.info

第五章

崇高文本

Windows/Mac/Linux(http://gswg.io#sublime)对于那些喜欢较轻重量的文本编辑器而不是集成开发环境【IDE】的人来说,升华文本是完美的选择。由于其巨大的可扩展性,一个简单的包管理器被称为包控制(http://gswg.io#sublime-包控制)。有用的软件包包括:

•SublimiteLineter—一种多语言静态分析器“linter”,在您键入时以内联方式显示代码警告

•CoffeeScript/Jade/Stylus/nginx 一系列插件,为各自的语言提供语法高亮显示

源树

Windows/Mac(http://gswg.io#sourcetree)-一个干净的 Git 用户界面,提供了可视化 Git 存储库当前状态的更快方法。此外,这些可视化通过清晰地传达诸如分支和合并之类的 Git 概念,降低了初学者的学习曲线。SourceTree 还包括Git Flow集成。

Git Flow 通过指导您的 Git 工作流来帮助实施 Git 最佳实践。

镀铬工具

Windows/Mac/Linux(http://gswg.io#chrome-devtools)-Google Chrome 的开发者工具为前端开发的各个方面提供了一套非常有用的调试、检查和性能分析工具。还有一个 Chrome 开发工具扩展名为Grunt 开发工具(http://gswg.io#grunt-它在 ChromeDevTools 中添加了一个“Grunt”选项卡,为 Grunt 提供了一个用户界面。

社区精选

在这个简短的部分中,我们将回顾前端社区使用的两个流行工具。

网络风暴

喷气式飞机(http://gswg.io#webstorm),IntelliJ 和 RubyMine 的创建者,也有一个用于 Web 开发的IDE。与 Sublime Text 类似,还有一个包管理器,其中包含许多有用的插件。

[111]

www.it-ebooks.info

高级 Grunt

约曼

约曼是一个脚手架工具(http://gswg.io#yeoman)用于使用当前行业最佳实践以及利用 Grunt 和 Twitter 的 Bower 的工作流生成项目。该工具的大量社区应用为许多框架生成了代码生成器。例如,有代码生成器用于以角度构建指令、主干中的模型、余烬组件等等。

总结

在本章中,我们简要介绍了 JavaScript 测试和 Grunt 插件,我们可以使用它将 Mocha 集成到 Grunt 构建中。我们已经看到了 Grunt 插件及其工作原理的简短介绍,以及其他有用的插件。

最后,我们介绍了与 Grunt 无关的 JavaScript 资源和开发工具,但是,当与 Grunt 结合使用时,每个工具都可能有助于将我们的开发周期提升到一个新的水平。

[112]

www.it-ebooks.info

感谢您购买 Grunt 入门:JavaScript 任务Runner。我希望这篇对 Grunt 的介绍既能提供信息又能让人感兴趣。你可以在 GitHub上找到我 http://gswg.io#jpillora 您可以发送评论和反馈 gswg@jpillora.com或在上发推特

@jpillora。我期待着听到你的回答。

www.it-ebooks.info

www.it-ebooks.info