简而言之:如果图像很大,使用数据URI将延迟HTML的加载时间。
我编写了一个脚本,用数据URI替换所有内联图像,以减少HTTP请求并加快移动设备的加载时间。
如果执行请求的时间大于下载图像的时间,则这是一个好主意,因为浏览器无论如何都需要下载图像数据(无论是否使用数据URI)。如果将图像嵌入HTML中作为数据URI,则会增加HTML的总大小,其大小为所有图像的大小之和(加上数据URI编码约33%)。
例如,如果打开新请求的连接时间为1秒,您的图像每个需要0.2秒下载,您有10个图像,您的HTML需要0.5秒下载,则需要:
- 仅HTML需要1秒+0.5秒=1.5秒
- 图像需要10 x (1 + 0.2)秒=12秒
如果将图像编码为HTML中的数据URI(大小增加33%):
- 1s + 0.5s + (10 x 0.2s x 1.33) = 4.2s
- (并且没有外部请求图片)
这里的一个重要因素是获取整个页面HTML源代码所需的时间(1.5秒与3.5秒)。如果在绘制页面时必须拥有图片,则数据URI将是一种良好的优化方式。如果可以异步加载大部分带有图片的页面,那么最好优化完全下载HTML。
如果您的图片很大,将它们编码为数据URI会更糟糕。如果每张图片需要1秒钟下载,并且其他因素相同:
使用外部图片:
- 仅用1.5秒+0.5秒下载HTML
- 10 x(1秒+1秒)=20秒下载图片
使用数据URI:
- 1秒+0.5秒+(10 x 1秒x 1.33)=14.8秒直到HTML下载完成!
我猜这取决于HTML文件的大小(大约100kb而不是5kb左右):)?
当浏览器下载页面的HTML源代码时,它开始解释和显示它。当它到达引用单独资源的元素时,例如具有外部URI(而不是数据URI)和(异步)脚本标记的图像,它将开始或排队下载它们,但继续下载和处理页面的HTML。
这意味着随着页面的下载,用户看到越来越多的内容,尽管没有加载图像和有时字体。
当浏览器到达带有数据URI的图像标记时,它必须在处理HTML源代码中该标记后面的任何内容之前下载和解析整个数据URI字符串。因此,如果您的原始HTML为1kb,并嵌入了1MB的图像数据URI,则当浏览器到达该图像标记时,会暂停,因为它下载了由数据URI编码的图像占用的1MB HTML源代码,然后才能处理页面的HTML的更多内容。
浏览器是否必须在完全下载完整个文档之前才能加载其中的链接资源?或者链接的资源,例如文档顶部的CSS和JavaScript,在浏览器完成完整文档之前就已经加载了吗?
链接的资源有自己的加载和解析逻辑。 <script>
标签将同步加载 - 阻止浏览器解析 HTML 源代码,直到引用的脚本被加载并执行 - 除非它们具有 async
属性。外部样式表将并行下载,但会阻塞渲染,直到它们被加载。
这里有一个很好的解释。
如果是这样,是否最好为数据 URI 单独使用 CSS 文件,像这样:
- 为结构加载 CSS(没有数据 URI)
- 为背景图像加载 CSS(所有背景图像都以 URI 格式)
“单独缓存的 jpg 文件” 是否比 “包含在缓存的 css 文件中的基于 URI 的图像” 加载更快?
如何使用数据 URI 的其他建议?
这取决于您要优化什么。您更关心首次呈现时间,即使页面不完整吗?还是更关心整个页面,包括所有图像,完全呈现的时间?
像任何工具一样,没有适用于所有情况的普遍规则,比如“总是使用数据URI”或“永远不要使用数据URI”。一个好的经验法则是对于小图标等小图片使用数据URI。Webpack的url-loader
会自动实现这个逻辑,对于指定大小以下的文件使用数据URI,否则使用外部URL。