阿里前端学习笔记(一)

2014-07-13 by niuzhixiang

Git的使用

Git与SVN的比较

  • SVN需要有一个主干(trunk),而若干个分支(branch)只能合并到主干,分支之间不能直接合并。相当于必须要以主干作为中转,才能实现分支的合并。
  • Git中没有主干的概念,只有分支的概念。其中一个名为master的分支作为主分支,类似于SVN中的主干。但是master本质上也只是一个分支,与其他分支无异。Git可以支持分支之间直接合并,比较灵活,适用于互联网前端开发这种需求变化较大的应用场景。
  • SVN的提交操作(commit)是直接将本地代码上传到远程仓库中。
  • Git的提交操作是先将本地代码提交到本地仓库(通过git commit命令),然后再将本地仓库中的代码“推送”到远程仓库中(通过Git的push命令)。
  • SVN中的版本控制是以“文件”为单元的,项目中的每一个文件都有自己的版本历史。
  • Git中的版本控制是以整个项目为单元的,整个项目作为一个整体,有一个统一的版本历史。
  • SVN远程仓库中存储的是各个版本的全量拷贝。
  • Git远程仓库中存储的是各个版本之间的增量变化(实际上是每个版本的“快照”),因此所需的存储空间较小。

Git常用命令

  • 从Git远程仓库中将项目复制到本地,使用git clone命令(该命令类似于SVN中的checkout,但在Git中checkout命令用于切换本地分支)。举例:git clone git@github.com:drogba321/alibaba-learning-docs.git
  • 新建一个项目以后,首先要使用git init命令进行git初始化(创建.git隐藏文件夹,表示这是一个git项目)。然后使用git remote add命令创建远程仓库。举例:git remote add origin git@gitlab.alibaba-inc.com:trip/h5-test.git(该命令的意思是,创建一个名为origin的远程仓库,其git地址为git@gitlab.alibaba-inc.com:trip/h5-test.git)。
  • 新增文件、修改文件和删除文件后,要首先将这些变化添加到版本控制中,使用git add命令(类似于SVN中的add)。举例:git add .(圆点符“.”代表将当前目录下的所有内容都添加到版本控制中)。
  • Git add之后,要完成提交,第一步需要将代码提交到本地仓库,使用git commit命令。举例:git commit -m 'this is the first commit'(引号中的内容为该版本的提交信息)。
  • 第二步是将本地仓库中的代码“推送”到远程仓库,使用git push命令,举例:git push origin daily/0.1.1:daily/0.1.1(origin为远程仓库的名称,第一个daily/0.1.1是本地分支的名字,第二个daily/0.1.1是远程分支的名字。该命令的意思是,将本地分支daily/0.1.1的代码推送到远程仓库origin的分支daily/0.1.1下)。
  • 将远程仓库中的代码更新到本地,使用git pull命令(类似于SVN中的update)。举例:git pull origin daily/0.1.1(该命令的意思是,将远程仓库origin的内容更新到本地分支daily/0.1.1);或者git pull origin master:daily/0.1.1(该命令的意思是,将远程仓库origin的远程分支master更新到本地分支daily/0.1.1。该命令可能会被reject,原因有待研究)。
  • 切换本地分支,使用git checkout命令。举例:git checkout master(该命令的意思是,将本地分支切换到master分支)。
  • 查看当前状态,包括当前本地所处的分支,有哪些修改等等,使用git status命令。
  • 查看本地与远程分支的列表,使用git branch命令。如果只想查看远程分支的列表,使用git branch -r命令。如果要新建分支,使用git branch [newBranchName]命令(其中newBranchName为新分支名)

本机开发环境

操作方法

  • 首先,在浏览器中开启正向代理127.0.0.1:8080
  • 然后,进入项目根目录(也即Gruntfile.js所在目录)执行grunt demo(源码调试,一般调试的是src目录下的代码)或者grunt debug(目标代码调试,一般调试的是build目录下的代码)。该指令会开启两个服务:本机8080端口上的反向代理服务,以及本机8081端口上的flexcombo服务(这两个服务的端口号默认分别为8080和8081,不过也可以自己配置)。
  • 最后,用浏览器访问demo.com/{path}demo.com/{path}?ks-debug(后者开启了kissy调试功能),进行代码的调试。

原理

