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.欢迎指正!
相关文章推荐
- 【应聘笔记系列】堆栈、栈帧与函数调用过程分析
- hsqldb源码分析系列3 执行引擎分析 插入过程分析
- Wireshark系列之2 路由过程理论分析
- PDF阅读器系列之--MuPDF源码分析过程(一)
- Nimbus<一>Storm系列(五)架构分析之Nimbus启动过程
- AT91系列微处理器启动过程的分析与实现
- Redis分析系列:启动加载过程
- Storm系列(五)架构分析之Nimbus启动过程
- Extjs4 源码分析系列一 类的创建过程
- React-Native系列Android——Javascript文件加载过程分析
- hsqldb源码分析系列3 执行引擎分析 插入过程分析
- lucene4.5源码分析系列:搜索过程
- lucene4.5源码分析系列:搜索过程
- redis客户端Jedis源码分析系列——连接池的创建过程
- 代码分析系列 内存执行过程
- uboot系列之----Uboot配置过程详细分析
- lucene4.5源码分析系列:索引的创建过程
- samba系列问题之分析解决过程
- PDF阅读器系列之--MuPDF源码分析过程(一)
- uboot系列之----Uboot配置过程详细分析