Skip to content

Instantly share code, notes, and snippets.

@303182519
Created May 26, 2014 02:45
Show Gist options
  • Save 303182519/b5563564e775938ad9c3 to your computer and use it in GitHub Desktop.
Save 303182519/b5563564e775938ad9c3 to your computer and use it in GitHub Desktop.

grunt 运行分析


通过分析grunt,了解基于nodejs开发一些命令行工具,比如fis,spm、doxmate等等


grunt的安装(即工具的安装)

我们打开grunt的官网:http://gruntjs.com/getting-started,看到有一句命令

npm install -g grunt-cli

很多工具的安装基本上都是这样的命令,比如fis的安装,等等

npm install -g fis

当运行这个命令的时候,到底发生什么呢,其实这个要看npm里面的代码是怎么写的(这个另开专题说明,不在此文章之内),先看整体的,我们 在cmd命令工具中输入npm config list的时候,看到下面的信息

看红色的那块,这就是我们通过-g的方式安装的时候,都会安装到次目录当中,至于更多的npm命令可以查过我的blog的一篇文章

http://303182519.github.io/nodejs/2014/02/11/npm.html

grunt源码分析

我们打开grunt的github源码地址:

https://github.com/gruntjs/grunt-cli

可以看到有一个叫package.json的文件,打开看看,这是一个nodejs包的说明,其他的项目我就不说了,挑几个重点的,看注释

{
  "name": "grunt-cli",
  "description": "The grunt command line interface.",
  "version": "0.1.13",
  "author": "Grunt Team",
  "homepage": "http://gruntjs.com/",
  "repository": {
    "type": "git",
    "url": "git://github.com/gruntjs/grunt-cli.git"
  },
  "bugs": {
    "url": "http://github.com/gruntjs/grunt-cli/issues"
  },
  "licenses": [
    {
      "type": "MIT",
      "url": "http://github.com/gruntjs/grunt-cli/blob/master/LICENSE-MIT"
    }
  ],
  "bin": {  //这是命令行
    "grunt": "bin/grunt"  
  },
  "engines": {
    "node": ">= 0.8.0"
  },
  "scripts": {
    "test": "node bin/grunt test"
  },
  "preferGlobal": true,
  "dependencies": {   //这是依赖包,会随着这行的命令行 npm install -g grunt-cli 一起下载的包 
    "nopt": "~1.0.10",
    "findup-sync": "~0.1.0",
    "resolve": "~0.3.1"
  },
  "devDependencies": {  //这是做grunt这个工具用到的一个测试工具
    "grunt": "~0.4.0",
    "grunt-contrib-jshint": "~0.2.0"
  }
}

当我们输入npm install -g grunt-cli 的时候,npm就会分析这个package.json里面的一个bin和dependencies,根据bin的内容生成两个文件在你的系统上,文件存放的路径请看上面的npm config list里面的prefix。一个是给linux系统,一个是给window系统用的,我们用编辑器打开cmd后缀的文件

:: Created by npm, please don't edit manually.
@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe"  "%~dp0\node_modules\grunt-cli\bin\grunt" %*
) ELSE (
  node  "%~dp0\node_modules\grunt-cli\bin\grunt" %*
)

大概的意思就是,这个文件是npm生成的,请不要手动编辑他。判断里面当前目录有没有node.exe,没有的话,就直接通过node命令运行当前目录下的\node_modules\grunt-cli\bin\grunt

其实也就是相当于通过node xx.js运行一个js,只是这里用npm包装了一层。

而依赖包dependencies就会安装到grunt-cli下的一个node_modules下。

而至于为什么我们能通过grunt命令运行当前目录的东西,是因为我们之前安装npm的时候,向我们的环境变量里填加了当前的路径

grunt-cli源码

这里面基本上都是js代码了

//在Linux系统下,我们可以把JS文件当作shell脚本来运行
#!/usr/bin/env node

'use strict';

process.title = 'grunt';

// 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;

// Do stuff based on CLI options.
if ('completion' in options) {
  completion.print(options.completion);
} else if (options.version) {
  info.version();
} else if (options.gruntfile) { //Note: if both `gruntfile` and `base` are set, use `gruntfile`
  basedir = path.resolve(path.dirname(options.gruntfile));
} else if (options.base) {
  basedir = path.resolve(options.base);
}

try {
  //返回当前目录的grunt文件的路径 	
  gruntpath = resolve('grunt', {basedir: basedir});
} catch (ex) {
  gruntpath = findup('lib/grunt.js');
  // No grunt install found!
  if (!gruntpath) {
    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();
@hoozi
Copy link

hoozi commented May 26, 2014

沙发是我的

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment