Cordova 3.x 源码分析(1) -- Cordova CLI

[b](1)Node.js的使用[/b]
Cordova CLI基于node.js,所以有必要知道nodejs最基本的知识。
// define:1个module1个js文件
exports.printFoo = function(){ return "foo" }
// import
var foo = require('./foo.js');
// call
console.log(foo.printFoo());


[quote]node main.js[/quote]

[b](2)2个重要的路径[/b]
[list][*]C:\Documents and Settings\RenSanNing\Application Data\npm\node_modules\cordova
[*]C:\Documents and Settings\RenSanNing\.cordova\lib (以下简称LIB_ROOT)[/list]
最新源码可以从Github下载,目前稳定版是3.4。
[url=https://github.com/apache/cordova-cli]https://github.com/apache/cordova-cli[/url]
[url=https://github.com/apache/cordova-android]https://github.com/apache/cordova-android[/url]

[b](3)输入命令到执行完的过程[/b]
安装完Nodejs后,npm的路径就被放到了环境变量PATH中。
[quote]C:\Documents and Settings\RenSanNing\Application Data\npm[/quote]
以下简称NPM_ROOT,安装完Cordova后,在这个文件夹下有:
[list]
[*]cordova.cmd(windows batch)
[*]cordova(linux shell)
[/list]
所以在输入cordova cli命令时,入口就是这两个文件,以下以cordova.cmd为例说明。

a) 输入命令(根据不同的命令处理不同,这里以添加平台支持为例)
[quote]cordova platform add android[/quote]

b) 执行<NPM_ROOT>/cordova.cmd
[quote]node "%~dp0\node_modules\cordova\bin\cordova" %*[/quote]
其中%~dp0代表的是batch文件所在路径,比如执行C:\bat_files\example.bat,那么%~dp0 就是 C:\bat_files\。这里就是指NPM_ROOT。类似shell的$0就是Windows下batch文件中获取参数的一种方式,可以在命令行窗口执行“for /?”可以查看详细说明。启动node执行cordova(nodejs)文件,并把所有参数传给它。(%*:输入的所有参数)

c) 执行cordova(nodejs)
路径:<NPM_ROOT>\node_modules\cordova\bin
nodejs文件:cordova
addTs()函数是打印执行时间,默认未开启,所以只要代码是:
var CLI = require('../src/cli');
new CLI(process.argv);

****cordova.cmd 作用和npm文件夹下的cordova.cmd一样,%~dpn0 代表带路径的batch文件名。

d) 进入<NPM_ROOT>\node_modules\cordova\src\cli.js
d.1)// 导入node_modules\cordova\cordova.js
var cordova = require('../cordova');
-> // 导入node_modules\cordova\src\util.js
-> var cordova_util = require('./src/util');
-> // 通过addModuleProperty()方法加载不同命令的(比如这里的platform)代码
-> addModuleProperty(module, 'platform', './src/platform', true);
d.2)对输入参数进行解析提取
d.3)根据不同命令执行cordova.raw[cmd].call();
比如调用platform()方法。

e) 进入<NPM_ROOT>\node_modules\cordova\src\platform.js
function platform(command, targets) {
// 验证当前文件夹是否是Cordova-based project
var projectRoot = cordova_util.cdProjectRoot();
// 获取Hooks文件
var hooks = new hooker(projectRoot);
// ...
// 调用相应的方法(比如:add)******
add(hooks, projectRoot, targets, opts)
}


function add(hooks, projectRoot, targets, opts) {
// 读入config.xml
var xml = cordova_util.projectConfig(projectRoot);
var cfg = new ConfigParser(xml);

// 执行before_platform_add的Hook
hooks.fire('before_platform_add', opts)

// 获取libDir的目录即: <LIB_ROOT>\android\cordova\3.4.0
lazy_load.based_on_config(projectRoot, t)
// 调用Android SDK******
call_into_create(t, projectRoot, cfg, libDir, template, copts)

// 执行after_platform_add的Hook
hooks.fire('after_platform_add', opts);
}


function call_into_create(target, projectRoot, cfg, libDir, template_dir, opts) {
// ...

// 检查平台依赖***0***
module.exports.supports(projectRoot, target)

var bin = path.join(libDir, 'bin', 'create');

// 调用bat创建project***1***
superspawn.spawn(bin, args, opts || { stdio: 'inherit' })

// 调用prepare
require('../cordova').raw.prepare(target);

// 把merges文件夹下的文件覆盖过去
createOverrides(projectRoot, target);

// 通过plugman安装plugins下的所有插件***2***
plugman.raw.install(target, output, path.basename(plugin), plugins_dir);
}


