Javascript 确保在内容脚本之前加载AMD模块 概述

Javascript 确保在内容脚本之前加载AMD模块 概述,javascript,requirejs,js-amd,Javascript,Requirejs,Js Amd,我正在尝试将一个站点转换为。该站点的大部分依赖于单独模块中定义的全局变量(主要是实用方法)。这给开发人员带来了严重的困难,因为模块并不总是在内容脚本之前加载 理想结果 我想要一种方法来防止在某些模块加载之前解析这些页面内脚本,这样团队成员就可以在时间允许的情况下慢慢删除它们 研究 我注意到有一种方法可以在同步模式下加载一些脚本 我找不到任何与RequireJS2+类似的东西,尽管我认为它过去是受支持的。(我的吉特福不够强壮。) 警告 虽然我知道在开发模式下可以通过脚本标签加载模块,但我不希望这样

我正在尝试将一个站点转换为。该站点的大部分依赖于单独模块中定义的全局变量(主要是实用方法)。这给开发人员带来了严重的困难,因为模块并不总是在内容脚本之前加载

理想结果 我想要一种方法来防止在某些模块加载之前解析这些页面内脚本,这样团队成员就可以在时间允许的情况下慢慢删除它们

研究
  • 我注意到有一种方法可以在同步模式下加载一些脚本
  • 我找不到任何与RequireJS2+类似的东西,尽管我认为它过去是受支持的。(我的吉特福不够强壮。)
  • 警告
  • 虽然我知道在开发模式下可以通过脚本标签加载模块,但我不希望这样,因为这需要在两个地方列出模块
  • 我试过的 所以我尝试生成一个轮询解决方案,它运行一个粗略计时的while循环,然后中断 出去运行回调。以下是我的实现:

    (function (global) { // Making this into a global, so I don't need to wait for the loader's extra timeout. 
        var undef;
    
        /**
         * Simple args getter.
         *
         * @param {*} arg Used if defined.
         * @param otherwise Used if arg is not defined.
         * @return {*}
         */
        var arg = function (arg, otherwise) {
            return arg !== undef ? arg : otherwise;
        };
    
        /**
         * Locks up the main thread as soon as the current thread completes.
         *
         * @param {number} time
         */
        var lock = function (time) {
            setTimeout(function () {
                var start = +(new Date),
                    current = 0;
                console.log('Locking thread at %d', start);
    
                start += time;
                while (start > (current = +(new Date))) {
                    console.log('tick');
                }
    
                console.log('Unlocking thread at %d', current);
            }, 0);
        };
    
        /**
         * Locks up the main thread until a condition is met, releasing it
         * momentarily to allow other "threads" to advance.
         *
         * @param {Function} condition
         * @param {number} [checkInterval=50] How long
         */
        var lockThreadUntil = global.lockThreadUntil = function (condition, checkInterval, releaseDuration) {
            checkInterval = arg(checkInterval, 50);
            releaseDuration = arg(releaseDuration, 0);
    
            var id = setInterval(function () {
                if (!condition()) {
                    lock(checkInterval);
                } else {
                    clearInterval(id);
                }
            }, releaseDuration);
        };
    
        define(function () {
            return lockThreadUntil;
        });
    })(this);
    
    在第页(我测试了创建全局的模块):

    在内容内脚本中:

    console.log('Was needed!');
    
    我希望这能在给脚本加载时间的同时,使DOM进步很少,从而允许它在内容脚本之前进入解析堆栈。不幸的是,内容中的脚本似乎是先启动的

    拉普 我愿意接受建议。我考虑的选项包括(两个看起来都很糟糕):

    • 咬紧牙关,使用脚本标签
    • 吞下RequireJS加载方法并用xhr实现替换

    我建议对遗留代码使用RequireJS功能,并允许RequireJS加载所有内容(包括您的in-DOM脚本标记)。Shim允许您创建传统浏览器全局文件的AMD版本。shim配置允许您指定shimed模块之间的依赖关系,以及标识其导出的全局浏览器

    假设您在DOM中将传统文件AB作为脚本标记,其中B依赖于(并且脚本标记位于)文件A之后。也就是说AB都依赖于AMD格式的实用程序模块Lib。从DOM中删除AB的脚本标记,并添加一个类似于以下内容的require js配置块:

    requirejs.config({
      shim: {
        'A': ['Lib'],
        'B': ['Lib', 'A']
      }
    });
    
    这将使RequireJS在解析AMD模块库后加载遗留脚本。我简化了这里的示例,假设您的所有库AMD模块都可以通过单个超级模块Lib来满足需求

    通读一下,因为它还解释了如何告诉requirejs您的模块导出了什么(以全局对象的形式),从而使垫片更加完整

    警告:这只在开发模式下有效。如果您尝试运行RequireJS优化器,结果将不起作用,因为填充模块依赖于标准AMD模块(如上所述)


    此外,此解决方案还需要在必要时使用shim config中的依赖项手动调整每个in-DOM脚本标记的顺序(就像我通过使B依赖于A使B跟随A)。在过去,你可以使用RequireJS订单!插件,但它是在RequireJS2。这并不是一件坏事,因为它可以帮助您解决脚本之间的真正依赖关系,并使将来完全转换到AMD变得更容易

    我很确定这不会解决我的问题。在DOM脚本加载后第一个模块不会加载吗?@Josh,对不起,我不清楚。我建议用
    shim
    ed模块定义替换DOM中的脚本标记,并允许RequireJS管理加载所有内容。您不必触摸非AMD脚本的代码,但必须从DOM中删除脚本标记。我编辑了我的答案以便更清楚。我不确定垫片给了我什么。脚本在内容中,所以我需要在内容之前加载它们的DEP,这在没有同步xhr或阻止浏览器dom解析器的情况下似乎是不可能的。我认为错误的沟通是依赖于AMD模块的脚本不在单独的文件中。(我希望是这样,但遗留代码是遗留的。)
    requirejs.config({
      shim: {
        'A': ['Lib'],
        'B': ['Lib', 'A']
      }
    });