浏览器(IE 和 Firefox)是否在每次页面刷新时解析链接的 javascript 文件?
他们可以缓存文件,所以我猜他们不会每次都尝试下载它们,但由于每个页面本质上都是独立的,我希望他们拆除所有旧代码并重新解析它。
这是低效的,虽然完全可以理解,但我想知道现代浏览器是否足够聪明来避免站点内的解析步骤。我正在考虑网站使用 javascript 库的情况,如 ExtJS 或 jQuery 等。
浏览器(IE 和 Firefox)是否在每次页面刷新时解析链接的 javascript 文件?
他们可以缓存文件,所以我猜他们不会每次都尝试下载它们,但由于每个页面本质上都是独立的,我希望他们拆除所有旧代码并重新解析它。
这是低效的,虽然完全可以理解,但我想知道现代浏览器是否足够聪明来避免站点内的解析步骤。我正在考虑网站使用 javascript 库的情况,如 ExtJS 或 jQuery 等。
这些是我能够挖掘的细节。首先值得注意的是,尽管 JavaScript 通常被认为是在 VM 上解释和运行的,但现代解释器并非如此,它们倾向于将源代码直接编译为机器代码(IE 除外)。
铬:V8引擎
V8 有一个编译缓存。这使用源代码的哈希存储编译后的 JavaScript,最多可进行 5 次垃圾回收。这意味着两个相同的源代码将在内存中共享一个缓存条目,无论它们是如何包含的。重新加载页面时不会清除此缓存。
更新 - 19/03/2015
Chrome 团队已经发布了有关他们的 JavaScript 流和缓存新技术的详细信息。
脚本流优化了 JavaScript 文件的解析。[...]
从版本 41 开始,Chrome 会在下载开始后立即在单独的线程上解析异步和延迟脚本。这意味着解析可以在下载完成后的几毫秒内完成,并导致页面加载速度提高 10%。
通常,V8 引擎会在每次访问时编译页面的 JavaScript,将其转换为处理器可以理解的指令。一旦用户离开页面,这个编译的代码就会被丢弃,因为编译的代码高度依赖于编译时机器的状态和上下文。
Chrome 42 引入了一种先进的技术,将编译后的代码存储在本地副本,这样当用户返回页面时,下载、解析和编译步骤都可以跳过。在所有页面加载中,这使 Chrome 可以避免大约 40% 的编译时间,并为移动设备节省宝贵的电池电量。
歌剧:卡拉坎引擎
实际上,这意味着每当将要编译的脚本程序的源代码与最近编译的其他程序的源代码相同时,我们都会重用编译器的先前输出并完全跳过编译步骤。这种缓存在典型的浏览场景中非常有效,在这种情况下,从同一站点加载一页又一页,例如来自新闻服务的不同新闻文章,因为每个页面通常加载相同的、有时非常大的脚本库。
因此 JavaScript 在页面重新加载时被缓存,对同一脚本的两个请求不会导致重新编译。
火狐:SpiderMonkey 引擎
SpiderMonkey 使用Nanojit
JIT 编译器作为其原生后端。编译机器码的过程可以在这里看到。简而言之,它似乎在加载脚本时重新编译它们。但是,如果我们仔细查看内部结构,Nanojit
我们会发现jstracer
用于跟踪编译的更高级别的 monitor可以在编译期间过渡到三个阶段,从而为Nanojit
:
跟踪监视器的初始状态是正在监视。这意味着蜘蛛猴正在解释字节码。每次spidermonkey 解释一个向后跳转字节码时,监视器都会记录跳转目标程序计数器(PC) 值被跳转到的次数。此数字称为 PC 的命中计数。如果特定 PC 的命中计数达到阈值,则该目标被认为是热的。
当监视器确定目标 PC 很热时,它会在片段的哈希表中查找是否存在包含该目标 PC 的本机代码的片段。如果找到这样的片段,它就会转换到执行模式。否则它会转换到录制模式。
这意味着对于hot
代码片段,本地代码会被缓存。这意味着不需要重新编译。不清楚这些散列的本机部分是否在页面刷新之间保留。但我会假设它们是。如果有人能为此找到支持证据,那就太好了。
编辑:它已经指出,Mozilla开发鲍里斯Zbarsky曾表示,壁虎不缓存编译脚本还。取自this SO answer。
Safari : JavaScriptCore/SquirelFish 引擎
我认为这个实现的最佳答案已经由其他人给出了。
我们目前不缓存字节码(或本机代码)。这是
我们考虑过的一个选项,然而,目前,代码生成是
JS 执行时间的一个微不足道的部分 (< 2%),所以我们目前不追求
这个。
这是由Safari 的首席开发人员Maciej Stachowiak编写的。所以我认为我们可以认为这是真的。
我找不到任何其他信息,但您可以在此处阅读有关最新SquirrelFish Extreme
引擎速度改进的更多信息,或者如果您喜欢冒险,请在此处浏览源代码。
IE : 脉轮引擎
该领域目前没有关于 IE9 的 JavaScript 引擎 (Chakra) 的信息。如果有人知道任何事情,请发表评论。
这是相当非正式的,但对于IE的旧的引擎实现,埃里克利珀(JScript中的MS开发商)在博客中回应称这里是:
JScript Classic 就像一种编译语言,在任何 JScript Classic 程序运行之前,我们都会对代码进行全面的语法检查,生成完整的解析树,并生成字节码。然后我们通过字节码解释器运行字节码。从这个意义上说,JScript 与 Java 一样“已编译”。不同之处在于 JScript 不允许您保留或检查我们的专有字节码。此外,字节码比 JVM 字节码高级得多——JScript Classic 字节码语言只不过是解析树的线性化,而 JVM 字节码显然旨在在低级堆栈机器上运行。
这表明字节码不会以任何方式持久化,因此不会缓存字节码。
据我所知,只有 Opera 缓存解析的 JavaScript。请参阅此处的“缓存编译程序”部分。
这是值得什么,谷歌飞dart通过“快照”明确铲球这个问题-我们的目标是通过加载代码的preparsed版本,以加快初始化和加载时间。
InfoQ 有一篇很好的文章 @ http://www.infoq.com/articles/google-dart
我认为正确的答案是“并非总是如此”。据我了解,浏览器和服务器都在确定缓存内容方面发挥作用。如果您真的需要每次都重新加载文件,那么我认为您应该能够从 Apache 内部进行配置(例如)。当然,我认为用户的浏览器可以配置为忽略该设置,但这可能不太可能。
所以我想在大多数实际情况下,javascript 文件本身被缓存,但每次页面加载时都会动态重新解释。