您的位置:首页 > 移动开发

APPRTC分析系列0--grunt过程分析0

2016-08-20 17:43 183 查看

一、grunt工具分析

apprtc的编译步骤为:

npm install

grunt build

网上查阅资料,发现grunt为一种构建项目的方式,其基本介绍为

http://www.gruntjs.net/getting-started

通过该介绍可以发现,grunt是通过npm安装和管理的,而npm又是node.js的包管理器。

在编译apprtc之前,需要安装的grunt-cli为Grunt命令行。执行的npm install -g grunt-cli为将命令行安装到全局环境中,其中的-g参数代表global全局的意思,这是npm install的参数。

安装完grunt-cli后,grunt命令就被加入到系统路径中了。

二、grunt过程分析

1、npm install

在apprtc目录下面执行npm install时,npm包管理器读取apprtc目录下面的package.json中的内容,并安装必要的包。

如,apprtc目录下的package.json内容如下

{
"name": "apprtc",
"version": "1.0.0",
"description": "Project checking for AppRTC repo",
"license": "BSD-3-Clause",
"main": "Gruntfile.js",
"repository": {
"type": "git",
"url": "https://github.com/webrtc/apprtc.git"
},
"scripts": {
"test": "grunt --verbose"
},
"devDependencies": {
"grunt": "^0.4.0",
"grunt-cli": ">=0.1.9",
"grunt-closurecompiler": ">=0.0.21",
"grunt-contrib-compress": "^0.13.0",
"grunt-contrib-csslint": ">=0.3.1",
"grunt-contrib-jshint": ">=0.10.0",
"grunt-htmlhint": ">=0.9.12",
"grunt-jinja": ">=0.3.0",
"grunt-jscs": ">=0.8.1",
"grunt-jstestdriver-phantomjs": ">=0.0.7",
"grunt-shell": "^1.1.1",
"socket.io-client": "^1.2.0",
"webrtc-adapter": "^1.0.6"
}
}


猜测npm install会安装package.json中的devDependencies对应的值,即各种必要的依赖,包括一些grunt插件。这些插件将会在后面执行grunt命令时使用。

npm install执行完之后,会在apprtc目录下面生成node_modules目录,该目录下面是npm intall安装的node.js包。查看node_modules目录下内容,发现和devDependencies值列表相同。证明刚才的npm install命令是执行安装package.json中devDependencies的包列表。

也可以通过在apprtc下面,执行npm list命令查看该目录下安装的nodejs包的结构。

2、grunt build[/b]

apprtc目录中存在一个Gruntfile.js的文件。里面涉及到grunt命令时的一系列东东。其介绍也在http://www.gruntjs.net/getting-started中。有兴趣的可以自己看一下。我们依据上面链接提供的知识来分析一下grunt build到底执行了什么。

看一下文件内容中的

grunt.registerTask('default', ['csslint', 'htmlhint', 'jscs', 'jshint',
'runPythonTests', 'shell:genJsEnums', 'jstests']);
grunt.registerTask('travis', ['shell:getPythonTestDeps',
'shell:installPythonTestDepsOnLinux',
'default']);
grunt.registerTask('runPythonTests', ['shell:buildAppEnginePackageWithTests',
'shell:getPythonTestDeps',
'shell:runPythonTests',
'shell:removePythonTestsFromOutAppEngineDir']);
grunt.registerTask('jstests', ['shell:genJsEnums', 'closurecompiler:debug', 'grunt-chrome-build', 'jstdPhantom']);
// buildAppEnginePackage must be done before closurecompiler since buildAppEnginePackage resets out/app_engine.

grunt.registerTask('build', [`'shell:buildAppEnginePackage', 'shell:genJsEnums', 'closurecompiler:debug', 'grunt-chrome-build'`]);


grunt.registerTask是一个grunt的api,其原型为grunt.registerTask(taskname,tasklist).其中tasklist必须是一个任务数组。其中的taskname为一个任务别名。在命令行执行grunt taskname时,会依次执行tasklist中的任务。

实际上grunt build是在执行Gruntfile.js文件中的build任务。而我们找一下,发现build任务是一个任务列表的别名。

按照文件规定,其会依次执行

'shell:buildAppEnginePackage',
'shell:genJsEnums',
'closurecompiler:debug',
'grunt-chrome-build'


这4个任务。

以shell:buildAppEnginePackage任务为例。

其中的shell为任务名,而buildAppEnginePackage为shell任务下的一个目标名。

在文件中寻找一下,发现shell任务属性如下:

shell: {
getPythonTestDeps: {
command: 'python build/get_python_test_deps.py'
},
installPythonTestDepsOnLinux: {
command: 'python build/install_webtest_on_linux.py webtest-master/'
},
runPythonTests: {
command: ['python', 'build/run_python_tests.py', 'google_appengine/',
out_app_engine_dir, 'webtest-master/'].join(' ')
},
buildAppEnginePackage: {
command: ['python', './build/build_app_engine_package.py', 'src',
out_app_engine_dir].join(' ')
},
buildAppEnginePackageWithTests: {
command: ['python', './build/build_app_engine_package.py', 'src',
out_app_engine_dir, '--include-tests'].join(' ')
},
removePythonTestsFromOutAppEngineDir: {
command: ['python', './build/remove_python_tests.py',
out_app_engine_dir].join(' ')
},
genJsEnums: {
command: ['python', './build/gen_js_enums.py', 'src',
'src/web_app/js'].join(' ')
},
},


