<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>西红柿爱番茄 &#187; Iframe</title>
	<atom:link href="http://www.ilovejs.net/archives/tag/iframe/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ilovejs.net</link>
	<description>到了创造为主的阶段，不忘继续学习</description>
	<lastBuildDate>Thu, 15 Dec 2011 06:18:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>使用“动态内联”的方式加载javascript、CSS</title>
		<link>http://www.ilovejs.net/archives/775</link>
		<comments>http://www.ilovejs.net/archives/775#comments</comments>
		<pubDate>Tue, 01 Jun 2010 12:08:58 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[性能优化]]></category>
		<category><![CDATA[Iframe]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[动态内联]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=775</guid>
		<description><![CDATA[“动态内联”这个词是出自“高性能网站建设指南”中第八章“规则8&#8212;使用外部Javascript和CSS”，它的原理是基于权衡页面中内联Javascript、CSS和外联Javascript、CSS时的比较。“纯粹而言，内联快一些”，因为外联的时候需要向服务器发送HTTP请求，这需要更多的加载时间，而相对于内联的方式，页面的总大小（包括HTML内容、js、css等等）的一定的，直接下载的方式当然会更快。但是，从“可缓存”、“组件重用”等方面来考虑，外联的方式更占有优势，可以更快的加载页面。 所以，这里就存在一个权衡点：到底是内联，还是外联？但是，有没有可能，让内联的优势和外联的优势结合起来呢？ 第一种方案就是书中提出的“加载后加载”，意思就是当可以预测到用户将会接下来访问什么页面的时候，可以通过当前页面的onload事件，来加载后续的组件，这样当用户在访问接下来的页面的时候，可以从缓存中获取组件，使得加载速度提升。这种方式是比较普遍的了。它的主要应用在于首页中，比如（Google，百度，Yahoo等等）。 第二种方案就是标题说的“动态内联”。如果服务器知道一个组件是否在浏览器的缓存中，它就可以在内联或者使用外联外部文件之间作出最佳的选择。服务器当然不可能直接查看浏览器的缓存，不过可以通过cookie的方式来检测是否缓存了组件。如果指定的cookie不存在，说明浏览器没有缓存相应的组件，使用内联的方式加载组件；当cookie存在，则使用外联的方式加载组件，从缓存中读取组件。 理论说起来容易，实践起来还是需要技巧的，而基本原理就是：使用Javascript设置cookie，服务器端的语言（php，jsp，asp.net等等）来检测cookie并读取文件，例如PHP中使用file_get_contents来读取文件。下面提供一个简单的例子（测试页面）： [javascript] &#60;?php //检查cookie是否存在，存在则采用外联的方式，否则采用内联的方式 if($_COOKIE[&#34;CSS&#34;]){ echo &#8216;&#60;link rel=&#34;stylesheet&#34; href=&#34;test.css&#34; /&#62;&#8217;; }else{ echo &#34;&#60;style&#62;&#34;.file_get_contents(&#34;test.css&#34;).&#34;&#60;/style&#62;&#34;; } ?&#62; &#60;script&#62; &#8230; <a href="http://www.ilovejs.net/archives/775" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
“动态内联”这个词是出自“高性能网站建设指南”中第八章“规则8&#8212;使用外部Javascript和CSS”，它的原理是基于权衡页面中内联Javascript、CSS和外联Javascript、CSS时的比较。“纯粹而言，内联快一些”，因为外联的时候需要向服务器发送HTTP请求，这需要更多的加载时间，而相对于内联的方式，页面的总大小（包括HTML内容、js、css等等）的一定的，直接下载的方式当然会更快。但是，从“可缓存”、“组件重用”等方面来考虑，外联的方式更占有优势，可以更快的加载页面。
</p>
<p>
所以，这里就存在一个权衡点：到底是内联，还是外联？但是，有没有可能，让内联的优势和外联的优势结合起来呢？
</p>
<p>
第一种方案就是书中提出的“加载后加载”，意思就是当可以预测到用户将会接下来访问什么页面的时候，可以通过当前页面的onload事件，来加载后续的组件，这样当用户在访问接下来的页面的时候，可以从缓存中获取组件，使得加载速度提升。这种方式是比较普遍的了。它的主要应用在于首页中，比如（Google，百度，Yahoo等等）。
</p>
<p>
第二种方案就是标题说的“动态内联”。如果服务器知道一个组件是否在浏览器的缓存中，它就可以在内联或者使用外联外部文件之间作出最佳的选择。服务器当然不可能直接查看浏览器的缓存，不过可以通过cookie的方式来检测是否缓存了组件。如果指定的cookie不存在，说明浏览器没有缓存相应的组件，使用内联的方式加载组件；当cookie存在，则使用外联的方式加载组件，从缓存中读取组件。
</p>
<p>
理论说起来容易，实践起来还是需要技巧的，而基本原理就是：使用Javascript设置cookie，服务器端的语言（php，jsp，asp.net等等）来检测cookie并读取文件，例如PHP中使用file_get_contents来读取文件。下面提供一个简单的例子（<a  href="http://www.ilovejs.net/lab/dynamic-inline/test.php">测试页面</a>）：
</p>
<p>[javascript]<br />
&lt;?php<br />
//检查cookie是否存在，存在则采用外联的方式，否则采用内联的方式<br />
if($_COOKIE[&quot;CSS&quot;]){<br />
  echo &#8216;&lt;link rel=&quot;stylesheet&quot; href=&quot;test.css&quot; /&gt;&#8217;;<br />
}else{<br />
  echo &quot;&lt;style&gt;&quot;.file_get_contents(&quot;test.css&quot;).&quot;&lt;/style&gt;&quot;;<br />
}<br />
?&gt;<br />
&lt;script&gt;<br />
&quot;use strict&quot;; //Don&#8217;t cancel<br />
//首先检测是否设置了cookie，如果没有则设置，并通过iframe的方式先缓存组件<br />
//在test.html中加载了test.css文件，先在浏览器缓存起来。<br />
if(!(/CSS/.test(document.cookie))){<br />
  document.cookie=&quot;CSS=1&quot;;<br />
  var iframe=document.createElement(&quot;iframe&quot;);<br />
  iframe.src=&quot;test.html&quot;;<br />
  iframe.width=&quot;0&quot;;<br />
  iframe.height=&quot;0&quot;;<br />
  document.body.appendChild(iframe);<br />
}<br />
&lt;/script&gt;<br />
[/javascript]</p>
<p>
如上代码所示，在页面第一次访问的时候，此时cookie还没有设置，采用内联的方式来加载组件，当刷新页面或者浏览其他页面的时候，会检测cookie并从缓存中读取test.css组件。这样就结合使用了内联和外联的优势，对页面加载速度起到了一定的优化效果。对于“动态内联”更多的描述，书中提到：
</p>
<blockquote><p>
这种方式的美好之处在于它的宽容，即便cookie的状态和缓存不匹配，页面也能够工作，只是没有本应该的那么优化而已。基于会话的cookie技术在内联时会发生错误，即便组件已经被放到浏览器缓存中了&#8212;&#8212;如果用户重新打开浏览器，基于会话的cookie会消失，但组件依然存在于缓存中。将cookie从基于会话的改为短期的（数小时或数天）可以解决这个问题，但当它们并不在浏览器缓存中时，使用外部文件又会出错。不管出现哪种情况，页面都能够正常工作。
</p></blockquote>
<p>对于上面的描述，我存在一个问题：当cookie存在，而缓存不存在的时候，就over了。除非在每一个页面的js中都加载一个iframe来缓存组件，比如修改上面的js代码如下：<br />
[javascript]<br />
  document.cookie=&quot;CSS=1&quot;;<br />
  var iframe=document.createElement(&quot;iframe&quot;);<br />
  iframe.src=&quot;test.html&quot;;<br />
  iframe.width=&quot;0&quot;;<br />
  iframe.height=&quot;0&quot;;<br />
  document.body.appendChild(iframe);<br />
[/javascript]<br />
上面的方式就是不检测cookie是否存在，而是每个页面每次浏览的时候都动态生成一个iframe来缓存文件。这确实没有必要的。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/775/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>主页面和iframe中加载资源的测试</title>
		<link>http://www.ilovejs.net/archives/760</link>
		<comments>http://www.ilovejs.net/archives/760#comments</comments>
		<pubDate>Fri, 28 May 2010 21:55:11 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[Iframe]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=760</guid>
		<description><![CDATA[对于iframe，我是比较少做测试的，今晚由于我的一个问题“有没有办法让页面HTML内容和其他资源并行加载”引发了我和瓶子之间的一番关于iframe的测试。 首先是由于我的一个误解“iframe会阻塞后面资源的下载”以及上面的问题引发的“浏览器解析页面和下载资源的顺序问题”开始。在Webkit的官方博客中发表了这么篇文章：《How WebKit Loads a Web Page》，讲述页面解析HTML和下载资源的机制。文中就说明了Webkit在加载一个页面的时候存在两个下载通道，一个用于加载html document，另一个用于加载子资源（图片、CSS、JS等等），并且这两个通道存在时间顺序问题（查看原文或者下面的图示即可了解），这就说明了“让页面HTML内容和其他资源并行加载”就目前来说是不可能实现的，因为这是由浏览器内部的加载页面的机制决定了。 在这篇文章里，跟瓶子就“Frames”这个字眼见解有些不同，他认为这就是跟普通页面的iframe一样的意思（这也是接下来一堆测试iframe的导火线），而我曾经在某篇En文里看过Firefox中解析HTML页面的时候，也提到了Frame这个字眼，而它所说的Frame并不是普通html中的iframe，而是相当于一个“暗箱”，或者说是一个“容器”，来解析HTML页面内容。这个问题未得到证实，就不多说了。 之后我就凭记忆说了一句“加载iframe会阻碍后面的元素的加载”，我的本意是说，当iframe中有js、图片、css等资源需要加载时，会阻塞主页面中iframe后面资源的加载。可是经过他的测试，发现说“主页面的html和iframe的html是并行加载的”。刚开始我就纳闷了，就拿出《高性能网站建设进阶指南》来查看关于iframe的内容，发现书中并没有关于“加载iframe会阻碍后面的元素的加载”的论述，而是叙述了当iframe前面有CSS或者JS资源的时候，会阻塞iframe的加载（测试页面），如果放到iframe其后的话，则会iframe和主页面会并行加载（测试页面）。同时书中也指明了一点“iframe会阻碍主页面onload事件的触发”。 经过这一番测试，不得不承认是我的失误，记错了~ 但是我在测试过程中，通过观察firebug和HTTPWatch生成的HTTP瀑布图发现了一个比较有趣的事情：当iframe在js、图片、css等主页面资源的前面的时候，在HTTP瀑布图中显示iframe内的资源都是后于主页面的资源加载的。我就纳闷了，这么奇怪的问题。接下来我就写了一个测试页面，页面中iframe内的js文件中定义了一个函数，而且文件有100多K大小；在主页面的fulljsmin.js文件中调用该函数，文件很小（测试页面）。通过测试更有意思的是，成功调用了该函数，没有出现未定义的错误，这不是跟HTTP瀑布图中显示的不符合吗？下面是在firebug和HTTPWatch下的HTTP瀑布图： 同时，在Chrome下用Inspect插件来测试，也都发现了这样的情况。虽然在IE8下HTTPWatch中显示iframe并没有和主页面并行加载，但是出现的问题都基本跟上面所述一致。这难道是firebug、HTTPWatch、Inspect的一个bug？不可能同时都出现这个问题吧？我想问题还应该是出在页面加载iframe的机制上。 对于这个问题，我最初的想法是主页面在加载iframe的时候会开启另外一个进程来加载iframe里面的资源，但是浏览器普遍都只能是两个资源并行下载，iframe内也同样难逃这条规则。所以这个想法就错误了，而瓶子对于这个页面同时加载主页面的资源和iframe内的资源的看法是： 父页面html加载->html解析 如果有iframe，就开一个iframe线程下载html，重复步骤1 把页面其他要请求的元素放入一个加载队列，这个队列是全局的，如果是iframe的html解析的时候，也会被加入到这个队列里。但是最终会出现的顺序可能有所不同，有的浏览器应该会等html全部分析完再开始执行加载队列，有的则是一边解析一边对队列进行执行。对于第一种情况，出现的顺序应该是：主页面的内容先加载，iframe里面的内容会最后连续加载对于第二种情况，出现的顺序可能是交叉的，不过iframe的加载应该大多集中在一处。 第一点看法是毋庸置疑的，但是第二点所说的“开一个iframe线程下载html，重复步骤1”，这点或许需要说明一下，这开一个iframe线程是受到浏览器通常只能同时两个并发下载数的限制的，所以这里的新开线程可能会受到CSS、JS文件的影响，就像开头说的，CSS、JS在iframe前面的时候，会阻塞iframe的加载（测试页面，这次在页面中嵌套了两个iframe）。从下图可以说明，在iframe前面有CSS、js等外联文件的时候，阻塞是比较严重的： 对于第三点的将iframe中的资源加入加载队列，这里我就有点迷糊于“在什么位置加入加载队列”。如果简单的从HTTP瀑布图来说的话，第一种情况是比较在理的：在页面开始加载资源的时候，自动生成一个加载队列，遇到iframe的时候，就将iframe中的资源加载到队列的末尾，可是这又不符合上面的函数调用的测试。所以我初步总结为：在Firefox、Chrome、IE中，当主页面开始加载子资源的时候，自动生成一个加载队列，当遇到iframe的时候，就把iframe里的子资源加入到加载队列里，主页面后续的子资源再加入到加载队列中。当页面内有几个iframe的时候，也是这个理。 写本文时我都还存在很多的疑问需要慢慢揭开，同时也希望对这方面有研究的朋友，能指明一二，共同探讨~]]></description>
			<content:encoded><![CDATA[<p>
对于iframe，我是比较少做测试的，今晚由于我的一个问题“有没有办法让页面HTML内容和其他资源并行加载”引发了我和<a  href="http://www.webairness.com/">瓶子</a>之间的一番关于iframe的测试。
</p>
<p>
首先是由于我的一个误解“iframe会阻塞后面资源的下载”以及上面的问题引发的“浏览器解析页面和下载资源的顺序问题”开始。在Webkit的官方博客中发表了这么篇文章：《<a  href="http://webkit.org/blog/1188/how-webkit-loads-a-web-page/">How WebKit Loads a Web Page</a>》，讲述页面解析HTML和下载资源的机制。文中就说明了Webkit在加载一个页面的时候存在两个下载通道，一个用于加载html  document，另一个用于加载子资源（图片、CSS、JS等等），并且这两个通道存在时间顺序问题（查看原文或者下面的图示即可了解），这就说明了“让页面HTML内容和其他资源并行加载”就目前来说是不可能实现的，因为这是由浏览器内部的加载页面的机制决定了。
</p>
<p>
<img src="/wp-content/uploads/2010/05/how-to-load-web-page.png" alt="" title="how to load web page" width="619" height="456" class="alignnone size-full wp-image-766" />
</p>
<p>
在这篇文章里，跟瓶子就“Frames”这个字眼见解有些不同，他认为这就是跟普通页面的iframe一样的意思（这也是接下来一堆测试iframe的导火线），而我曾经在某篇En文里看过Firefox中解析HTML页面的时候，也提到了Frame这个字眼，而它所说的Frame并不是普通html中的iframe，而是相当于一个“暗箱”，或者说是一个“容器”，来解析HTML页面内容。这个问题未得到证实，就不多说了。
</p>
<p>
之后我就凭记忆说了一句“加载iframe会阻碍后面的元素的加载”，我的本意是说，当iframe中有js、图片、css等资源需要加载时，会阻塞主页面中iframe后面资源的加载。可是经过他的测试，发现说“主页面的html和iframe的html是并行加载的”。刚开始我就纳闷了，就拿出《高性能网站建设进阶指南》来查看关于iframe的内容，发现书中并没有关于“加载iframe会阻碍后面的元素的加载”的论述，而是叙述了当iframe前面有CSS或者JS资源的时候，会阻塞iframe的加载（<a  href="http://www.ilovejs.net/lab/iframe/template3.html">测试页面</a>），如果放到iframe其后的话，则会iframe和主页面会并行加载（<a  href="http://www.ilovejs.net/lab/iframe/template4.html">测试页面</a>）。同时书中也指明了一点“iframe会阻碍主页面onload事件的触发”。
</p>
<p>
经过这一番测试，不得不承认是我的失误，记错了~
</p>
<p>
但是我在测试过程中，通过观察firebug和HTTPWatch生成的HTTP瀑布图发现了一个比较有趣的事情：当iframe在js、图片、css等主页面资源的前面的时候，在HTTP瀑布图中显示iframe内的资源都是后于主页面的资源加载的。我就纳闷了，这么奇怪的问题。接下来我就写了一个测试页面，页面中iframe内的js文件中定义了一个函数，而且文件有100多K大小；在主页面的fulljsmin.js文件中调用该函数，文件很小（<a  href="http://www.ilovejs.net/lab/iframe/template.html">测试页面</a>）。通过测试更有意思的是，成功调用了该函数，没有出现未定义的错误，这不是跟HTTP瀑布图中显示的不符合吗？下面是在firebug和HTTPWatch下的HTTP瀑布图：
</p>
<p>
<img src="http://www.ilovejs.net/wp-content/uploads/2010/05/iframe1.png" alt="" title="iframe1" width="502" height="192" class="alignnone size-full wp-image-761" /><br />
<img src="http://www.ilovejs.net/wp-content/uploads/2010/05/iframe2.png" alt="" title="iframe2" width="608" height="139" class="alignnone size-full wp-image-762" />
</p>
<p>
同时，在Chrome下用Inspect插件来测试，也都发现了这样的情况。虽然在IE8下HTTPWatch中显示iframe并没有和主页面并行加载，但是出现的问题都基本跟上面所述一致。这难道是firebug、HTTPWatch、Inspect的一个bug？不可能同时都出现这个问题吧？我想问题还应该是出在页面加载iframe的机制上。
</p>
<p>
对于这个问题，我最初的想法是主页面在加载iframe的时候会开启另外一个进程来加载iframe里面的资源，但是浏览器普遍都只能是两个资源并行下载，iframe内也同样难逃这条规则。所以这个想法就错误了，而瓶子对于这个页面同时加载主页面的资源和iframe内的资源的看法是：
</p>
<blockquote>
<ol>
<li>父页面html加载->html解析</li>
<li>如果有iframe，就开一个iframe线程下载html，重复步骤1</li>
<li>把页面其他要请求的元素放入一个加载队列，这个队列是全局的，如果是iframe的html解析的时候，也会被加入到这个队列里。但是最终会出现的顺序可能有所不同，有的浏览器应该会等html全部分析完再开始执行加载队列，有的则是一边解析一边对队列进行执行。对于第一种情况，出现的顺序应该是：主页面的内容先加载，iframe里面的内容会最后连续加载对于第二种情况，出现的顺序可能是交叉的，不过iframe的加载应该大多集中在一处。</li>
</ol>
</blockquote>
<p>
第一点看法是毋庸置疑的，但是第二点所说的“开一个iframe线程下载html，重复步骤1”，这点或许需要说明一下，这开一个iframe线程是受到浏览器通常只能同时两个并发下载数的限制的，所以这里的新开线程可能会受到CSS、JS文件的影响，就像开头说的，CSS、JS在iframe前面的时候，会阻塞iframe的加载（<a  href="http://www.ilovejs.net/lab/iframe/template2.html">测试页面</a>，这次在页面中嵌套了两个iframe）。从下图可以说明，在iframe前面有CSS、js等外联文件的时候，阻塞是比较严重的：
</p>
<p>
<img src="http://www.ilovejs.net/wp-content/uploads/2010/05/iframe31.png" alt="" title="iframe3" width="529" height="217" class="alignnone size-full wp-image-764" />
</p>
<p>
对于第三点的将iframe中的资源加入加载队列，这里我就有点迷糊于“在什么位置加入加载队列”。如果简单的从HTTP瀑布图来说的话，第一种情况是比较在理的：在页面开始加载资源的时候，自动生成一个加载队列，遇到iframe的时候，就将iframe中的资源加载到队列的末尾，可是这又不符合上面的函数调用的测试。所以我初步总结为：在Firefox、Chrome、IE中，当主页面开始加载子资源的时候，自动生成一个加载队列，当遇到iframe的时候，就把iframe里的子资源加入到加载队列里，主页面后续的子资源再加入到加载队列中。当页面内有几个iframe的时候，也是这个理。
</p>
<p>
写本文时我都还存在很多的疑问需要慢慢揭开，同时也希望对这方面有研究的朋友，能指明一二，共同探讨~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/760/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

