写点什么

基于 Node.js 的自动化构建工具 Grunt.js

  • 2013-06-04
  • 本文字数:3086 字

    阅读完需:约 10 分钟

Java 世界里的 Maven 提供了强大的包依赖管理和构建生命周期管理。在 JavaScript 的世界里,随着 Node.js 的流行,JavaScript 原生的构建工具已经成为可能。

Grunt.js 是基于 Node.js 的自动化任务运行器。Grunt.js 结合 NPM 的包依赖管理,完全可以媲美 Maven。Grunt.js 天然适合前端应用程序的构建——不仅限于 JavaScript 项目,同样可以用于其他语言的应用程序构建。越来越多的 JavaScript 项目已经在使用 Grunt,其中最大的使用者包括著名的 jQuery 项目。

Grunt 的生态系统在迅速的成长,目前已经有上百种插件发布在 NPM 上可供选择。同时,任何人都可以方便的发布自己的插件到 NPM 上供其他人使用。

Grunt 没有像 Maven 那样强调构建的生命周期,各种任务的执行顺序可以随意配置。Grunt 本身仅是一个执行器,大量的功能都存在于 NPM 管理的插件中。特别是以grunt-contrib-开头的核心插件,覆盖了大部分的核心功能,比如 handlebars,jade,less,compass,jshint,jasmine,clean,concat,minify,copy,uglify,watch,minify,uglify 等。

通过提供通用的接口以进行代码规范检验(Lint)、合并、压缩、测试及版本控制等任务,Grunt 使入门门槛大大降低了。

安装

Grunt 目前的最新版本为 v0.4 版。相比 v0.3 版,Grunt 本身不再作为一个整体全局模块安装,而是分为了三个部分:grunt,grunt-cli,grunt-init。

grunt-cli 用于命令行启动 Grunt,必须作为全局模块安装:

npm install -g grunt-cli

grunt-init 是可选的,用于以命令行新建 Grunt 项目模板,必须作为全局模块来安装:

npm install -g grunt-init

Grunt 核心作为项目或插件的依赖包而单独存在,避免由于不同的插件依赖的 Grunt 版本不同而造成的冲突。

新建项目工程

在命令行中执行 grunt init

无论新建项目是应用程序还是一个 Grunt 插件,Grunt 生成的工程都是一个标准的 NPM 模块。

新工程目录下有两个文件非常重要:

package.json: NPM 的发布配置文件,包含了包依赖信息和项目工程的元数据。熟悉 Node.js 的读者应该不陌生。

gruntfile.js: Grunt 配置文件,用于配置或定义 Grunt 任务,以及加载 Grunt 插件等。

Grunt 任务配置

所有的任务配置都存在 gruntfile.js 中。作为 JavaScript 源文件,其配置信息以 JSON 对象的方式来存放,并可以使用 JS 函数来动态生成,比 Maven 的 XML 配置方式更加简洁和富有灵活性。一份典型的 gruntfile 如下:

复制代码
module.exports = function(grunt) {
  // 项目配置信息.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
      },
      build: {
        src: 'src/<%= pkg.name %>.js',
        dest: 'build/<%= pkg.name %>.min.js'
      }
    }
  });
  // 加载 "uglify" 插件..
  grunt.loadNpmTasks('grunt-contrib-uglify');
  // 注册默认任务.
  grunt.registerTask('default', ['uglify']);
};

可以看到,它就是一个标准的 Node.js 模块定义。

  1. 插件配置:形如 JSON 对象的配置信息,包括定义文件操作的源与目标,标志变量等。Grunt 还提供了一些模板变量用于插入常用的信息,如日期时间等。
  2. 加载插件:通过 grunt.loadNpmTask(),显式地加载外部 Grunt 插件。
  3. 注册自定义任务。用法见下文“自定义任务”。可以注册任意的任务链,但至少注册一个默认任务链。

运行

进入项目的根目录,在命令行执行grunt 即可根据配置文件来执行所有的自动化任务。

复制代码
$ grunt
Running "jshint:gruntfile" (jshint) task
1 file lint free.
 
Running "jshint:src" (jshint) task
1 file lint free.
 
Running "uglify:dist" (uglify) task
File "dist/ba-tiny-pubsub.min.js" created.
Uncompressed size: 389 bytes.
Compressed size: 119 bytes gzipped (185 bytes minified).
 
Done, without errors.
$

也可以选择性地执行某些任务,甚至给不同的插件附加命令行参数:

例如,只执行 clean 插件的 dist 子任务和 jasmine 插件的所有任务:

grunt clean:dist jasmine

流行的插件

v0.4 版以后,各种常用插件基本都归入了 grunt-contrib-xxx系列。下面介绍几个比较常用的插件:

  • grunt-contrib-clean: 用于清理指定文件(夹),一般是构建之前或之后进行
  • grunt-contrib-coffee: 将 CoffeeScript 编译为 JavaScript
  • grunt-contrib-compass: 调用 Compass 工具生成 CSS 文件
  • grunt-contrib-concat: 连接源文件,减少 HTTP 请求
  • grunt-contrib-copy: 复制文件(夹)
  • grunt-contrib-handlebars: 将 handlebars 模板预编译为 JST 文件,提高运行时性能
  • grunt-contrib-jasmine: 借助 Jasmine 在 PhantomsJS 中运行单元测试,结合 grunt-template-jasmine-istanbul,还能实现单元测试覆盖率计算
  • grunt-contrib-jshint: JS 代码质量检查工具,类似 jsLint
  • grunt-contrib-watch: 监视磁盘文件,一旦更改就会重新运行指定的任务,例如使 http 服务器重新加载源文件
  • grunt-contrib-ugligy: 压缩 JS 源文件,提高运行时性能

自定义任务

利用 Grunt 的 API 可以很方便的创建自定义任务和插件。两种方式所用到的 API 完全一致,只不过自定义任务在写在项目的 gruntfile.js 中,而插件可以自主发布。

任务分为两种:

  • grunt.registerTask():以 JS 函数的形式定义的一个独立的任务,可以从命令行传入参数、调用 Grunt API、 或者仅仅是作为别名(alias),链式地调用其他任务。
  • grunt.registerMultiTask():与 registerTask() 函数不同的是,同一任务可以同时存在多组配置目标 (target),Grunt 会自动地遍历读取每组配置目标分别执行,也可以指定仅以某个配置来单独执行任务。这对于文件操作任务比较常用。例如要使用清理文件的 clean 插件,可能会有两组配置,分别用于清理打包文件夹和清理单元测试临时文件夹。此外,jshint,concat,uglify 等也都是 MuitiTask 类型。

API 扩展

无论是自定义任务还是创建独立的 Grunt 插件,都少不了要用到 Grunt 提供的 API。其中一些是对 Node.js 功能的扩展,另一些是满足 Grunt 的特殊需要:

  1. grunt.config: 读取和管理 gruntfile 中的配置信息
  2. grunt.event: 自定义事件
  3. grunt.fail: 用于异常处理时发出警告或强制终止任务
  4. grunt.file: 用于磁盘文件管理的扩展函数,包括 read,write,copy,delete,mkdir,expand,exist,path 等
  5. grunt.log: Grunt 自有的 log 功能
  6. grunt.option: 用于从命令行中读取参数
  7. grunt.task: 用于注册自定义任务和加载外部任务
  8. grunt.template: 处理 gruntfile 中的模板变量,以及提供了常用的日期模板辅助(helper)函数,包括 template.data,template.today
  9. grunt.util: 各种公用工具函数,以及集成了各种外部库,包括 Lo-Dash,Async,Hook 等

小结

本文介绍了基于 Node.js 的自动化构建工具 Grunt.js,展示了其基本组成、安装步骤,配置文件示例以及运行示例,并且列出了流行的 Grunt 插件以及其 API 扩展接口。

