在最近的印象中,最受期待的浏览器功能之一就是data URI了。最近已经有不少关于data URI的文章:我同事Stoyan Stefanov已经写了两篇关于data URI的文章,我旧同事Hedger Wang也写了一篇关于如何在IE使用data URI的文章。但出乎意料的是,对于data URI的误解和困惑依然屡见不鲜。它是什么?它是怎么工作的?为什么你会想去使用它?

是URI,不是URL

URL是uniform resource locator的缩写,是一个特定资源的协议(用什么方式去获取数据)和地址的组合。每一个公开可访问的资源,例如图片,JS文件,HTML文件或者样式 表文件,都有一个URL告诉浏览器从哪里下载它们。浏览器会根据这个URL建立一个链接,并开始下载或执行这个文件。

URL其实也是个URI,URI是uniform resource identifier的缩写。URI指定了一个协议用来接收信息,包括一些关于资源的额外的信息。那些额外的信息可能是一个地址也可能不是(如果是的话, 那么URI就是URL了),但是它总是跟一个特定的协议和有关联。因此,既然不包含地址信息,data URI也就不是URL了。

Data URI的格式

data URI的格式很简单,在RFC 2397里有清楚的说明(很短,你可以把它全部看完)。基本的格式如下:

data:[][;charset=][;base64],

在这个格式中,data:URI的协议,表明这是一个data URI。第二部分,MIME type,表明了要呈现的数据的类型。拿PNG图片举个例子,它的MIME type是image/png。如果没有指定,MIME type将会默认为text/plain。charset在大多数情况下可以无视,对于图片来说它根本没用。下一部分指明了使用的编码。跟流行观念相反, 你不一定要用base 64编码。如果内容不是用base 64进行编码,那么这些数据就会使用标准的URL编码(对URL安全的ASCII字符将会保留原样显示,其他会显示成%xx格式的十六进制编码)进行编 码。编码后的数据可能会包含一些没用空格,

Base 64编码

Base 64编 码是一个编码规则,通过它数据被转化成二进制码,然后组合成一个base 64符号的序列。Base 64符号包括大写和小写的字母A到Z,数字,符号+和/。=号是用来填充用的(可以查看Wikipedia上的文章获取更多的信息)。你真正需要知道的是 base 64编码会使编码过的数据变得更小。

下面的例子是一张GIF图片用base 64进行编码后的data URI(来源):

data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub//ge 8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1h LnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguWw6aFjsVMkkIr7g 77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7

同一张图片如果不用base 64编码的话将会如下显示:

data:image/gif,GIF89a%22%00%1B%00%F7%00%00lll%D6%D6%D6%FF%EB%85 %FF%E0%7B%FF%F7%91%FF%D4o%DF%DF%DF%F6%F6%F6%87%87%87%FE %CBf%FF%F4%8E%E6%B3NKKK%C5%92-%FF%FF%99%FF%FF%FF%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%2C%00%00 %00%00%22%00%1B%00%00%08%A9%00%1F%08%1CH%B0%A0%C1%83%08 %13*%5C%C8%B0%A1%C3%87%10%23J%9CH%91%60%83%8B%0D%0C%1C %A8h%B0%81%C5%00%1B9%0A%F4%E8%A0%A4%83%07%181j%9C%D8%80 %80%82%97%2F%0B6%40%60%80%A5%00%01)s%AA%94%D8%60%80G%84 %02P%22%E0Y%A0%81%C9%A3%25%138h%00%80g%02%A3%04%A2J%8D %BA%60i%D3%88%0D%9E%3A%B8%C9%95kU%A6N%8D%0E%18Kv%EC%D7 %AB%10%B3%1A-%C0%B6-%5B%A3%60%23%1A%D0I%97%C1%D0%88%07 %02%20%00%C0%B7%AF_%00%08%02L%3C%60%20%80%E1%C3%88%03 %AC%14%C9%B8%B1%E3%C7%90%23K%9EL0%20%00%3B

就大小来说,用base 64编码的图片完胜,它明显小多了。

注意:Base 64编码事实上会使图像变大。然而,如果你使用了HTTP压缩,那么你并不会察觉到有什么差异,因为base 64编码的数据的压缩性极好。如果因为某些原因不能使用HTTP压缩的话,那么你可能会想知道你发送的数据究竟有多大,然后权衡下是否值得这么做。

不仅仅用于图像

尽管大部分人在谈论data URI作为在HTML或者CSS文件里嵌入图片的方法,但这里并没有指定是图片。你可以编码然后嵌入任何类型的文件,甚至是HTML本身。Ian Hickson,HTML 5名人(或者恶人,视乎你怎么看)提供了一个工具让你体验下data URI。默认的例子是使用或者不用base 64编码把一个HTML文件转变成data URI。体验一下这个data URI产生器可以帮助你具体化一下核心的概念。

注意:IE8对data URI有安全限制,使得data URI对于非图片的数据的用处大打折扣。

性能影响

data URI最有趣的地方是它可以让你把文件嵌入到其他文件中。大多数的文章都把焦点放在把data URI嵌入到CSS文件里改善性能上。实际上,大量的研究表明,HTTP请求是影响网页性能最主要的因素之一,减少请求的数量可以改善页面的性能。实际上,“最小化HTTP请求”是Yahoo! Exceptional Performance Best Practices的第一准则,它特别提到了data URI:

内联图像使用了data URI把图像数据嵌入到页面中,会增加HTML文档的大小。把内联图像在(已缓存的)样式表里组合起来可以减少HTTP请求和避免页面大小的增加。内联图像还没有得到所有主流浏览器的支持。

这对使用data URI来说是个很好的建议:把它们用在缓存频率最高的地方。通过HTTP下载的普通图片会根据它们的header和浏览器设置进行缓存,这样它们就不用每 次请求都被重新下载。Data URI会被当作装载它的那个文件的一部分,所以它是所嵌入的HTML或者CSS文件的一部分。这意味着data URI没有单独的缓存控制策略。嵌入data URI会使你的文件变大,如果文件经常改动的话(例如博客的首页),那么这个变大的文件就会被频繁的下载,使网页速度变慢。

最简单的使用方法是把data URI嵌入到一个强制缓存的外部样式表里。这样的话,在浏览器缓存为空的情况下,网站速度会比较快(因为少了额外的请求),而在浏览器存在缓存的情况下,则体验是一样的。

浏览器支持情况

绝大多数的现代浏览器都支持data URI:
Firefox 2+
Opera 7.2+ - data URI必须少于4100个字符
Chrome (all versions)
Safari (all versions)
Internet Explorer 8+ - data URI必须小于32k

由于版本低于8的IE浏览器不支持data URI,你需要决定是否值得为这些不支持data URI的浏览器提供替代的东西(可以看看Stoyan的文章)。

结论

Data URI对网页来说是个很有趣和独特的概念,可能在将来会被越来越广泛的应用,暂时来说,它大概是最适合用于那些跟性能相关的任务上,但是谁也不知道将会会 怎样。但目前你能看到的是使用data URI获取图片时减少额外的HTTP请求带来的一些性能上的优化。另外,Data URI还带来了使用JS动态产生图片的可能性,尽管浏览器对<canvas>的支持的不断增加可能会使得这个方法被淘汰。