Data URI是一个富有争议的特性。即使在最有经验的前端开发者眼中,也会形成对 data URI 截然不同的看法:有人认为它是性能优化神器,有人认为它已经落后于时代。为什么会这样?本文带你进行深入的剖析。
URI,不是URL
我们习惯的 URL 的全称是统一资源定位符(uniform resource locator),它是由一个“协议”和一个“地址”组成。
协议
告诉浏览器或者程序用何种方式去获取这个资源,
地址
告诉程序在哪里找到这个资源,每个地址都能唯一定位一个公开资源(比如图片、HTML、JavaScript 等)或非公开资源(这时候就需要提供用户名和密码)。
URI 是一个更广的概念,或者说 URL 是最常见的一种 URI。URI的全称是统一资源定位符(uniform resource identifier),由一个“协议”和“定位符”组成。定位符其实就是补充信息,它可以是一个地址(如果是这样的话,那这个 URI 就是一个 URL),也可以是数据本身(比如 data URI),或者命名空间(URN)。
所以 Data URI 不是 URL。
在1998年的
RFC 2397
中第一次定义了 Data URI:
A new URL scheme, "data", is defined. It allows inclusion of small data items as "immediate" data, as if it had been included externally.
本文档定义了一个新的URL 协议(我觉得这里有点误用,应该是 URI 协议,因为跟蒂姆·伯纳斯·李的
RC 2396
有冲突)。
它允许(文档)直接使用一小段数据作为“即时数据”
,而不是之前那样必须引用外部资源。
随后,文档定义了 data URI 的格式:
data:[mediatype>][;base64],data>
在这种格式中,
data:
就是 URI 的协议,表明这是一个 data URI。
mediatype
可能是
image/png
之类的,如果不填,默认是
text/plain
。
以下是一个HTML代码片段:
SRC="data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7" ALT="Larry">
Base64 编码
可能有同学会问,base64 编码在 data URI 中的角色是什么?
我们一般指定
base64
编码方式,如果不填,默认是低效的
URL编码
。
对于非英文字符串,URL 编码一种非常浪费空间的编码方式。URL 编码在地址栏中很常见,对于 URL 安全的字符(比如英文字母、数字、中划线、下划线等)就直接显示,对于 URL 不安全的字符(比如非英文的字符)就编码成
%xx
的形式。
二进制文件中包含很多 URL 不安全的字符,所以转成 URL 编码字符之后很冗长。所以有了 base64 编码,base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符(包括大写的英文字母、小写的英文字母、数字、+、/)。
以下是“MAN”这个单词对应的二进制位和 base64 编码。
举一个实际的例子,对于下面这个图片:
直接使用二进制文件,然后进行 URL 编码结果如下(空格会被忽略):
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%