Cordova CLI源码分析(三)——初始化
本部分主要涉及以下三个文件
1 cli.js
2 cordova.js
3 events.js
通过前一篇package.json的分析,可以知道,当命令行执行cordova相关命令时,首先调用main参数指向的cordova.js文件,加载模块的相关信息,把内部接口暴露出来,起到初始化作用,方便后续模块内部调用各部分接口;
然后bin 指向的./bin/cordova 文件,执行
1. .#!/usr/bin/env node
2. var CLI = require('../src/cli');
3. new CLI(process.argv);
调用 src/cli,js文件,这个文件才是真正解析命令行参数,并执行对应操作的内容;
cli.js源码
var optimist = require('optimist'),
cordova = require('../cordova'),
plugman = require('plugman'),
platforms = require("../platforms");
module.exports = function CLI(inputArgs) {
//inputArgs参数是process.argv,命令行参数数组
//第一个元素是node,第二个元素是脚本文件名,第三个元素开始每个元素是运行参数
//所以假设用户输入的是:cordova create hello hellotest com.jinkai.hellotest
//process.argv输出结果是:node cordova create hello hellotest com.jinkai.hellotest
args = optimist(inputArgs)
.boolean('d') //boolean判断命令行参数中是否存在d,如果有args.d返回true,否则false
.boolean('verbose')
.boolean('v')
.boolean('version')
.argv;//args.argv 返回命令参数
if (args.v || args.version) {
return console.log(require('../package').version);
}
//arrayObject.slice(start,end) 方法可从已有的数组中返回选定的元素
//start 必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
//end 可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。
//返回值:返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素
var tokens = inputArgs.slice(2), //inputArgs从数组中提取第三个元素(包含第三个)到最后,产生一个新数组
opts = {
platforms: [],
options: [],
verbose: (args.d || args.verbose)
},
cmd;
// provide clean output on exceptions rather than dumping a stack trace
process.on('uncaughtException', function(err){
if (opts.verbose) {
console.error(err.stack);
} else {
console.error(err);
}
process.exit(1);
});
cordova.on('results', console.log);
if (opts.verbose) {
cordova.on('log', console.log);
cordova.on('warn', console.warn);
plugman.on('log', console.log);
plugman.on('warn', console.warn);
//Remove the corresponding token
//删除token数组中的标识符,即-d ,--verbose这类参数
if(args.d && args.verbose) {
tokens.splice(Math.min(tokens.indexOf("-d"), tokens.indexOf("--verbose")), 1);
} else if (args.d) {
tokens.splice(tokens.indexOf("-d"), 1);
} else if (args.verbose) {
tokens.splice(tokens.indexOf("--verbose"), 1);
}
//arrayObject.splice(index,howmany,element1,.....,elementX) 函数
//index 必需。规定从何处添加/删除元素。
//howmany 必需。规定应该删除多少元素。必须是数字,但可以是 "0"。
//返回值:如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组
}
cmd = tokens && tokens.length ? tokens.splice(0,1) : undefined;
if (cmd === undefined) {
return cordova.help();
}
if (cordova.hasOwnProperty(cmd)) {
if (cmd == 'emulate' || cmd == 'build' || cmd == 'prepare' || cmd == 'compile' || cmd == 'run') {
// Filter all non-platforms into options
tokens.forEach(function(option, index) { //此处使用forEach遍历元素,不应使用for循环,避免node异步IO机制带来的问题
if (platforms.hasOwnProperty(option)) {
opts.platforms.push(option);
} else {
opts.options.push(option);
}
});
cordova[cmd].call(this, opts);
} else if (cmd == 'create' || cmd == 'serve') {
cordova[cmd].apply(this, tokens);
} else {
// platform/plugins add/rm [target(s)]
var invocation = tokens.slice(0,1); // this has the sub-command, i.e. "platform add" or "plugin rm"
var targets = tokens.slice(1); // this should be an array of targets, be it platforms or plugins
invocation.push(targets);
cordova[cmd].apply(this, invocation);
}
} else {
throw new Error('Cordova does not know ' + cmd + '; try help for a list of all the available commands.');
}
}
源码中加入了必要的注释;
这段代码的主要作用就
1)提取参数,然后调用针对命令参数,分别调用不同接口函数;
2)Log和debug信息输出设置判断
3)栈崩溃信息的美化处理
再来看一下cordova.js文件
var cordova_events = require('./src/events'),
prepare = require('./src/prepare'),
platform = require('./src/platform'),
run = require('./src/run'),
hooker = require('./src/hooker'),
util = require('./src/util'),
path = require('path'),
fs = require('fs'),
compile = require('./src/compile');
var off = function() {
cordova_events.removeListener.apply(cordova_events, arguments);
};
var emit = function() {
cordova_events.emit.apply(cordova_events, arguments);
};
module.exports = {
help: require('./src/help'),
config: require('./src/config'),
create: require('./src/create'),
platform: platform,
platforms: platform,
prepare: prepare,
compile: compile,
run: run,
ripple: require('./src/ripple'),
emulate: require('./src/emulate'),
plugin: require('./src/plugin'),
plugins: require('./src/plugin'),
serve: require('./src/serve'),
on: function() {
cordova_events.on.apply(cordova_events, arguments);
},
off: off,
removeListener:off,
removeAllListeners:function() {
cordova_events.removeAllListeners.apply(cordova_events, arguments);
},
emit: emit,
trigger: emit,
build: require('./src/build')
};
这段代码作用主要有三个:
1)包含依赖文件 require(....)函数部分
2)对node.js事件机制的包装,on 和off两个函数对应绑定事件和移除事件,emit 发射事件,其中cordova_events = require('./src/events') ,调用events.js
var events = require('events');
var emitter = new events.EventEmitter();
module.exports = emitter;
3)Module.exports中暴露出必要的参数接口
Cordova CLI源码分析(三)——初始化的更多相关文章
- Cordova CLI源码分析(四)——创建工程
在第一篇分析我们曾经举例,创建一个新工程, cordova create hello hellotest com.xxx.hellotest cli.js文件分析命令行参数后,会走到 else if ...
- Cordova CLI源码分析(一)——简介
本系列文章分析基于node.js的命令行工具Cordova CLI,所以如果对node.js基础不是很了解,建议参考http://nodejs.gamesys.net/node-js提供的基础教程 文 ...
- Cordova CLI源码分析(二)——package.json
每个包需要在其顶层目录下包含一个package.json文件,该文件不仅是包的说明,也影响npm安装包时的配置选项 更多参数详见参考文档https://npmjs.org/doc/json.html ...
- SpringMVC源码分析--容器初始化(三)HttpServletBean
在上一篇博客springMVC源码分析--容器初始化(二)DispatcherServlet中,我们队SpringMVC整体生命周期有一个简单的说明,并没有进行详细的源码分析,接下来我们会根据博客中提 ...
- SpringMVC源码分析--容器初始化(四)FrameworkServlet
在上一篇博客SpringMVC源码分析--容器初始化(三)HttpServletBean我们介绍了HttpServletBean的init函数,其主要作用是初始化了一下SpringMVC配置文件的地址 ...
- 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入
使用react全家桶制作博客后台管理系统 前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...
- tomcat源码分析(三)一次http请求的旅行-从Socket说起
p { margin-bottom: 0.25cm; line-height: 120% } tomcat源码分析(三)一次http请求的旅行 在http请求旅行之前,我们先来准备下我们所需要的工具. ...
- SpringMVC源码分析--容器初始化(五)DispatcherServlet
上一篇博客SpringMVC源码分析--容器初始化(四)FrameworkServlet我们已经了解到了SpringMVC容器的初始化,SpringMVC对容器初始化后会进行一系列的其他属性的初始化操 ...
- springMVC源码分析--容器初始化(二)DispatcherServlet
在上一篇博客springMVC源码分析--容器初始化(一)中我们介绍了spring web初始化IOC容器的过程,springMVC作为spring项目中的子项目,其可以和spring web容器很好 ...
随机推荐
- Minor GC、Major GC和Full GC之间的区别(转)
在 Plumbr 从事 GC 暂停检测相关功能的工作时,我被迫用自己的方式,通过大量文章.书籍和演讲来介绍我所做的工作.在整个过程中,经常对 Minor.Major.和 Full GC 事件的使用感到 ...
- 开始AFNetworking
郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助.欢迎给作者捐赠.支持郝萌主,捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 This ...
- 2006 ACM Northwestern European Programming Contest C题(二分求最大)
My birthday is coming up and traditionally I'm serving pie. Not just one pie, no, I have a numberN o ...
- javascript (八) 语法格式
JavaScript 对大小写敏感. JavaScript 对大小写是敏感的. 当编写 JavaScript 语句时,请留意是否关闭大小写切换键. 函数 getElementById 与 getEle ...
- 苹果新的编程语言 Swift 语言进阶(五)--控制流
Swift 语言支持C语言全部的控制语句.包含for 和while循环语句,if和switch条件语句,以及break和continue控制语句等. Swift 语言除了支持以上语句,还添加了一个f ...
- hdu 4706 Children's Day 2013年ICPC热身赛A题 模拟
题意:按字母顺序排列成n型,简单的模拟题. 当字母排到z时从a开始重新排起. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * Blog: ...
- C++中的函数模板
我们在定义函数时,可以通过定义函数模板,来简化一些功能相同而数据类型不同的函数的定义和调用过程. C++中的函数模板 对于类的声明来说,也有同样的问题.有时,有两个或多个类,其功能是相同的,仅仅是数据 ...
- mysql update改动多条数据
通常情况下,我们会使用下面SQL语句来更新字段值: 复制代码代码例如以下: UPDATE mytable SET myfield='value' WHERE other_field='other_va ...
- Swift - 使用UIView给页面添加4×4方格
1,下面是一个利用UIView来给页面上绘制灰色方块的例子,效果图如下: 代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ...
- go (break goto continue)
package main import ( "fmt" ) func main() { LABEL1: for { ; i < ; i++ { { break LABEL1 ...