作者简介:

申健,在跨国企业从事 __8__ 年以上的研发和管理工作,涉及电信、金融、互联网等领域,拥有丰富的移动应用程序和面向服务分布式系统的项目经验。2007__ 年开始接触敏捷开发。对大型组织(500__ 人以上_)的敏捷转型,以及敏捷工程实践的落地运用具有丰富的经验。拥有 __CSP, CSM。擅长面向服务 __(SOA)_的分布式架构分析,以及移动应用的前后端整体解决方案。天津软件沙龙和敏捷之旅天津站等活动的组织者。


感谢田永强对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2013-06-04 09:4713875

评论

发布
暂无评论
发现更多内容

安防小区管控系统建设,智慧社区智能化集成方案

t13823115967

智慧平安社区平台建设

公安大数据:警务大数据分析系统解决方案

t13823115967

智慧公安

vivo 微服务 API 网关架构实践

vivo互联网技术

微服务 API网关 Zuul2

UBI波场挖矿系统软件APP开发

系统开发

Vmware+Centos设置静态IP

千泷

Spark的分布式存储系统BlockManager全解析

华为云开发者联盟

spark 分布式 存储

11 组关系带你看清 JVM 全貌

田维常

JVM

详解Spring5+SpringMVC5+MyBatis3.X,同时整合Redis缓存+ActiveMQ+项目等

Java架构追梦

Java spring 架构 mybatis springmvc

天天CRUD,被领导怼,我是如何从小公司菜鸡到阿里P8架构师?,首次分享Java程序员黄金五年进阶心得

Java架构之路

Java 程序员 架构 面试 编程语言

年轻人不讲武德,乱用索引,你到底走了多少弯路?

比伯

Java 编程 架构 面试 程序人生

数据结构与算法经典问题解析-Java语言描述

田维常

数据结构

为什么你成为不了团队核心成员

数据社

团队 七日更

测开之函数进阶· 第1篇《递归函数》

清菡软件测试

测试开发

业务重要?还是技术重要?

数据社

思考 团队 七日更

全面到哭!阿里内部疯传Netty实战文档程序员必须人手一份

比伯

Java 编程 架构 程序人生 编程语言

淘宝|蚂蚁|菜鸟|盒马|滴滴|饿了么面经,已拿多个offer(Java岗)

Java架构之路

Java 程序员 架构 面试 编程语言

Alibaba技术专家必知必会的Java技术知识点,掌握这些理论+实践+技术是你通往阿里的路

Java架构之路

Java 程序员 架构 面试 编程语言

BATJ真题突击:Java基础+JVM+分布式高并发+网络编程+Linux

Java架构之路

Java 程序员 架构 面试 编程语言

iOS面试基础知识 (三)

iOSer

ios 面试 ios开发

4. 上新了Spring,全新一代类型转换机制

YourBatman

Spring Framework 类型转换 Converter

Code Shared & Review(20201214-20201220)

刘璐

优化PostgreSQL Autovacuum

PostgreSQLChina

数据库 postgresql 开源 优化

ETHERZ流动性挖矿系统软件APP开发

系统开发

关于代码重构的灵魂三问:是什么?为什么?怎么做?

华为云开发者联盟

重构 代码 代码重构

Linux 如何实现定时调度任务

Near

Linux Timer 定时调度

Synchronized用法原理和锁优化升级过程(面试)

叫练

synchronized 轻量级锁 偏向锁 多线程与高并发 同步

AlibabaP8架构师整理,283页的Java核心资料pdf文档,学会后月薪4W没问题

Java架构之路

Java 程序员 架构 面试 编程语言

盘点2020 | 2020年读过的这些书

xcbeyond

读书感悟 盘点2020 七日更

基于Node.js的自动化构建工具Grunt.js_JavaScript_申健_InfoQ精选文章