Hello World

go语言入门[1]—-发邮件

这里说的发邮件,用的是“net/smtp”,不多说,看代码

package main
 
import (
	"net/smtp"
	"fmt"
	"strings"
)
 
//对发送接口的简单封装
func SendMail(to, subject, body, mailType string) error{
	//发件服务器相关配置,这里以gmail为例
	u := "xxxxx@gmail.com"
	p := "xxxx"
	host := "smtp.gmail.com"
	port := "25" 
	//Auth
	auth := smtp.PlainAuth("", u, p, host)
	var content_type string
	if mailType == "html" {
		content_type = "Content-Type: text/html; charset=UTF-8"
	}else{
		content_type = "Content-Type: text/plain; charset=UTF-8"
	}
	msg := []byte("To:" + to + "\r\nForm: 老大<" + u + ">\r\nSubject: " 
		+ subject + "\r\n" + content_type + "\r\n\r\n" + body)
	send_to := strings.Split(to, ";")
	//发信
	err := smtp.SendMail((host + ":" + port), auth, u, send_to, msg)
	return err
}
 
func main() {
	to := "xxxx@163.com;xxxx@gmail.com"
	subject := "test-go-smtpxxx"
	body := "<html><body><hr><h1>test-smtpxxx</h1><hr></body></html>"
 
	fmt.Println("send email")
	err :=  SendMail(to, subject, body, "html")
	if err != nil {
		fmt.Println("mail error: %v", err)
	}else{
		fmt.Println("mail ok!")
	}
}
Hello World 业界杂谈

nodejs-express初体验

上次文章提到,正在用nodejs做一个小项目,现在总算是做完了

学习/搞着玩是一回事,虽然两年前就开始接触nodejs,做实际要用到项目里是另一回事,经过两周的折腾,我这里不想夸,也不想踩,只想说一下我真实的感受,给准备用nodejs的朋友一点参考

整体来讲,nodejs+express的开发模式,感觉还可以,既不像前端大牛们说的一样好,也不像另一些人说的那样一无是处,下面针对几个关键点分别说一下

1. express

早就听人说过,express是个“优秀”的web框架,我这次的使用体验,却让我没有这种感觉。大概是用惯了cakephp那种规约编程/傻瓜化的web框架的缘故,我觉得一个框架最应该做的,就是让使用者不要过多感觉到框架的存在,以最简单的方式获取请求参数/调取model/lib/以及向view层传递显示,可以让人将所有的精力都投入到业务逻辑中~~要不我还用你框架干嘛?

对express,最别扭的一点,就是它的routes配置~~居然每一个请求的url都要去做配置,让我一下想到了java/spring mvc的那个xml~~懒婆娘的裹脚布也不过如此

另一个sb的地方,是它的logger~~本来不想重写日志类的,特别是access日志,服务器能自动记录最好,找了好久,才找到如何设置express 日志的格式,可是设置好以后,发现日志时间记录的不对,格式也不好看,一查原码才发现,logger里用的是date.toUTCString~~UTC啊,尼玛我看日志的时候,还得想着和实际时间差8小时。。。

最关键的一点是,express官方的api极其“简约”,很多东西不得不去翻框架原码才能发现一些“隐藏”的功能

最后,作为一个web框架,居然没有filter,虽然app.use可以部分实现filter的功能,但用起来还是感觉很不爽

2. npm

npm真TMD乱,很多好名字都被占了,占着茅坑不拉屎

比如thrift,装上以后发现根本不能用,版本太老,仔细一看,居然2年没维护了

再比如email,居然没看见在哪儿设置邮件服务器~~太TM扯淡了

3. 模板引擎

express默认的jade就不提了,稍微复杂点的页面,就会搞得一团糟

我用的是ejs,不好不坏,只能说“可用”。我比较喜欢view层代码,后端程序和前端html/js可以一目了然,所以我使用<%作为格式符,然后用jsp编辑器打开ejs文件~~哈哈,一目了然

ejs比较不好用的一点是对于变量的判断过于严格:如果试图输出没往view层传递的变量,页面居然会直接抛500错误~~太较真了吧,你当空串处理不久行了吗?

4. nodejs

不好意思,上面说了3点,大部分都是在踩,现在该说点好的了

