data uri 科普 笔者对本文的定位是实践操作型,所以一些理论基础只点到为止。首先 data uri 是什么? 引用 wikipedia 上对其的解释:
data uri 是一种提供让外置资源的直接内嵌在页面中的方案。这种技术允许我们只需单次 http 请求即可获取所有需要引用的图片与样式资源,并因无需多次请求资源而变的高效。
在 rfc2397(http://tools.ietf.org/html/rfc2397)中定义了它格式规范:
data:[][;charset=][;base64],
data uri 初探 看格式规范貌似不是很友好,我们以内嵌图片为例:
data:image/png;base64, 是固定的格式, image/png 是图片的mime类型,base64是数据编码方式。这里还有必要指出下base64 编码后的数据会比原始数据大 4/3 左右,这与base64 编码算法有关。 如需使用在电子邮件中,根据 rfc 822 规定,每 76 个字符,还需要加上一个回车换行,此时编码后数据长度大约为原长的135.1%。
为验证理论的我们做如下的测试,分别对不同尺寸的图片进行base64编码,与我们的预期一致,比原始数据增长了 1/3 :
图片尺寸 | 原始大小 | base64大小 | 增长率 |:-----------|:------------|:-------------|:-------------|16*16 | 618 | 824 | 34.2%24*24 | 1,063 | 1,420 | 33.6%32*32 | 1,615 | 2,156 | 33.5%42*42 | 2,510 | 3,348 | 33.4%48*48 | 2,892 | 3,856 | 33.3%96*96 | 8,217 | 10,956 | 33.3%350*350 | 49,899 | 66,532 | 33.3%
图片是使用 data uri 最常用的情景,但 data uri 是与资源类型无关的规范,您也可以使用 data uri 内嵌其他资源:
var cvs = 'data:text/csv;charset=utf-8,' + encodeuricomponent(csv);var html = 'data:text/html;charset=utf-8,' + encodeuricomponent(html);
data uri 兼容性 在前端,浏览器兼容性几乎每个技术都逃不过的话题,检阅 data uri 的兼容性:
firefox 2+ opera 7.2+ chrome++ safari++ internet explorer 8+ 大部分主流浏览器都早已支持 data uri,ie8 虽支持但其最大长度不能超过32k的数据,在 ie9 下已解除此限制,ie 详细的文档可细读微软官方文档。 剩下的依旧是面对在国内还是 a 类浏览量的 ie 6/7, 我们可以采用与 data uri 类似的 mhtml(笔者认为其设计上比 data uri 是更优秀的,考虑到了内嵌数据的重用). mhtml 详细的介绍不在本文的讨论范围,但需要指出的是微软在 2011 年发布了 mhtml 中的漏洞可能允许信息泄露 的补丁, 将造成 mhtml 无法被引用的问题,所以在 ie 中使用 mhtml 的方案会有极大的风险,权且当扩展知识面不推荐采用。
http://technet.microsoft.com/zh-cn/security/advisory/2501696 http://www.microsoft.com/china/security/bulletins/ms03-014.mspx data uri 最佳实践 在 data uri 转换之前我们不进行图片合并,而是直接使用小图片,如此省去了合图定位的麻烦,
background-image:url(data:image/png;base64,ivborw0kggoaaa...elftksuqmcc);*background-image:url(http://cdn.example.com/foo.gif);
比较数据:
图片尺寸 | 原始大小 | base64大小 | gzip大小 | gzip压缩率 | 增长率 |:-----------|:------------|:-------------|:-------------|:-------------|:-------------|16*16 | 618 | 824 | 668 | 81.1% | 108.8%24*24 | 1,063 | 1,420 | 1,119 | 78.8% | 5.3%32*32 | 1,615 | 2,156 | 1,670 | 77.5% | 3.9%42*42 | 2,510 | 3,348 | 2,568 | 76.7% | 2.3%48*48 | 2,892 | 3,856 | 2940 | 76.2% | 1.7%96*96 | 8,217 | 10,956 | 8304 | 75.8% | 1.1%350*350 | 49,899 | 66,532 | 50,095 | 75.3% | 0.4%
diy 生成工具 node 是名副其实的前端开发得力助手,只用3行代码就能让一张图片转换成base64编码:
var body = fs.readfilesync('./foo.png', 'binary'); // 输入var image = new buffer(body, 'binary').tostring('base64'); // base64编码var base64 = 'data:image/png;base64,' + image; // 输出
datauri 格式数据需要更多cpu计算来呈现图片,也许在性能稍弱的pc上,额外请求图片的方案可能更早的渲染出图片,尤其在移动端有限cpu的情景下,一定要慎用。
这里折中方案是限定转换的条件,只有小于 2k 的小图才被转换成base64编码, 2k 是比较推荐的阀值