浏览器是否在每个页面加载时都解析javascript?

问题描述 投票:189回答:6

浏览器(IE和Firefox)每次页面刷新时是否解析链接的javascript文件吗?

它们可以缓存文件,所以我猜他们不会每次都尝试下载它们,但是由于每个页面本质上是分开的,所以我希望它们能够删除所有旧代码并重新解析。

这是低效的,虽然完全可以理解,但是我想知道现代浏览器是否足够聪明,可以避免站点内的解析步骤。我正在考虑网站使用JavaScript库(例如ExtJS或jQuery等)的情况。

javascript browser-cache javascript-engine
6个回答
338
投票

这些是我能够挖掘的细节。首先值得注意的是,尽管通常认为JavaScript是在VM上解释并运行的,但是现代解释器的确不是这种情况,现代解释器倾向于将源代码直接编译为机器代码(IE除外)。] >


Chrome:V8引擎

V8具有编译缓存。它使用源的哈希存储最多5个垃圾回收的已编译JavaScript。这意味着两个相同的源代码片段将共享内存中的缓存条目,而不管它们如何包含在内。重新加载页面时不会清除此缓存。

Source


更新-19/03/2015

Chrome小组已发布details about their new techniques for JavaScript streaming and caching

  1. 脚本流式传输
  2. 脚本流传输优化了JavaScript文件的解析。 [...]