在浏览器开启正向代理“127.0.0.1:8080”后,所有在浏览器地址栏输入的url都会交给该代理来处理,即交给本机的8080端口来处理;而执行grunt demogrunt debug命令后,在本机的8080端口上会开启一个反向代理服务(这个端口由配置参数proxyport指定,默认为8080)。于是url请求便由反向代理接管。如果请求地址为配置参数proxyHosts指定的域名(例如demo.com)或[ag].tbcdn.cn,则反向代理服务器会将请求转发至flexcombo服务器(flexcombo服务器也是由grunt demo/debug启动的,flexcombo的端口由配置参数port指定,默认为80),flexcombo服务器接收到url请求后,会去配置参数target指定的本地路径取文件;如果请求地址是其它域名,则反向代理服务器去公网取文件。这种方式可以模拟真实环境的调试(例如在淘宝首页中调试Slide组件:淘宝首页引用Slide组件的路径是http://g.tbcdn.cn/kg/slide/1.2/index.js,在开启浏览器正向代理和grunt debug后,由于该请求域名为g.tbcdn.cn,所以该请求最终会返回本地build目录下的目标代码文件./build/index.js,从而实现本地代码模拟真实线上环境的调试)。以下是Gruntfile.js中关于flexcombo配置的代码片段。

  1. grunt.initConfig({
  2. // FlexCombo服务配置
  3. // https://npmjs.org/package/grunt-flexcombo
  4. //
  5. // 注意:urls 字段末尾不能有'/'
  6. flexcombo : {
  7. // 源码调试服务
  8. demo : {
  9. options : {
  10. //反向代理服务器的端口,一般取8080
  11. proxyport : '8080',
  12. //flexcombo将特定域名下的请求映射到的本地路径,源码调试一般为'src/',目标代码调试一般为'build/'
  13. target : 'src/',
  14. //flexcombo将[ag].tbcdn.cn域名下的该url请求映射到target指定的本地路径下,例如http://g.tbcdn.cn/kg/slide/index.js => ./src/index.js
  15. urls : '/kg/<%= pkg.name %>/',
  16. //flexcombo服务器的端口,默认为80,一般取8081
  17. port : '8081',
  18. //flexcombo对这些域名的请求也映射到target指定的本地路径下,例如http://demo.com/d1.html => ./src/d1.html
  19. proxyHosts : ['demo', 'demo.com'],
  20. servlet : '?',
  21. longPolling : false,
  22. separator : ',',
  23. charset : 'utf8'
  24. }
  25. },
  26. // 目标代码调试服务
  27. debug : {
  28. options : {
  29. // 无线H5项目调试,可打开host配置,用法参照
  30. // https://speakerdeck.com/lijing00333/grunt-flexcombo
  31. target : 'build/',
  32. proxyport : '8080',
  33. urls : '/kg/<%= pkg.name %>/<%= pkg.version %>',
  34. port : '8081',
  35. proxyHosts : ['demo', 'demo.com', 'h5.m.taobao.com'],
  36. servlet : '?',
  37. separator : ',',
  38. longPolling : false,
  39. charset : 'utf8',
  40. filter : {
  41. '-min\\.js' : '.js',
  42. }
  43. }
  44. }
  45. }
  46. });

另外,flexcombo在处理请求url时,还会读取src/config.js中的配置,如果请求url后面挂着“?ks-debug”,则说明是开启kissy调试,flexcombo会返回本地的js文件,这样可以供调试js代码用;如果请求url后面没有挂着“?ks-debug”,则说明未开启kissy调试,flexcombo会返回“g.assets.daily.taobao.net”(预发环境)或“g.tbcdn.cn”(线上环境)域名下面的js文件,而如果此时代码还未预发到预发环境,或还未正式发布到线上环境,则这些域名下就不会有相应的js文件,就无法进行js代码的调试了。(注:如果是线上环境g.tbcdn.cn域名下,则该请求最终仍会由flexcombo映射到本地文件,具体详情请自行深入分析~)以下是src/config.js的源代码示例。

  1. (function(){
  2. KISSY.config('tag', null);
  3. var debug = (location.search.indexOf('ks-debug') >= 0);
  4. if (debug) {
  5. var srcPath = "../../";
  6. KISSY.config({
  7. combine:false,
  8. packages:[
  9. {
  10. /*注:这里的name对应于在使用Kissy模块时的包名。例如在使用这个模块时:
  11. KISSY.use('h5-2banner-active/pages/secondpage/index', ...);
  12. 其中使用的包名'h5-2banner-active'就对应于这里的name参数。它的路径
  13. 由path参数指定,此处即'../../'。因此最终实际使用的是在这个路径下
  14. '../../pages/secondpage/index.js'的模块。*/
  15. name:"h5-2banner-active",
  16. path:srcPath,
  17. charset:"utf-8",
  18. ignorePackageNameInUri:true,
  19. debug:true
  20. }
  21. ]
  22. });
  23. } else {
  24. if (location.host.match(/(waptest\.taobao|wapa.taobao|daily.taobao.net)/)) {
  25. KISSY.Config.daily = true;
  26. }
  27. var srcHost = KISSY.Config.daily ?
  28. 'g.assets.daily.taobao.net' :
  29. 'g.tbcdn.cn';
  30. KISSY.config({
  31. combine:true,
  32. packages: [
  33. {
  34. name: 'h5-2banner-active',
  35. path: 'http://' + srcHost +'/trip/h5-2banner-active/@@version',
  36. ignorePackageNameInUri: true
  37. }
  38. ]
  39. });
  40. }
  41. })();

项目构建及配置

操作方法

Grunt工具执行的任务:

  • build:执行构建(包括将src目录下的源码文件进行kmc合并、less/sass编译、代码压缩等操作,最后生成build目录下的目标代码文件)。
  • demo:进行源码调试(调试src目录下的源代码)。
  • debug:进行目标代码调试(调试build目录下的目标代码)。
  • newbranch:创建一个新的本地日常分支,并切换到该分支下。
  • prepub:预发布资源文件(js、css文件等),将资源文件发布到日常环境(“g.assets.daily.taobao.net”域名下)。事实上,该任务就是使用git push命令将代码提交到日常分支(daily分支)。
  • publish:正式发布资源文件,将资源文件发布到线上环境(“g.tbcdn.cn”域名下)。事实上,该任务就是使用git push命令将代码提交到线上分支(publish分支)。
  • awpp:发布H5页面。可以选择发布到“日常”/“预发”/“预上线”/“上线”这四个环境中。
  • 备注:对于H5页面文件,一共有四个环境:日常(wapp.waptest.taobao.com)、预发(wapp.wapa.taobao.com)、预上线(不清楚~)和上线(h5.m.taobao.com)(均通过grunt awpp任务发布,执行该任务时命令行会提示选择具体发布到哪个环境);而对于js、css等资源文件,一共只有两个环境:预发(g.assets.daily.taobao.net)(或称日常,通过grunt prepub任务发布)和线上(g.tbcdn.cn)(通过grunt publish任务发布)。

Yeoman工具和Clam脚手架工具执行的构建任务:

  • yo clam:初始化一个标准的项目。包括生成该项目的Gruntfile.jspackage.jsonabc.json等配置文件;生成src目录等等。
  • yo clam:h5:初始化一个H5页面。该命令应当在src/pages目录下执行,会生成标准的页面模板index.html,并自动生成配套的index.jsindex.less等文件。
  • yo clam:mod:初始化一个模块。应在src/mods目录下执行。
  • yo clam:widget:初始化一个widget(即一个标准的kissy组件),应在src/widgets目录下执行。
  • yo clam:h:显示帮助信息。

原理

grunt任务都是在Gruntfile.jspackage.json配置文件中定义并注册的。每个任务本质上就是一个命令集合,是对常用命令的进一步封装。如果想要自定义一个新任务或者修改已有任务的执行方式,直接编辑Gruntfile.js源文件即可。以下代码为Gruntfile.js配置文件中对于任务“build”的定义。可以看出,build任务就是按顺序执行copy、less、sass、kmc、tms等等这些子任务(这些子任务在别处已经定义过了)。

  1. // build任务
  2. grunt.registerTask('exec_build', '执行构建脚本', function () {
  3. var actions = [
  4. 'clean:build',
  5. //'tpl_compiler',
  6. 'copy',
  7. 'less',
  8. 'sass',
  9. /*'mytps',*/
  10. 'kmc',
  11. 'tms'
  12. ];
  13. if(isH5){
  14. actions = actions.concat([
  15. 'inline-assets'
  16. ]);
  17. }
  18. actions = actions.concat([
  19. 'combohtml',
  20. 'replace:dist',
  21. 'uglify',
  22. 'cssmin'
  23. ]);
  24. task.run(actions);
  25. });

此外,这些构建任务中所使用到的nodejs模块都放在node_modules目录下了,例如grunt-flexcombo模块、grunt-kmc模块等等,必要时也可以直接修改这些模块的源代码。

其他

线上地址

对于一个典型的H5项目(例如汽车票项目h5-car),代码正式发布后,项目中的js和css文件会部署到Assests CDN服务器(域名为g.tbcdn.cn),项目中的html文件会部署到CDN服务器(域名为h5.m.taobao.com)。

技术参考资料

  • Grunt:这里
  • Yeoman:这里
  • Bower:这里
  • Bower与NPM的区别:这里。附加一句:NPM对于NodeJS就相当于Maven对于Java的意义,都是用于解决包依赖关系的。NPM的配置文件是package.json(相当于Maven中的pom.xml)。
  • KPM(Kissy组件的开发):这里这里