从以上内容可以看到,buildAppEnginePackage的实质是执行

'python', './build/build_app_engine_package.py', 'src',
out_app_engine_dir


其中的out_app_engine_dir在文件开头定义,内容如下:

/* globals module */
var out_app_engine_dir = 'out/app_engine';


所以,buildAppEnginePackage应该是要执行

'python', './build/build_app_engine_package.py', 'src','out/app_engine'


更具体的含义就需要查看对应的python文件了。

类似的

‘shell:genJsEnums’,对应

'python', './build/gen_js_enums.py', 'src','src/web_app/js'


‘closurecompiler:debug’对应:

closurecompiler: {
debug: {
files: {               文件对象格式,一个目标可以多个src-dest对。
// Destination: [source files]
'out/app_engine/js/apprtc.debug.js': [       //其中out/app_engine/js/apprtc.debug.js为dest文件,属性名;[]为src文件
'node_modules/webrtc-adapter/out/adapter.js',
'src/web_app/js/analytics.js',
'src/web_app/js/enums.js',
'src/web_app/js/adapter.js',
'src/web_app/js/appcontroller.js',
'src/web_app/js/call.js',
'src/web_app/js/constants.js',
'src/web_app/js/infobox.js',
'src/web_app/js/peerconnectionclient.js',
'src/web_app/js/remotewebsocket.js',
'src/web_app/js/roomselection.js',
'src/web_app/js/sdputils.js',
'src/web_app/js/signalingchannel.js',
'src/web_app/js/stats.js',
'src/web_app/js/storage.js',
'src/web_app/js/util.js',
'src/web_app/js/windowport.js',
]
},
options: {
'compilation_level': 'WHITESPACE_ONLY',
'language_in': 'ECMASCRIPT5',
'formatting': 'PRETTY_PRINT'
},
},


分析一下:

closurecompiler:debug的会从如下一堆文件

'node_modules/webrtc-adapter/out/adapter.js',
'src/web_app/js/analytics.js',
'src/web_app/js/enums.js',
'src/web_app/js/adapter.js',
'src/web_app/js/appcontroller.js',
'src/web_app/js/call.js',
'src/web_app/js/constants.js',
'src/web_app/js/infobox.js',
'src/web_app/js/peerconnectionclient.js',
'src/web_app/js/remotewebsocket.js',
'src/web_app/js/roomselection.js',
'src/web_app/js/sdputils.js',
'src/web_app/js/signalingchannel.js',
'src/web_app/js/stats.js',
'src/web_app/js/storage.js',
'src/web_app/js/util.js',
'src/web_app/js/windowport.js',


生成
out/app_engine/js/apprtc.debug.js
文件

生成过程中,采用options中的属性,其中的具体含义没有找到确切的答案。

‘grunt-chrome-build’对应

'grunt-chrome-build' : {
apprtc: {
options: {
buildDir: 'out/chrome_app',
zipFile: 'out/chrome_app/apprtc.zip',
// If values for chromeBinary and keyFile are not provided, the packaging
// step will be skipped.
// chromeBinary should be set to the Chrome executable on your system.
chromeBinary: null,
// keyFile should be set to the key you want to use to create the crx package
keyFile: null,
appwindowHtmlSrc: 'src/web_app/html/index_template.html',
appwindowHtmlDest: 'out/chrome_app/appwindow.html'
},
files: [       //文件数组格式,多个src-dest文件映像,同时支持每个src-dest有各自的属性 files:[]为文件数组格式,files:{}为文件对象格式,区别在于是否允许不同的src-dest有不同的属性
{
expand: true,                      //处理大量的单一文件时,用来动态的构建文件列表。expand 为true时
cwd: 'src/web_app/chrome_app',     //为之后src文件匹配时,都是相对此处的路径
src: [
'manifest.json'                  //应该src文件就是src/web_app/chrome_app/manifest.json
],
dest: 'out/chrome_app/'            //目标文件路径前缀
},
{
//expand属性为true时,后面的src/dest的路径都是相对cwd路径而言的
expand: true,
cwd: out_app_engine_dir,
src: [
//通配符筛选文件,**可以表示文件路径,*表示任意数目字符,但不能代替‘/’
'**/*.js',
'**/*.css',
'**/images/apprtc*.png',
'!**/*.pem'
],
dest: 'out/chrome_app/'
},
{
expand: true,
cwd: 'src/web_app',
src: [                   //文件操作中的简洁模式,一个src-dest对。源文件为src值,目标文件为dest值,都是相对cwd值的路径,即src第一个文件为src/web_app/js/background.js
'js/background.js',
'js/appwindow.js',
'!**/*.pem'
],
dest: 'out/chrome_app/'
}
],
}
},


具体执行应该是执行这4个任务。这4个任务的更具体的含义,之后有时间来分析一下。

本人也是边学习新知识边分析apprtc.欢迎指正!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: