使用 font-face 定义字体

最近在看中文字体,顺便也研究了一下 CSS 中关于字体的内容。

在 CSS 中设置文字的字体,需要使用 font-family 属性,比如下面的代码指定了段落(p)中使用 Helvetia 字体,如果系统中没有 Helvetia,则退一步使用 Arial 字体,再没有的话,则使用系统默认的无衬线(sans-serif)字体。

如果你想加载一种新的字体,则需要使用 @font-face 指令。@font-face 用于定义一个新的 font-family,并指定它的源文件。如下:

上面这段代码定义了 Genericons 字体,它的源文件有 4 种可选,eot、woff、ttf、svg。其中 eot 是为了兼容 IE 6 而单独存在的,其它三种则广泛被现代的浏览器支持。实际上,如果不考虑 IE 6,单 woff 一种格式就足够了,没有必要提供其它三种。

定义完之后,就可以在 font-family 中使用 Genericons 了。

@font-face 的另一个作用是统一同一字体的不同名称,比如本站所用的 Noto Sans CJK SC,在 Adobe 那边的定义为 source-han-sans-simplified-c,如果不想每次都在 font-family 中写两个,可以把它们写进 @font-face,如下:

这样定义了之后,在 font-family 中只要写 Noto Sans CJK SC 就可以了,系统会自动在本地查找两种字体,找到任何一种,都可被用来渲染页面。

另外在 @font-face 中还可以指定字重(weight)和样式(style),具体可以参考 MDN 的相关介绍

投靠 Ubuntu

经过一番纠结之后,我还是把博客换到了 Ubuntu 之上。

之前提到过,从 AWS 转到 GCE 的时候,被迫选择了 RHEL 7(Redhat Enterprise Linux),因为只是 RHEL 7 是完全兼容 AmazonLinux 的。虽然 RHEL 需要另外付费,但为了平滑过渡,我还是以谨慎为先。

RHEL 有非常完善的商业支持,文档很齐全,有什么问题一查就可以明白。唯一的问题是,它的收费太高了,GCE 上面用一个月需要 50 刀以上,且不像主机一样用的时间长会打折,这样算下来,年费和一个 Radhat 的订阅差不多价格。但是我并不需要什么客户支持,技术问题都可以靠 Stackoverflow 搞定,这个订阅费用就白白浪费了。这也是我转向 Ubuntu 的主要原因。

还有一个原因是 HHVM。HHVM 是 Facebook 的 PHP 引擎实现,完全兼容 PHP 5.5 (及以上)。WordPress 从 3.9 开始,完整兼容 HHVM。

HHVM 的响应时间,据说是 PHP-FPM 的一半,也就是提升了一倍的吞吐量。原生 PHP 要做到这个效果,需要等 PHP 7 发布才行。看着各种发行版对于新软件的保守程度,不知道 PHP 7 要到什么时候才能成为主流。另一方面,Facebook 的研发能力肯定要比 Zend 来得强,等 PHP 7 发布了,HHVM 的性能肯定会更强。于是我就抛弃了原生 PHP,转投 HHVM。

当然,我也可以在 RHEL 上自己编译安装 HHVM。我试过,GCE 的机器编译了一个小时,我都快睡着了才编译完成,但安装(make install)的时候,告诉我某个文件不存在 -_-。我还是老老实实用官方的安装包吧,而 HHVM 官方只提供了 Debian 系列的安装包。

为什么没有选 Debian?Debian 保守到现在还只提供了 Apache 2.2,无语。

那也可以转投 Nginx 呀?我不高兴重写那一堆的 RewriteRule,并且 PageSpeed 在 Nginx 上也需要自己编译安装,不想再重蹈 HHVM 的覆辙。

由于 HHVM 和 PHP-FPM 的用法几乎一模一样,转换过程没出现任何问题,我做的唯一的工作就是重新设置了 Apache。花了几个小时,不过没什么难度,转换过程很顺利。

现在博客已经运行在 Ubuntu 14.04 + Apache 2.4 + HHVM 3.5 + MySQL 5.6 之上,欢迎测试,有问题请留言。

Javascript 中判断对象为空

最近写代码的时候碰到这个问题,需要检查一个对象(Object)是否为空,即不包含任何元素。Javascript 中的对象就是一个字典,其中包含了一系列的键值对(Key Value Pair)。检查一个对象是否为空,等价于检查对象中有没有键值对。写成代码,形如:

至于 isEmptyObject 的实现,jQuery 中有一个很有想法的方式,请看代码:

尽管 Javascript 没有原生提供 isEmpty() 方法,但它提供了迭代器,可以用来遍历所有的键值对。于是 jQuery 所做的事情,就是尝试遍历,如果有任何一个键值对,即说明对象非空,直接返回 false。从效率上来说,由于只读取了一个元素,顶多加上一些跳出循环的开销,实际性能不会比原生方法差太多。这是一个非常巧妙的实现。

注:有网友指出 ES5 中提供了 Object.getOwnPropertyNames 方法来获取所有的元素键。它的返回值是一个数组,当数组长度为零时,说明对象为空。

在 PHP 中生成 UUID

UUID 全称是 Universally unique identifier,它是一种识别符,使用任意的计算机都可以生成,不需要一个中央数据库进行管理,即可以保证几乎没有重复的几率。而 UUID 的值域之大,据说给世界上每一粒沙子分配一个 UUID,也不会有重复的。

最近在改 WordPress 的代码,需要用到 UUID。但是,PHP 中居然没有生成 UUID 的函数,只好自己写一个。

上述代码可以生成一个 UUID version 4。UUID 目前有 5 个版本,其中第四版是完全随机的,生成起来比较容易。而其中的 com_create_guid,是 Windows 中 PHP 的一个函数,它直接调用 COM 的 CreateGuid 函数来生成 UUID,但是在 Linux 没有对应的函数库,只好自己写了。为了方便在不同的平台上使用,就创建了一个同名的函数。其它的代码就是生成随机数了。

至于用法,就直接调用 com_create_guid() 即可。

又见 Markdown

在 Jetpack 中又看到了 Markdown 的设置,看来这东西还真的很流行,连千年不改编辑器的 WordPress 都要兼容它。不过我还是选择不使用 Markdown。

先说一下什么是 Markdown:它是一种标记语言,用于给纯文本加上一些格式,同时又不影响源广本的阅读。比如下面这段使用 Markdown 的广本(摘自 Swift 中文文档):

# 基础部分
-----------------

Swift 是一门进行 iOS 和 OS X 应用开发的新语言。然而,如果你有 C 或者 Objective-C 开发经验的话,你会发现 Swift 的很多内容都是你熟悉的。

## 常量和变量

常量和变量把一个名字(比如`maximumNumberOfLoginAttempts`或者`welcomeMessage`)和一个指定类型的值(比如数字`10`或者字符串`"Hello"`)关联起来。常量的值一旦设定就不能改变,而变量的值可以随意更改。

这段文本,即使它包含了各种奇怪的符号,但不影响阅读,大家都能从中得到它大概的意思。而 Markdown 牛 X 的一点是,这段文本可以被翻译成更漂亮的格式:

基础部分

Swift 是一门进行 iOS 和 OS X 应用开发的新语言。然而,如果你有 C 或者 Objective-C 开发经验的话,你会发现 Swift 的很多内容都是你熟悉的。

常量和变量

常量和变量把一个名字(比如maximumNumberOfLoginAttempts或者welcomeMessage)和一个指定类型的值(比如数字10或者字符串"Hello")关联起来。常量的值一旦设定就不能改变,而变量的值可以随意更改。

从中不难发现,在 Markdown中,“#”表示标题,“##”表示副标题,“`”表示代码格式等。不仅这些,Markdown 支持几乎所有的常见文档格式,包括超链接、图片等。对于不熟悉 HTML 但是想写博客的人来说,上手快,不需要深入了解 HTML 的知识就可以编写优美的文章。

但是,Markdown 上手方便,用久了会出现很多问题。比如上述的“#”表示标题,换句话说,只要某一行的第一个字符是“#”,这一行一定会被翻译成标题,那如果一定要显示一个“#”怎么办?Google 了之后你可能会找到,用“\”字符可以转义,也就是说“\#”会显示出来“#”。那好,如果要显示“\#”怎么办?

你也许会说,上面只是一个特例,在真正的写作过程中,很少碰到。那么我们再看一个例子:Markdown 中图片的标记是“![](<图片地址>)”,看上去很简单,于是你就在文章中插入了一张图片,预览,Ooops,图片太大了。你只想显示 200*200 的图片,但是原图有 400*400,这该怎么办?于是你又 Google 了一下,这下可好,有些贴子说,你可以在括号里加上“ =200x200”,有些贴子说,你可以说 CSS:{width=200px height=200px},但这些都不是标准的 Markdown,你所使用 Markdown 引擎可能还不支持它们。好吧,还是要学学 HTML……等等,什么是“转义字符”和“CSS”?

最后,虽然不重要但值得一提的是,中英文符号是有差别的,比如“#”和“#”是不一样的,而 Markdown 只识别英文符号。这对于中文写作者来说非常不友好。说它不重要是因为,HTML 也存在同样的问题;值得一提是因为 HTML 中如果写错了,浏览器好歹会有一个警告,而 Markdown 不会。

在Javascript中使用String.startsWith和endsWith

在操作字符串(String)类型的时候,startsWith(anotherString)和endsWith(anotherString)是非常好用的方法。其中startsWith判断当前字符串是否以anotherString作为开头,而endsWith则是判断是否作为结尾。举例:

但不幸的是,Javascript中没有自带这两个方法,需要的话只能自己写。当然写起来也不难就是了。

String.slice()和String.substring()类似,都是获得一段子串,但有评测说slice的效率更高。这里不使用indexOf()的原因是,indexOf会扫描整个字符串,如果字符串很长,indexOf的效率就会很差。

和startsWith不一样,endsWith中可以使用indexOf。原因是它只扫描了最后的一段字符串,而比起slice的优势是它不用复制字符串,直接扫描即可,所以效率更高。

在网页中嵌入图片

在网页中加入一张图片很简单,只需要插入一个<img>标签就可以了。对于大多数图片来说,使用<img>标签很方便,但它有两个小问题:

  • 需要上传一张图片,可能需要额外的图床,管理起来相对麻烦;
  • 对于网速比较慢的用户来说,需要多开一个连接下载图片,有时候会下载不到,影响用户体验。

所以,一些小图片,与其放在图床上,还不如直接嵌在网页里。图片本身就小(比如小于32k),下载速度很快,而且省去了建立连接的时间,方便快捷。唯一不好的地方是无法设置图片缓存,因此不能对重复出现的图片做这种优化。

怎么把图片直接嵌在网页里?只需要使用Data URI标记就可以了,它形如<img src="data:image/png;base64,xxxx"/>。其中xxx是图片的base64编码,image/png表示图片是png格式,你也可以使用其它格式。示例如下,图片是本页地址的二维码,查看源代码就可以看到它的base64形式。

QR Code

这种方式在主流的浏览器(IE、Chrome、Firefox)中都支持,放心使用。