grunt源码解析:整体运行机制&grunt-cli源码解析

前端的童鞋对grunt应该不陌生,前面也陆陆续续的写了几篇grunt入门的文章。本篇文章会更进一步,对grunt的源码进行分析。文章大体内容内容如下:

  1. grunt整体设计概览
  2. grunt-cli源码分析
  3. grunt-cli模块概览
  4. grunt-cli源码分析
  5. 写在后面
    Alt text

grunt整体设计概览

grunt主要由三部分组成。其中,grunt-cli是本文的讲解重点

  1. grunt-cli:命令行工具,调用本地安装的grunt来运行任务,全局安装。
  2. grunt:本地grunt,一般安装在项目根目录下。主要作用是读取插件配置,调用指定的grunt插件。
  3. grunt插件:完成具体的构建任务。

grunt运行机制

抛开代码细节,grunt运行的整体流程如下。接下来,我们就会对红框部分,grunt-cli的源码进行进一步的探讨。
Alt text

grunt-cli源码分析

grunt-cli/packge.json里可以看到,主入口文件是 bin/grunt。接下来,我们就分析下bin/grunt.js的源码。

"bin": {
    "grunt": "bin/grunt"
},

grunt-cli源码概览

同样,我们先通过一个简单的流程图看下这个文件究竟做了什么事情。从下图可以看到,主要包含三个逻辑分支。

  1. 运行任务:主要的分支,用绿色标出,比如运行grunt copy就会进入这个分支
  2. 信息查看:右侧的一堆if/else分支,如运行grunt --version就会进入这个分支(还有其他如help等没列出来)
  3. 异常处理:非上面两种情况,异常退出。

Alt text

查看信息

如果命令行中包含--completion--version

  • 如果有--completion,输出自动完成信息,程序退出
  • 如果有--version,输出版本信息,程序退出

运行任务

  1. 命令行中是否有--gruntfile--base
    • 都有:优先将basedir设置为gruntfile指定的路径
    • 只有gruntfilebase:将basedir设置为basegruntfile指定的路径
  2. 根据basedir找到当前项目的grunt,并运行指定任务

异常处理

如果没有包含--completion--version,当前项目下也没有安装grunt,异常退出。

grunt-cli模块概览

下图为grunt-cli的整体目录机构,相对比较简单。这里做下介绍

  1. bin/grunt:主入口文件,调用其他模块来完成工作。
  2. lib/*:被bin/grunt调用,主要有如下几个模块
    • cli.js:分析、处理命令行参数。
    • completion.js:处理自动完成信息。
    • info:打印版本、帮助信息等。

Alt text

grunt-cli源码分析

首先,引入组件的依赖模块

// Especially badass external libs.
var findup = require('findup-sync');  // 文件查找 var resolve = require('resolve').sync; // 路径解析 // Internal libs. var options = require('../lib/cli').options; // 解析后的命令行参数 var completion = require('../lib/completion'); // 自动完成 var info = require('../lib/info'); // 版本信息等 var path = require('path'); var basedir = process.cwd(); var gruntpath; 

然后,根据命令行参数,决定是否要打印版本信息、自动完成信息,还是设置当前的工作路径(basedir)

// Do stuff based on CLI options.
if ('completion' in options) {
  completion.print(options.completion); // 打印自动完成信息,程序退出 } else if (options.version) { info.version(); // 打印版本信息(在本地grunt里会退出) } else if (options.base && !options.gruntfile) { basedir = path.resolve(options.base); // 根据 base 设置 basedir } else if (options.gruntfile) { // 根据 gruntfile 设置 basedir basedir = path.resolve(path.dirname(options.gruntfile)); } 

最后的考验,如果能找到本地grunt,就进入最后一步;如果找不到,很有可能就异常退出了。

try {
  // 得到当前目录的本地grunt路径(grunt/lib/grunt.js)
  gruntpath = resolve('grunt', {basedir: basedir});  // 得到的是类似这样的路径 /Users/usename/Documents/code/edu_proj/trunk/htdocs/ke.qq.com/node_modules/grunt/lib/grunt.js
} catch (ex) { gruntpath = findup('lib/grunt.js'); // 有可能当前在项目的子目录里,逐级往上查找,直到找到 grunt // No grunt install found! if (!gruntpath) { // 找不到grunt,悲剧了 if (options.version) { process.exit(); } // 打印版本信息,退出 if (options.help) { info.help(); } // 打印帮助信息 info.fatal('Unable to find local grunt.', 99); // 打印错误日志,并异常退出 } } 

恭喜,来到这一步,可以愉快地运行构建任务了。

// Everything looks good. Require local grunt and run it.
require(gruntpath).cli();  // 找到 本地grunt了,开始运行 .cli 是local grunt的方法 

写在后面

本文对构建工具grunt的整体设计、运行机制,以及grunt-cli的源码进行了较为深入的分析。后续会对本地grunt的源码进行剖析,敬请期待。如有错漏,请指出。有任何疑问也可以在下面留言 :)

转载于:https://www.cnblogs.com/chyingp/p/grunt-cli-code-analyse.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值