***0***
function supports(project_root, name) {、
// 平台配置解析文件 <NPM_ROOT>\node_modules\cordova\platforms.js
// 具体Android在:src\metadata\android_parser
var platforms = require('../platforms');
var platformParser = platforms[name].parser;

// 检查平台依赖lib是否存在
platformParser.check_requirements(project_root);
}


***1***
进入 <LIB_ROOT>\android\cordova\3.4.0\bin
create.bat
[quote]SET script_path="%~dp0create"
node %script_path% %*[/quote]

create(nodejs)
var create = require('./lib/create');
create.createProject(args._[0], args._[1], args._[2], args._[3], args['--shared'], args['--cli']).done();


进入 <LIB_ROOT>\android\cordova\3.4.0\bin\lib
create.js
说是创建其实大部分都是从libdir拷贝过来的,执行了一下“android update project”。
[quote]C:\Documents and Settings\RenSanNing\.cordova\lib\android\cordova\3.4.0[/quote]
exports.createProject = function(project_path, package_name, project_name, project_template_dir, use_shared_project, use_cli_template) {
// ...

// 检测Ant(ant -version),Java(java -version),Android(android list targets)
check_reqs.run();

// 前边有很多Copy文件的准备工作,其中最重要的cordova.js就是从以下路径Copy过来的。
// <LIB_ROOT>\android\cordova\3.4.0\framework\assets\www\cordova.js

// 这里就是创建Android工程的具体实现
// cmd:android update project --subprojects --path "platforms\android" --target android-19 --library "CordovaLib"
// CordovaLib工程也是从<LIB_ROOT>\android\cordova\3.4.0\frameworkCopy过去的
// target_api取得是<LIB_ROOT>\android\cordova\3.4.0\framework\project.properties的target=android-19
runAndroidUpdate(project_path, target_api, use_shared_project);
}


***2***
进入 <NPM_ROOT>\node_modules\cordova\node_modules\plugman
plugman.js

进入 <NPM_ROOT>\node_modules\cordova\node_modules\plugman\src
install.js
function installPlugin(platform, project_dir, id, plugins_dir, options) {
//...
// 这里就是解析plugin.xml后安装plugin的具体实现
runInstall(current_stack, platform, project_dir, plugin_dir, plugins_dir, options)
//...
}


function runInstall(actions, platform, project_dir, plugin_dir, plugins_dir, options) {
//...
// Copy文件
copyPlugin();
handleInstall();
//...
}


function handleInstall(actions, plugin_id, plugin_et, platform, project_dir, plugins_dir, plugin_dir, filtered_variables, www_dir, is_top_level) {
//...
plugman.prepare(project_dir, platform, plugins_dir, www_dir);
//...
}


进入 <NPM_ROOT>\node_modules\cordova\node_modules\plugman\src
prepare.js
scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) { ' + scriptContent + '\n});\n';

从plugins往\platforms\android\assets\www\plugins下Copy插件JS代码的时候,添加了模块的定义,所以最终执行的插件的JS和安装的JS是不一样的。

// 生成cordova_plugins.js
var final_contents = "cordova.define('cordova/plugin_list', function(require, exports, module) {\n";
final_contents += 'module.exports = ' + JSON.stringify(moduleObjects,null,' ') + ';\n';
final_contents += 'module.exports.metadata = \n';
final_contents += '// TOP OF METADATA\n';
final_contents += JSON.stringify(pluginMetadata, null, ' ') + '\n';
final_contents += '// BOTTOM OF METADATA\n';
final_contents += '});';


以上过程只是主要的处理流程,至此Android项目创建成功,并且以下两个Cordova核心的js也放置到了相应的位置。
[list]
[*]platforms\android\assets\www\cordova.js
[*]platforms\android\assets\www\cordova_plugins.js
[/list]

其他的命令各自有各自的作用,所以处理内容不同。特别要说的是执行和project相关的命令时,最终会调用到各个平台工程下的脚本,比如:platforms\android\cordova。放在project下的目的除过各个平台的脚本不一样以外,也使该工程更独立,只要有Nodejs环境即可编译运行。
[list][*]prepare
[*]compile(platforms\android\cordova\build)
[*]build(prepare->compile)
[*]run(prepare->platforms\android\cordova\run)
[*]emulate(prepare->platforms\android\cordova\run) 比run多了个参数“--emulator”[/list]

参考:
[url=http://blog.csdn.net/mociml/article/category/1409992]http://blog.csdn.net/mociml/article/category/1409992[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值