URI:统一资源标识符。由一个‘协议’和‘定位符’组成。定位符其实是补充信息,它可以是一个地址(如果是这样的话,那这个URI就是一个URL),也可以是数据本身(比如 data URI),或者命名空间(URN).
URI较URL是一个更广的概念,或者说URL是最常见的一种URI。所以Data URI不是URL。
RFC 2397(The "data" URL scheme)中第一次定义了Data URI:
它允许文档直接使用一小段数据作为"即时数据",而不是之前那样必须引用外部资源
随后,文档定义了data URI的格式:
data:[<mediatype>][;base64],<data>
在这种格式中,data:就是URI的协议,表明就是一个data URI。
mediatype可能是image/png之类的,如果不填,默认是text/plain
我们一般指定base64编码方式,如果不填,默认是低效的URL编码。
对于非英文字符串,URL编码是一种非常浪费空间的编码方式。URL编码在地址栏中很常见,对于URL安全的字符(比如英文字母、数字、中划线、下划线等)就直接显示,对于URL不安全的字符(比如非英文的字符)就编码成%XX的形式。
二进制文件中包含很多URL不安全的字符,所以转成URL编码字符之后很冗长。因此所以有了base64编码。(关于base64编码http://www.jianshu.com/writer#/notebooks/3331706/notes/11322163)。
通过对比 Base64编码明显比URL编码小很多(但是因为使用了6个比特而不是8个比特,所以仍然比压缩过的二进制文件大一些)
因此,当我们提到data URI时,99%同时是指配套使用base64编码技术,来把一个二进制资源文件(比如字体或图片)合并到主文档(可能是HTML,可能是CSS)中。
性能神器还是弃之可惜的鸡肋?
误区一:节省请求等于性能优化?
对于前端来说,显而易见好处是能够减少图片的HTTP请求,而缺点可能是不够显而易见。
样式表会变得很大,从而阻塞关键下载和渲染。
通俗地讲,图片文件或字体文件的体积转移到了HTML或CSS中,而后者的体积直接影响到渲染,导致用户会长时间注视空白屏幕。HTML和CSS阻塞渲染,图片不会。
这是Base64的第一个缺点,资源合并到CSS文件中导致体积增大,进而阻塞关键路径。
误区二:Base64 能获益于Gzip压缩?
Gzip是在web前端最常见的一种压缩文本的方法。
Gzip压缩算法分两步。
第一步:采用LZ77算法的一种变种替换字符串。
第二步:使用Huffman树来储存出现的位置和长度。
简单来讲,Gzip把原文本中多次出现的相同字符串标记为一个‘标记’,所以文本中重复出现的字符串越多,压缩率越高。
图片经过Base64转化后变成的文本是无规律的,所以在Gzip中不能达到较高的压缩率。
误区三:考虑缓存了吗?
Base64影响了我们的缓存策略。
我们把样式、图片、字体文件等合并到一起之后,整个变成一个资源,我们无法再分别为它们配置缓存时间,以及更新资源。而图片、字体、HTML和CSS的更新频率都是不一样的。
在平常的项目中,CSS文件的修改频率是较高的,图片其次,而字体文件几乎不改,我们一般会为不同类型的文件设置不同的缓存失效时间,以及在更新某个文件之后单独更新这个文件的时间戳。混在一起之后,即使我们只是想更新CSS规则里面的一个字号,整个几百k的文件就会重新生成。用户不得不在每次小型更新后重新下载整个大文件,这违背了基本的缓存原则。
Base64跟CSS混在一起,难以分别进行缓存设置和更新。
误区四:CSSOM渲染
Base64跟CSS混在一起,大大增加了浏览器需要解析CSS树的耗时。一般解析CSS树的过程是很快的,一般在几十微秒到几毫秒之间。如果CSS文件中混入了Base64,那么(因为文件体积的大幅增长)解析时间会增长到十倍以上。增加的解析时间全部都在关键渲染路径上
有没有适合使用data URI的场景?
有!在某些罕见特例中,也许使用Base64是合理的选择。在规避了以上缺点时,就可以考虑使用它了。
网友评论