[从版本41开始,下载开始后,Chrome会在单独的线程上解析异步脚本和延迟脚本。这意味着解析可以在下载完成后仅几毫秒内完成,从而使页面加载速度提高了10%。

  1. 代码缓存
  2. [通常,V8引擎每次访问时都会编译页面的JavaScript,将其转换为处理器可以理解的指令。一旦用户离开页面,该编译代码便被丢弃,因为编译代码高度依赖于编译时机器的状态和上下文。

Chrome 42引入了一种高级技术,用于存储已编译代码的本地副本,因此,当用户返回页面时,可以跳过所有下载,解析和编译步骤。在所有页面加载中,Chrome可以避免大约40%的编译时间,并节省移动设备上的宝贵电量。


Opera:Carakan Engine

实际上,这意味着每当要编写脚本程序时,已编译,其源代码与某些其他程序的源代码相同最近编译的,我们重用了之前的输出编译器,然后完全跳过编译步骤。这个缓存相当在典型的浏览方案中有效,在这种情况下,一个加载页面之后来自同一站点的页面,例如新闻中的不同新闻文章服务,因为每个页面通常加载相同的页面,有时甚至很大,脚本库。

因此JavaScript在页面重新加载时被缓存,对同一脚本的两个请求将不会导致重新编译。

Source


Firefox:SpiderMonkey Engine

SpiderMonkey使用Nanojit作为其本机后端,即JIT编译器。可以看到机器代码的编译过程here。简而言之,它在加载脚本时appears

重新编译脚本。但是,如果we take a closer look内部的Nanojit可以看到,用于跟踪编译的上级监视器jstracer可以在编译过程中过渡到三个阶段,从而为Nanojit提供了好处:

跟踪监视器的初始状态为监视。这意味着Spidermonkey正在解释字节码。每次蜘蛛猴解释后向跳转字节码,监视器记下跳转目标程序计数器(PC)值达到的次数跳进去。此数字称为PC的命中计数。如果命中特定PC的计数达到阈值,目标是认为很热。

[当监视器确定目标PC很热时,它会在哈希表中查找片段以查看是否有一个片段包含本机代码该目标PC。如果找到这样的片段,它将过渡到执行模式。否则,它将转换为记录模式。

这意味着对于hot个代码片段,将缓存本机代码。这意味着不需要重新编译。尚不清楚这些哈希的本机部分是否在页面刷新之间保留。但我认为它们是。 如果有人能找到支持的证据,那就太好了。

编辑

:有人指出,Mozilla开发人员Boris Zbarsky已声明Gecko不会缓存已编译的脚本yet。取自this SO answer

Safari:JavaScriptCore / SquirelFish引擎

我认为此实现的最佳答案已经是been given by someone else

我们目前不缓存字节码(或本机代码)。它是一个我们考虑过的选项,但是目前,代码生成是JS执行时间的琐碎部分(<2%),因此我们不追求此刻。

[这是由Safari的首席开发人员Maciej Stachowiak编写的。所以我认为我们可以做到这一点。

我无法找到任何其他信息,但是您可以了解有关最新SquirrelFish Extreme引擎here的速度改进的更多信息,或者如果您喜欢冒险,可以浏览源代码here


IE:Chakra Engine

此字段中没有有关IE9的JavaScript引擎(Chakra)的当前信息。 如果有人知道,请发表评论。

这是非常非正式的,但是对于IE的较旧引擎实现,Eric Lippert(a MS developer of JScript)在博客回复here中指出:]]

JScript Classic就像编译语言一样,在任何JScript Classic程序运行之前,我们都对语法进行完整的语法检查,生成完整的解析树,并生成字节码。然后,我们通过字节码解释器运行字节码。从这个意义上讲,JScript与Java一样“被编译”。 不同之处在于JScript不允许您保留或检查我们专有的字节码

。而且,字节码比JVM字节码高得多-JScript Classic字节码语言只不过是解析树的线性化,而JVM字节码显然旨在在低级堆栈计算机上运行。

这表明字节码不会以任何方式持久存在,因此不会缓存字节码。

Opera这样做,如另一个答案中所述。 (source

Firefox(SpiderMonkey引擎)不会不是

缓存字节码。 (source

WebKit(Safari,Konqueror)不会not缓存字节码。 (source

我不确定IE [6/7/8]或V8(Chrome),我认为IE可能会进行某种缓存,而V8可能不会。 IE是封闭源,所以我不确定,但是在V8中,缓存“已编译”的代码可能没有意义,因为它们直接编译为机器代码。

据我所知,只有Opera会缓存已解析的JavaScript。请参见“高速缓存的已编译程序”一节here

Google Dart通过“快照”明确解决此问题毫无用处-目标是通过加载准备好的代码版本来加快初始化和加载时间。

InfoQ在[http://www.infoq.com/articles/google-dart]上有不错的文章>

我认为正确的答案是“并非总是如此”。据我了解,浏览器和服务器都在确定要缓存的内容方面发挥作用。如果您确实需要每次都重新加载文件,那么我认为您应该能够从Apache内部进行配置(例如)。当然,我想可以将用户的浏览器配置为忽略该设置,但这不太可能。

因此,我想在大多数实际情况下,javascript文件本身都会被缓存,但是每次页面加载时都会动态地重新解释。

浏览器肯定会使用缓存,但是是的,每次页面刷新时,浏览器都会解析JavaScript。因为每当浏览器加载页面时,它都会创建2棵树1.内容树和2.渲染树。

此渲染树包含有关dom元素的视觉布局的信息。因此,每当加载页面时,都会对javascript进行解析,并且javascript进行的任何动态更改都将类似于定位dom元素,show / hide元素,add / remove元素,从而使浏览器重新创建渲染树。但是像FF和chrome这样的现代浏览器在处理它方面略有不同,它们具有增量渲染的概念,因此,只要js进行了如上所述的动态更改,它只会导致这些元素再次渲染和重新绘制。


12
投票

Opera这样做,如另一个答案中所述。 (source


3
投票

据我所知,只有Opera会缓存已解析的JavaScript。请参见“高速缓存的已编译程序”一节here


2
投票

Google Dart通过“快照”明确解决此问题毫无用处-目标是通过加载准备好的代码版本来加快初始化和加载时间。


0
投票

我认为正确的答案是“并非总是如此”。据我了解,浏览器和服务器都在确定要缓存的内容方面发挥作用。如果您确实需要每次都重新加载文件,那么我认为您应该能够从Apache内部进行配置(例如)。当然,我想可以将用户的浏览器配置为忽略该设置,但这不太可能。

因此,我想在大多数实际情况下,javascript文件本身都会被缓存,但是每次页面加载时都会动态地重新解释。


0
投票

浏览器肯定会使用缓存,但是是的,每次页面刷新时,浏览器都会解析JavaScript。因为每当浏览器加载页面时,它都会创建2棵树1.内容树和2.渲染树。

此渲染树包含有关dom元素的视觉布局的信息。因此,每当加载页面时,都会对javascript进行解析,并且javascript进行的任何动态更改都将类似于定位dom元素,show / hide元素,add / remove元素,从而使浏览器重新创建渲染树。但是像FF和chrome这样的现代浏览器在处理它方面略有不同,它们具有增量渲染的概念,因此,只要js进行了如上所述的动态更改,它只会导致这些元素再次渲染和重新绘制。

© www.soinside.com 2019 - 2024. All rights reserved.