js&node,本身还是一款很不错的组合,虽然异步编程需要一些时间来适应,但却给高并发和快速影响带了了天生支持;另外,js语法简单自由,也可以带来很高的开发效率

对于所谓的“前后端共用代码”,我倒是觉得不太有必要~~毕竟,前后端执行环境差异巨大,写这种“公用代码”的维护成本,还不如直接copy一份给前端用

最后,给自己留一个问题:下次你还会选nodejs吗?

以前写过一个简单的前端mvc框架,jLeaf,基本思路是模仿cake和spring来做的,node出来后,曾经想顺势再写一个后端框架,名字就叫jRoot,可惜因为工作忙,也因为人懒,没能实际做出来,看到express这么难用,真想现在就把jRoot做出来,可惜现在更忙了~~~希望后面能有时间把它搞出来,也希望node能有其它更好用的web框架出来

 

日志

新东西

接手一个小项目,本来,想用go语言来做的,于是前半周便开始临阵磨枪的疯狂学习go语言
go真的是个好玩的东西,语法简单,又支持许多高级特性,package管理超方便,集动态语言的灵活、快速开发,与静态语言的高效于一身
语言编码格式神马的常见问题都好解决,eclipse就搞定了
然而,windows安装go环境却颇费了一番周折,开始是8g,后来是go run,最后也没找到合适的调试web程序的方式,只能在linux的测试服务器上做部署调试
虽然是小项目,但仍然要包含各种元素,需要一个一个搞定才能正式做项目
web框架,go有beego和webgo,都是很好用的MVC框架
mysql神马的也都不是问题
最后卡在了thrift上
thrift本身是支持go的,可以生成go的client,但是却找不到完整的例子,thrift文档里的example里没有go,按生成的client里的小例子做,根本走不通。gifhub里的两个go-thrift插件也都没走通。最关键的是,不管是百度还是google,相关的资料几乎都没有。折腾了一天,到周三下午的时候,眼看项目时间周期就要受此影响,最后不得不暂时放弃

放弃了,转向另一个早就想跃跃欲试的东西:nodejs
第一次用nodejs/express做项目也并不顺畅,选什么模板/怎么连mysql/thrift,以及怎么做权限过滤,还好,都解决了,但是最后险些卡在了图片验证码上
搜到的的资料,nodejs的验证码大部分都是基于node-canvas做的。canvas是nodejs的一个图形库,大概类似php所用的GD库。canvas和操作系统结合比较紧密,windows安装再次遇到了问题。要装npm-gyp来编译c++,进而需要安装Visual C++,还要装Python,可是最后“npm install canvas”的时候,还是TM不停的失败
还好,改了一下思路,找到了另外一个可以生成验证码的nodejs小插件:node-ccap,实现了需要的效果

已经很久没真正尝试过后端的新东西了~~~近三年以来,不再用java,也不用很久之前就开始研究的nodejs,而一直使用php,甚至几乎只使用cakephp~~~~鄙视
直到近期,发现cakephp一个很SB,却很关键,会造成整个系统无法工作的bug,才突然意识到,应该学点后端的新东西了

开始的时候没选nodejs,是因为个人其实并不看好nodejs在后端的作为。听过很多nodejs的经验介绍和分享,但几乎无一例外的,使用nodejs做项目的公司,开始时都是前端开发资源过剩,于是让前端团队去承担后端工作。
对于传统的后端开发,nodejs的缺点明显:单进程,与异步
多核时代的今天,nodejs的默认启动模式居然还不支持多核,让人很纳闷
大部分人都不习惯nodejs的异步模式,这也是其使用的一个巨大障碍
另外,基于js的后端程序,其效率可能只能与php相比,与java、go等静态编译型语言相比,先天不足

日志

