JavaScript UI,requirejs和Flash Of Unstyled Content

时间:2013-09-06 11:22:10

标签: javascript jquery-ui requirejs fouc

我目前正在使用requirejs,主要是因为它的资源加载器。我喜欢它管理后备的方式。

我的javascript应用程序根本不复杂,只是一些jQuery UI小部件和其他小调整。

在我开始使用requirejs之前,我甚至不知道FOUC是什么。这是非常引人注目的,所以目前我正在避免它:

var protect_from_FOUC = function(element) {
    if(typeof element === 'string') {
        element = document.querySelector(element);
    }
    element.classList.add('ui-helper-hidden');
};

<div id="main" class="main_block" role="main">
<!-- a block affected by FOUC -->
</div>
<script>protect_from_FOUC('#main');</script>

并在我的脚本中:

require(['jquery', 'jquery-ui' /*, ...*/], function($) {

var recover_from_FOUC = function(element) {
    $(element).show({
        effect: 'blind',
        duration: 200
    }).removeClass('ui-helper-hidden');
};

$(document).ready(function() {

    // Themed buttons:
    $(':button, :submit, :reset, .button').button();
    // ... Some other similar changes
    recover_from_FOUC('#main');

});  // document.ready

});  // require

这是我所拥有的最好的,我发现的主题上的所有在线资源都推荐了这些内容。

我的问题是,考虑到我在讨论的是仅影响用户界面的脚本, requirejs值得吗?正如我所说,我想继续使用它的资源回退系统,但整个“FOUC补丁的东西”似乎适得其反......

每个jQuery UI示例都包含头部中的脚本,但是互联网中的每个人都建议在关闭正文之前或使用异步加载程序包含脚本。 此建议仅适用于“非UI”脚本吗?

在这种情况下最好的是什么?

请注意,即使关闭,这不仅仅是另一个“如何避免FOUC问题”。

编辑:添加我的页面中包含的外部文件和我的require.config

<!-- This is in my head right below the meta tags and exactly in this order -->
<link rel="shortcut icon" href="images/favicon.ico"/>
<!-- Keep before the site css to allow overriding jquery's style -->
<link rel="stylesheet" href="style/lib/jquery-ui/ui-lightness/jquery-ui.css"/>
<link rel="stylesheet" href="style/lib/chosen/chosen.css"/>
<link rel="stylesheet" href="style/lib/icheck/minimal/yellow.css">
<link rel="stylesheet" href="style/reset.css">
<link rel="stylesheet" href="style/style.css"/>

<!-- Here I have the definition of `protect_from_FOUC` in an inline script -->

<script data-main="js/main" src="js/lib/require.js"></script>

在main.js中:

require.config({
    paths: {
        // Common:
        'jquery': ['//code.jquery.com/jquery-2.0.3.min', 'lib/jquery'],
        'sugar': ['//cdnjs.cloudflare.com/ajax/libs/sugar/1.3.9/sugar.min', 'lib/sugar'],

        // UI:
        'jquery-ui': ['//code.jquery.com/ui/1.10.3/jquery-ui.min', 'lib/jquery-ui'],
        'autosize': ['//cdnjs.cloudflare.com/ajax/libs/autosize.js/1.17.1/autosize-min', 'lib/jquery.autosize'],
        'chosen': ['//cdnjs.cloudflare.com/ajax/libs/chosen/0.9.15/chosen.jquery.min', 'lib/chosen.jquery'],
        'icheck': ['lib/jquery.icheck'],

        // django i18n:
        'gettext': [translations_url + '?noext']
    },
    shim: {
        'jquery-ui': {
            deps: ['jquery']
        },
        'autosize': {
            deps: ['jquery']
        },
        'chosen': {
            deps: ['jquery']
        },
        'icheck': {
            deps: ['jquery']
        }
    }
});

require(['style', 'interaction']);

2 个答案:

答案 0 :(得分:3)

脚本pa-of before-before - </body>的原因是因为它们阻止了解析。

这很糟糕,特别是考虑到你的用例,你的网页上可能有很多内容等待解析和呈现,而不是你通过Javascript包含的内容。

包含脚本最后允许直接包含在HTML中的所有内容进行解析和渲染,而无需等待任何脚本(以及它们的整个请求周期 - >解析 - >执行)。

然而,这个策略存在问题。那就是在你身体末端堆积脚本标签不允许良好的(任何?)依赖关系管理。这是创建requirejs的主要原因之一(除了代码封装,版本控制/后备,模板插件等)。

你使用requirejs是为了一个有效的目的,否则会很难管理,所以我肯定会说在这种情况下requirejs是“值得的”。

至于你对“FOUC修补”的评论似乎适得其反,我不确定你为什么会这样认为。考虑补丁为您提供的内容:平滑加载UI和未阻止HTML 。在头部抛出阻塞脚本当然是一个有效的决定,但只有当页面上的大多数内容依赖于它们尽可能快地加载时。这种情况很少发生(实际上是演示/开发之外的反模式)。

考虑用户体验,特别是考虑缓慢的连接/缓慢的JS解析/执行有些老化的智能手机的速度。而不是将这些用户保持在空白屏幕上3-5 +秒,异步加载可以让您的感知加载时间更快。当脚本最终可用时,可以使用您的FOUC补丁显示UI铃声和口哨声。

因此,您可以使用异步脚本提供看似快速的页面加载,并在加载时使用JS进行增强,同时使用requirejs获取依赖关系管理/智能资源回退。听起来不错。

答案 1 :(得分:1)

作为外部CSS阻止渲染的后续示例。慢速外部样式表将阻止后续页面的渲染(在我测试过的Chrome和FF中)。

<!doctype html>

<html>

<head>
    <style>body { background: white; }</style>
    <link rel="stylesheet" type="text/css" href="http://deelay.me/0/http://rawgithub.com/gitgrimbo/6487200/raw/red.css">
    <link rel="stylesheet" type="text/css" href="http://deelay.me/5000/http://rawgithub.com/gitgrimbo/6487200/raw/blue.css">
</head>

<body>
    <h1>Top header</h1>

    <script>console.log(new Date()); document.write(new Date());</script>

    <h1>Bottom header</h1>
</body>

</html>

但是如果你将两个<link>元素移动到页面主体中(作为<body>的第一个元素),那么我可以在Chrome和FF中看到...

在Chrome中,行为与<link>元素位于文档<head>中的行为相同。

在FF中,您有时会在蓝色前看到红色背景5秒,有时在蓝色之前会看到闪烁的红色。我不确定为什么会这样。

阻止脚本?

由于CSS延迟,Chrome和FF似乎也阻止了<script>块的运行。不知道为什么会这样。