JavaScript UI, requirejs and the Flash Of Unstyled Content

JavaScript UI, requirejs and the Flash Of Unstyled Content

本文关键字:Flash Of Unstyled Content the and UI requirejs JavaScript      更新时间:2023-09-26

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

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

什至不知道FOUC是什么,直到我开始使用requirejs。这很明显,所以目前我正在避免它:

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

这是我拥有的最好的,我发现的所有关于该主题的在线资源都推荐了类似的东西。

我的问题是,考虑到我谈论的是仅影响 UI 的脚本,需求值得吗?正如我所说,我想继续使用其资源回退系统,但整个"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>

主要.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']);

脚本先于</body>的赞美的原因是因为它们阻止了解析。

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

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

但是,此策略存在问题。也就是说,在正文末尾堆积脚本标签不允许良好的(任何?)依赖关系管理。这是创建requirejs的主要原因之一(以及其他目的,如代码封装,版本控制/回退,模板插件等)。

您将 requirejs 用于一个有效的目的,否则管理起来会很痛苦,所以我肯定会说 requirejs 在这种情况下是"值得的"。

至于你对"FOUC修补"似乎适得其反的评论,我不确定你为什么会这样。考虑一下补丁为您提供的内容:流畅加载的 UI 和未阻止的 HTML。在脑海中抛出阻塞脚本当然可能是一个有效的决定,但前提是页面上的大部分内容都取决于它们是否尽快加载。这种情况很少见(实际上在演示/开发用途之外是一种反模式)。

考虑

用户体验,特别是考虑有些老化的智能手机的慢速连接/慢速JS解析/执行速度。异步加载不会让这些用户停留在空白屏幕上 3-5+ 秒,而是可以让您感知的加载时间更快。然后,当脚本最终可用时,UI 的花里胡哨可以与您的 FOUC 补丁一起显示。

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

作为外部 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秒钟,有时在蓝色之前看到红色的闪烁。我不确定这是为什么。

阻止脚本?

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