千里之外

    今天,因为一件小事打电话找二姐,却听到了很不愿意听的消息:老家房子终于要被拆了!
    从两年多以前开始,因为地底下采煤的关系,老家附近几个村就就被镇政府要求拆迁,让村民们搬到几公里外的安置房里去。不过,扯淡的是,安置房那时才刚刚打了地基,ZF的人想让村民们先自己租房子住,再加上补偿款、安置房面积等种种问题,结果可想而知,村民们坚决抵制,总算顶住了两年。可惜,胳膊拗不过大腿,我们的ZF在对付老百姓时总是那么睿智,虽然安置房的竣工日期还遥遥无期,在ZF的威逼利诱和分化瓦解下,村民们还是被迫搬迁
    今天和二姐打电话时,二姐正在帮老爸搬家装车,明天,我家的房子就要被拆了。。。
    刚听到这个消息,因为知道是迟早的事情,所以心里并没有怎么样特别感觉,可是放下电话不久,想起老家的房子,和在那里过的二十几年的日子,我哭了

    我是一个很恋旧的人,自己用过一段时间的东西,只要还有地方放,就绝不会扔掉或者卖掉
    记得还是很小的时候(那应该是我记忆中最早的一块东西), 大概三岁时吧 ~~
    那时,家里的正房还是土坯房子,三间正房旁边还有一间小土房,是做厨房用的。有一天,爸妈找来村里盖房子的人,说要在原来厨房的位置盖两间砖房做配房,当然,要先拆掉那间小土房。我听说以后,估计去找爸妈说不要拆掉那间房子,结果可想而知,这种事情谁会理会三岁孩子的意见。然后,当天晚上,我便坐在小土房门口哭、怄气,直到很晚睡着了才被抱回屋里

    现在要被拆的房子的主体,是在我上小学三年级的时候建起来的,算起来,应该是1991年
    还记得当时建这房子时的很多细节:
    拆旧房子,拆掉前后墙后剩下的山墙,是一群人用绳子拉倒的,每面墙倒下时,都会“轰”的一声巨响~~~
    挖地基的时候,在东面墙的下面,曾挖出一个圆形的土质很松的坑,爸爸回忆说那里曾经是一口井
    房子是秋天盖的,天已经比较凉的,盖房的时候,爸妈睡在过堂屋里,拿一张褓(一种用高粱杆做的席子)挡在门口挡风
    房子刚盖完,粉刷墙壁前的那个晚上,老爸熬夜把所有的电线不好,这样,等粉刷的时候,就可以把电线盖在刷墙的石灰下面了,墙的表面只有开关,不会再有电线
    房子盖好后,一群人合力将一块楼板斜着搭在房顶和地面之间,后来,老爸在这条楼板上用砖头垒出了一级一级的台阶,又将水管焊上去作为栏杆
    。。。。

    房子是平顶的,没事的时候,我经常爬到房顶上玩
    夏天的时候,很多邻居都会来我家房顶乘凉,大家把席子铺在刚刚被太阳晒得暖暖的地面上,舒服极了~~~吃饱喝足,拿把蒲扇赶着蚊子,抬头看着星星,听着大叔大婶们聊着天~~~~
    秋天的时候,房顶上会放些稻草,留着来年绑稻苗用。有一年春节,我在门口放鞭,将一个点着的鞭扔到了房顶的稻草里,没过多久,便听到头顶噼里啪啦的声音,抬头一看~~妈呀,稻草被引燃了。而稻草的旁边,有为很多家供电的电线~~于是,附近的邻居都被调动起来,帮忙灭火,还好稻草不多,没有引起什么大得事故~~~我是村里出了名的“乖孩子”,这可能是我做过的唯一的“坏事”
    我家靠着村里的大马路,每天早晨天一亮就会有各种叫卖声,最早的是换馒头的,巨有特色的吆喝,“换馒头不~~”;然后卖豆腐的、换锅贴的、补鞋的、收头发辫子的、卖香油的、卖各种蔬菜的;夏天的时候还有换西瓜的、换苹果的、换桃子的~~~虽然很吵,却也很方便~~从来不用担心错过卖各种东西的
    经常听到窗子外面传来邻居们的高谈阔论,开始可能是两个人,然后是三个、四个,越聚越多,然后突然某大婶说一声“哎呦,天不早了,我得回家烧汤去”“慌慌嘛,还早那”“我也得走了,二妞子快放学了”…..然后各自散去
    我家的院子里曾经种过一棵葡萄树,葡萄藤爬满大半个院子,整个暑假,我每天都会去“巡视”N次,找遍每一条藤的每一串,不放过每一颗哪怕只是微微变红的葡萄~~O(∩_∩)O哈哈~
    院子中间有个不大的花坛,开始的时候种着月季花,每到夏天都能开出绚丽的红花;过了几年,貌似是某种病,月季死掉了,便又种上了无花果树。从此,除了葡萄,又有了无花果~~嘿嘿
    靠配房门的小花坛里,刚开始种了一棵石榴树,可是,可能是品种不好,也可能是葡萄藤挡了它的光线,这颗石榴树一直没长好,每年结不了几颗石榴,还又小又酸。后来,换成了一棵苹果树~~没长起来~~再后来,记得曾经种过一棵香椿树,也不太成功~~所以最后那个小花坛干脆不种东西了
    院子里种的最成功的一棵树是院东边中的一棵柿子树,妈妈种的,说是等我们有了孩子,可以让孩子们吃柿子。可惜柿子树还没结出柿子,妈妈就去世了。后来,柿子树长的几乎覆盖了东侧大半个院子,每年秋天都能结出上千个大柿子
    从初中开始,和村里的几个同年级的哥们关系越来越好,每天上学,大家总会到我家集合,然后一起去学校,周末,大家也会过来一起玩,下下象棋,玩玩游戏机,或者到附近的打谷场踢踢球。而我们家,就是大家的根据地,无论去玩什么,大家总会到我家来集合

    从高中开始,便开始离开了家,高一高二每周回家一天;到了高三是每月一次;到了大学四每年两次,到了现在~~一年也不见得一次~~~
    10年春节,回老家结婚,是毕业会在家里待的最久的一次,也不过十天而已

    虽然回家的时间越来越短,可是家毕竟是家,每当有什么好事情,总是想回家和爸爸妈妈大姐二姐分享;每当有了什么好玩的东西,总是想带回家去玩;每当在外面受了委屈,仍然下意识的希望能回家,回到自己的小屋里呆上一会

    然而,现在不同了,我的小屋、我的小院、我的小村~~都即将被连根拔起,被从这个地球上抹去。。。。。。而我,不仅无能为力,甚至没能再回去看上一眼

    ————谨以此文,先给即将消失的老家

