【问题标题】:How to preload JavaScript and CSS files in the background, to have them ready in the browser cache when the user goes to the main page?如何在后台预加载 JavaScript 和 CSS 文件,以便在用户转到主页时将它们准备好在浏览器缓存中?
【发布时间】:2010-09-02 14:16:03
【问题描述】:

我想从登陆页面预加载一个 JS 文件和一个 CSS 文件来优化主站点的加载,在登陆转换之后。我一直在寻找有关此的信息,最后尝试使用以下方法完成此操作:

    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'jsUrl');
    xhr.send('');
    xhr = new XMLHttpRequest();
    xhr.open('GET', 'cssUrl');
    xhr.send('');

使用 Firefox 非常棒,但使用 Chrome 时,XHR 调用似乎缓存在与 css 和 js 文件不同的缓存中。 我们不使用 JQuery,着陆页必须是轻量级的(负载更少,转化率更高)。

您对解决原始问题的另一种方法有什么建议吗? (预加载组件)

你知道如何让 Chrome 缓存这些请求吗?

【问题讨论】:

    标签: cross-browser xmlhttprequest preload browser-cache web-optimization


    【解决方案1】:

    这是一个在大容量网站中经过测试的解决方案。

    首先,为避免登录页面资源与带宽的预加载资源之间的竞争,您可以使用 javascript 延迟加载:

    var prevOnLoad=window.onload;
    function onLoadPreloadComponents() {
        if(prevOnLoad) {
            try{
               prevOnLoad();
            }catch(err){
            }
        }
        preloadSiteComponents();
    }
    
    window.onload=onLoadPreloadComponents;
    

    这不是我解决此问题的方法,因为在我的用例中,最终加载着陆时会发出一个 Flash 事件(使用 Flash 到 JS 桥接)信号。但是前面的代码也必须有效。当浏览器触发 load page 事件时,此函数将执行之前的 onLoad 代码和预加载。

    我在要加载 iframe 的位置放置了一个空的 div 硬币容器。

    <div id="mainSiteComponentsContainer" style="display: none;">
    </div>
    

    而功能码是:

    function preloadSiteComponents() {
        try{
            document.getElementById('mainSiteComponentsContainer')
                .innerHTML=
                    "<iframe src=\"http://www-components.renxo-cdn.net/preload-site-components-data-url-scheme-version-1.2.84-css-1.0.53.html\" frameborder=\"no\" height=\"0px\" width=\"0px\"></iframe>";
        }catch(err) {
        }
    }
    

    如您所见,iframe 的链接 url 是动态的,它会在不同的平台版本(不同的部署)之间变化,以避免在新部署中出现不需要的浏览器缓存。

    iframe 中的 HTML 可能是这样的(例如):

    <html class=" gecko win js" xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <meta content="noindex,nofollow" name="robots">
            <script src="http://www-components.renxo-cdn.net/scripts/lib-1.2.84.js" type="text/javascript">
            <link href="http://www-components.renxo-cdn.net/styles/skin-data-url-scheme-1.0.53.css" media="all" type="text/css" rel="stylesheet">
        </head>
        <body> </body>
    </html>
    

    在这里您可以看到指向我要预加载的组件的链接。 最后,div 硬币容器将拥有 iframe。 onLoad 事件后:

    <div id="mainSiteComponentsContainer" style="display: none;">
        <iframe width="0px" height="0px" frameborder="no" src="http://www-components.renxo-cdn.net/preload-site-components-data-url-scheme-version-1.2.84-css-1.0.53.html">
            <html class=" gecko win js" xmlns="http://www.w3.org/1999/xhtml">
                <head>
                    <meta content="noindex,nofollow" name="robots">
                    <script src="http://www-components.renxo-cdn.net/scripts/lib-1.2.84.js" type="text/javascript">
                    <link href="http://www-components.renxo-cdn.net/styles/skin-data-url-scheme-1.0.53.css" media="all" type="text/css" rel="stylesheet">
                </head>
                <body> </body>
            </html>
        </iframe>
    </div>
    

    您可以看到有效的解决方案here

    使用 Firebug 查看此组件的延迟加载。

    【讨论】:

    • 这种方法的问题是该站点确实可以阻止从某些 url 加载。这样,一旦页面加载,您就不能对这些 url 使用 AJAX。
    【解决方案2】:

    胡思乱想:

    也许您可以在您的登录页面中包含一个隐藏的 IFrame,它会加载一个除了包含您的 javascript 和 CSS 文件之外什么都不做的页面。如果您在 javascript 中触发该 IFrame 的加载,则它不应阻止登录页面的加载或呈现,但浏览器将像加载任何其他页面一样加载脚本和 css 文件。

    【讨论】:

    • 这是个好主意,但起初我不想动态添加 iframe,因为它看起来比两个 XHR 调用更复杂。我需要动态地执行此操作,以便组件不会与登录页面的横幅下载竞争。谢谢。
    • 您不必动态添加 IFrame。它可以在页面的源代码中,只是最初不要指向任何东西。只需通过 javascript 设置其 src(或任何属性)即可启动缓存页面。
    • Javascript / DHTML 不需要隐藏 iframe。只需在静态 iframe 上使用 style="visibility:hidden;height:0px;width:0px" 并将其放在页面的最后。固定尺寸将防止它阻塞渲染,并且它在页面中的位置应确保其资源在其他页面元素之后加载。
    【解决方案3】:

    尚未尝试过,但将其添加到着陆 HTML 的底部应该可以:

    <!-- Preload -->
    <img src="/path/to/preload.js" style="display:none">
    <img src="/path/to/preload.css" style="display:none">
    

    浏览器实际上并不关心资源不是图像,它无论如何都应该获取和缓存它们。浏览器通常按页面顺序加载资源,因此您不会延迟其他元素,并且使用 display:none 您可能也不会阻止渲染。

    缺点是您不会预加载 CSS 或 @imports 中定义的图像,除非您手动预加载它们。

    【讨论】:

    • 我想我会对此进行测试,尽管我看到一个资源建议“display:none”不会在某些浏览器中加载,这听起来很合理。
    • 我读到有些浏览器有不同的缓存区来存储不同类型的资源。例如,浏览器可以有一个用于图像的缓存区和另一个用于 JS 的缓存区。所以,这个想法很好,但可能不适用于所有主要浏览器。
    • @romkyms: style="visibility:hidden;width:0;height:0" 应该实际下载。 @Jonathan:我认为这不太可能,我想不出好的技术理由来划分这样的缓存资源。
    猜你喜欢
    • 1970-01-01
    • 2014-02-03
    • 2011-09-12
    • 2010-09-12
    相关资源
    最近更新 更多