日志

四月的最后一天

  • 今天是四月的最后一天,过了今晚,2013便已经过了三分之一~~~好快

    去年年底换了工作,在经过两个月的调整期后,工作量开始逐渐上来了,特别是四月份的前两周,简直有种疲于奔命的感觉。还好,现在已经逐步适应了新公司的节奏

    三月中旬,终于把房子签了,一下变成了一贫如洗且负债累累的房奴。但却并没有给我带来压力山大的感觉~~~~或许正应了这个词:死猪不怕开水烫。。。哈哈

    ╮(╯▽╰)╭,不多想了,睡觉~~~~

  • Hello World 倒塌集

    不靠谱的东西

    这周碰到了两个不靠谱的东西,一个是微信自动回复里的图片,另一个是魅族手机

    微信的公众平台API却是非常强大,可以依托它做出各种精彩的应用,然而,这周一却碰到了一个美中不足的问题不,这个问题不大不小却让人很不爽:自动回复里的图片,不管你给什么尺寸,在不同的设备里,总是会或左右,或上下的被截去一段,比如下图公众号“IT程序猿”发的内容:

    可以看到,中间的图片,左侧二维码只显示了一般,右侧文字也没遮住了一部分

    我测试了各种尺寸的图片,发现都不可以,最后的解决方案是:用大约1:2的图片,但是图片的上下、左右都不放重要内容,这样就随它截去了~~

    这周碰上的另一个东西是魅族手机的系统浏览器。

    魅族版的android,界面确实很漂亮,甚至可以说很华丽,但它的自带浏览器,确实也很屎。

    昨天测试发现一个bug,在这个浏览器内,页面里里面有几个输入框,当输入时,整个页面都会随着上下不停的抖动。貌似,是因为有输入动作时,浏览器会试图将输入框放到页面的顶端,但每次定位都不成功,下次又试图再次定位,于是就出现了这种怪异的现象~~解决方案是。。。目前还没有

     

    幻界杂谈 幻视幻听 日志

    基地

    用了近三个月时间,终于“读完”了阿西莫夫的基地系列~~~

    据说上图是读客版基地的封面,里面的四个“经典”人物都深受基地的影响,可是我买到的读客版却没有这个封面

    已经很久没有读过长篇了,平时上班不读书,晚上、周末不读书,这次重读基地系列,完全是利用每天坐地铁的时间。每天大约一个小时,能读三、四十页

    前面说“读完”,其实只读了5本,中间“略过”4、5两部讲谢顿生平的“基地前传”,,本来想读完第七部在读前面两部,可是后来就没有兴趣了。。。太长了

    大学时读过基地的第1、2部,印象深刻,所以今年年初才会心血来潮买了七部曲全集来看~~但是,说实话,后面几部真的有些失望

    (以下有剧透。渗入)

    前三部据说是作者年轻时写的,真的是“史诗”级的作品,每一步包含若干个故事,每一个故事结构紧凑,人物鲜明,所有故事一起构成了“第一基地”前300年的发展历程,同时也逐渐揭开了“第二基地”的神秘面纱。

    后面几部,则是作者年长以后写的,或许是所谓“写作手法”的成熟,故事变得冗长起来,后面两部的总篇幅和前三步不相上下,讲的却只是一个故事,人物就只有可数的几个。而且,情节也上否定了前三部奉为神明的“谢顿计划”,转向了作者的另一个套大作:机器人系列。特别是最后一部“基地与地球”,四百多页的篇幅,有三分一都是在讨论“盖亚星系”的种种优点,整篇都是在“寻找地球”,可是最后找到了地球,给出的选择“盖亚星系”的理由,在我看来却是严重的牵强附会,更加不明白为什么会选择“盖亚星系”作为银河的未来发展方向

    不过,整体来讲,基地系列还是很棒的一套书,有时间的朋友可以拿来读读

    Hello World 业界杂谈 点点滴滴

    php ci快速入门

    久闻php ci的大名,一直没有机会使用,上周做个小项目,用到了这个框架,整体感觉很不错,这里跟大家分享一下ci的快速入门

    ci文档入口:http://codeigniter.org.cn/user_guide/toc.html(中文!)

    ci,即codeigniter,我用的版本是当前的最新版本2.1.3

    使用ci,只要将apache或者nginx的发布目录指到codeigniter的顶级目录下就可以

    下面,就按MVC的顺序来所说ci的使用

    url

    比如要访问/news/list的action,默认情况下,url需要这么来写:xxx.xxx.xxx/index.php/news/list~~多个index.php,很别扭

    如果要去掉这个index.php,需要加上“.htaccess”来实现urlRewrite:

    1
    2
    3
    
    RewriteEngine on
    RewriteCond $1 !^(index\.php|images|robots\.txt)
    RewriteRule ^(.*)$ /index.php/$1 [L]

    C

    ci的controller位于application/controllers目录下,文件名和ation方法名需要遵循规约变成的规则

    不多说了,还是直接写代码吧:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    class News extends CI_Controller{
    	function __construct(){
    		parent::__construct();
    	}
    	// http://localhost/news/lists,如果要使用其他的url,需要到“application/config/routes.php”去配置路由
    	public function lists($keyWords){
    		//使用model,model()方法的第一个参数“news”对应application/models/news.php
    		//第二个参数“News”对应下面如何引用这个model:$this->News,如果不设置这个参数,这是$this->news,及model的名字
    		$this->load->model('news', 'News');
    		$data['list1'] = $this->News->list_all();
    		//使用library核心类
    		$this->load->library('news_manager');
    		$data['list2'] = $this->news_manager->search_news($keyWords);
    		//使用view,向浏览器输出内容
    		$this->load->view('header');
    		$this->load->view('news/list', $data);
    		$this->load->view('footer');
    	}
    	//
    	public function view_news($id){
    		$this->load->view('view_news', array(
    			'title' => news->title,
    			'content' => $news->content
    		));
    	}
    }

    如果要加载非默认数据源,需要到config/database.php里配置不同的数据源,比如现在除了default,又添加了一个叫做abc的数据源,我们如何调用哪个它哪?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    //abc
    $abc = $this->load->database('abc', true);
    $this->load->model('abc_table1');
    $thisi->abc_table1->db = $abc;
    //default
    $defaultdb = $this->load->database('default', true);
    $this->load->model('news');
    $this->news->db = $defaultdb;
    //即通过“$this->load->database”建立数据源,然后通过$thisi->model->db=xxx为当前某个model的引用设置数据源

    另一个要说的功能是:可以将controller文件放在子文件夹中,比如“application/controllers/shop/products.php”,调用它就需要“/index.php/shop/products/xxx”

    M

    上面的代码已经用到了模型的调用,这里所说模型的常用方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    class news extends CI_Model{
    	function __construct(){
    		parent::__construct();
    	}
     
    	function cretae($title, $content){
    		$data = array(
    			'title' => $title,
    			'content' => $content,
    			'create_time' => new time()
    		);
    		//INSERT INTO news (title, content, create_time) VALUES ('xxxx', 'xxxx', 'xxxx')
    		$this->db->insert('news', $data); 
    	}
    }

    1
    2
    3
    4
    5
    
    //DELETE FROM mytable WHERE id = $id
    $this->db->delete('news', array('id' => $id)); 
    //等效
    $this->db->where('id', $id);
    $this->db->delete('news');

    1
    2
    3
    4
    5
    6
    7
    
    $data = array(
    	'title' => $title,
    	'content' => $content,
    );
    $this->db->where('id', $id);
    //UPDATE news SET title = xxxx, content = xxx where id = $id
    $this->db->update('news', $data);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    //SELECT * FROM news
    $query = $this->db->get('news');
    //select * from news where id = $id limit $offset, $limit
    $query = $this->db->get_where('news', array('id' => $id), $limit, $offset);
    //直接取结果集
    $list = $query->result();
    //取结果集的数量
    $count = $query->num_rows();
    //此外,ci的查询还有丰富的方法,支持各种查询,诸如:where/or_where/where_in/or_where_in/like等等

    打印sql

    1
    
    echo $this->db->last_query();

    V

    ci的view位于application/views/目录下,比如view_news.php,可以直接使用php代码书写

    1
    2
    3
    4
    5
    6
    7
    8
    
    <html>
    <head>
    	<title><?php echo $title;?></title>
    </head>
    <body>
    	<h1><?php echo $content;?></h1>
    </body>
    </html>

    上面的title、content参数,可以通过下面的方式在controller中传递过来:

    1
    2
    3
    4
    
    $this->load->view('view_news', array(
    	'title' => $news->title,
    	'content' => $news->content
    ));

    ———
    参考:http://codeigniter.org.cn/user_guide/toc.html


    ———
    蒋评:
    先不论框架的易用性、性能等因素,相对于cakephp和thinkphp,ci最大的又是就是它的中文资料丰富,有完整的中文文档,甚至官网还提供中文视频教程:http://codeigniter.org.cn/tutorials,这些都大大降低了新手的入门难度[赞]

    Hello World 幻界杂谈 点点滴滴

    jQuery()方法的第二个参数

    jquery框架的神奇之处在于,即便是对于我这种以“精通jquery”自居的人(嘿嘿),每次在看文档时,仍然能有新的发现,比如今天,就发现$(xxx)方法,其实还可以有第二个参数,并且随着第一个参数的不同,第二个参数还有不同的含义:

    1.  $(selector, [context])

    这种用法,相当于 $(context).find(selector) 或者 context.find(selector)

    2. jQuery(html, [ownerDocument])

    文档对ownerDocument的解释是:“创建DOM元素所在的文档

    也就是说,如果你要编写挎document的脚本,比如iframe或者用window.open开一个新窗口,可能会用得着它

    3. jQuery(html, props)

    这个比较简单,直接把文档里的例子贴出来了:

    $("<input>", {
    type: "text",
    val: "Test",
    focusin: function() {
    $(this).addClass("active");
    },
    focusout: function() {
    $(this).removeClass("active");
    }
    }).appendTo("form")

    也就是说,props内的属性会像.attr()方法一样,被设置到新创建的标签内

    注:IE总不能通过.attr()设置input的type属性
    ----------
    参考:http://www.w3school.com.cn/jquery/core_jquery.asp#syntax1

    业界杂谈 他山石

    关于WebKit的几个问题

    1. WebKit是什么?

    WebKit是一个开源的Web浏览器引擎。
    WebKit的HTML解析器和JavaScript解析器代码分别源自KDE的KHTML和KJS代码库。

    2. 谁在使用WebKit?

    “MacOS X系统的Safari、Dashboard、Mail和很多其他OS X程序”
    这就是在说,WebKit是Safari背后的浏览器引擎。还需要补充的是,Apple在Safari里面使用了自己的Nitro JavaScript引擎(只用WebKit来渲染HTML)。

    Google官方说明:Chromium使用WebKit做为渲染引擎。与其打造Chromium特有的实现方式,我们更希望去尽可能多的去为使用WebKit核心的浏览器做贡献。

    这是说Chrome也在使用Nitro JS引擎?不,Chrome有他自己的V8 JavaScript引擎。简单的说,Chrome也使用WebKit,但是它也实现了自己的JavaScript处理方式。V8同时还是驱动Node.js的JavaScript引擎。

    Opera会使用Chromium实现的WebKit,也会使用V8引擎。这就是说虽然Opera在宣称自己使用WebKit,但事实上它使用WebKit和Safari与其他浏览器使用的WebKit并不完全一样。如果你想客观了解现状,这是必须清楚的概念。

    3. 现在WebKit究竟有多少分支?

    所以我们知道现在WebKit正在驱动,或者将会驱动3个主流浏览器。但是WebKit还有多少其他类型的实现?
    确实还有很多很多WebKit的变种,特别是在移动领域。他们都是WebKit的分支。

    4. 这些WebKit的分支有多少差别?

    有一种假设:因为这些浏览器都在使用WebKit,所以他们也会以同样的方式去支持相同的特性。
    对于很多基本的特性来说,确实是这样。但是对于很多小众特性,就未必如此了。

    举例来说,当Chrome开始支持游戏手柄API的时候,Safari不但还没开始支持,而且以后也不太可能支持。另一个例子是WebGL。做为在Chrome已经支持了很久的特性之一,Safari却才刚刚看到了曙光(而且还是在开发者选项里)。当然,这些还都是比较出名的例子。还有很多试验性的例子潜伏在大众的视野之下。

    甚至很多基础的、日常的功能,在不同的代码分支下都有所不同。PPK完整的总结了这些WebKit的差异。

    5. WebKit的逐步普及,对web开发有什么影响?

    如果一个浏览器迁移到了WebKit,那是不是意味着(在编写代码的时候)可以少测试一个浏览器了?
    不。每个浏览器都有它自己的怪异模式、性能差异、设计,和功能。所以每个浏览器都要测试。

    当一个功能加入到WebKit的时候,是不是意味着在其他浏览器里就可以使用这功能了?
    当然不是。比如游戏手柄API的例子。Paul Irish强调了这样一个事实:WebKit浏览器们可以挑选究竟把哪些API放入他们的版本。比如Chrome选择支持游戏手柄API。很多API在WebKit的层面就已经被实现了,但是WebKit项目书允许关闭这些功能。(编者注:Paul Irish是Google Chrome的员工,他曾在jQuery团队工作两年。)

    如果所有的浏览器都使用相同的引擎,这对程序员来说意味着什么?
    随着时间的流逝,他们会意识到尽管同是WebKit,也会有很多不同的东西。

    6. 新特性如何加入到WebKit中,谁又来负责审核?

    现在有许多公司正在为WebKit项目贡献自己的力量。

    WebKit项目提交和审查页面提到只能有老的代码提交员和审核员才能提名新的新的代码提交员与审核员。这比较合理。然而,无论WebKit项目决定让谁参与进来,最终都还是要让Apple来做审核:
    当有人被WebKit代码提交员成功提名后,Apple会处理发送代码提交员协议,在签署协议之后,Apple会继续开通SVN账户。

    对于这一点并没有什么隐秘的动机,但这确实在告诉大家,WebKit和很多开源项目一样,并不是真正分散和民主的。权利是且必须是集中的——只有这样才能保证能做出决定,并且把事情做成。

    7. 如何评价WebKit?

    允许我们强调一下,WebKit是好的。它有开放的流程和强大的贡献者。我们只是想澄清一个当下被广泛接受的错误概念——一个WebKit等于所有WebKit,还有——如果所有浏览器都选择WebKit,那么对开发者来说,工作会变得更轻松。
    我的意思是说,与众多独立的浏览器引擎会为市场带来多样性一样,WebKit在这一点来说,同样会表现的很棒。

    —————

    转自:http://www.infoq.com/cn/news/2013/02/webkit-history-and-now