【问题标题】:Load requireJS module inline the HTML body?在 HTML 正文中加载 requireJS 模块?
【发布时间】:2012-10-02 19:50:08
【问题描述】:

我正在将 RequireJS 集成到 CMS 中,因此我将其放在页面模板的底部:

<html>
<body>
  {Placeholder1}
  <script src="scripts/require.js" data-main="scripts/main"></script>
  {Placeholder2}
</body>
</html>

然后在每个页面上,我想创建一个利用 RequireJS 的函数。所以我试着把它放在页面底部:

<html>
<body>
    <h1>Home</h1>
    <div class="slider">Slider content</div>

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

    <script type="text/javascript">
      require([
        'jquery',
        'utils',
        'slider'
      ], function ($, utils, slider) {
        slider.start();
      });
    </script>
</body>
</html>

但我在 jquery、utils 和滑块 js 文件上得到 404。似乎它没有读取我拥有的 main.js 配置:

require.config({
    paths: {
        jquery: 'libs/jquery-1.8.1.min',
        utils: 'libs/utils',
        slider: 'libs/jquery.slider.min'
    },
    shim: {
        slider: ['jquery']
    }
});

require([ 'utils' ], function (utils) {
    utils.init();
});

我尝试在页眉中加载 RequireJS 和 main,但结果不一致。有时 jquery、utils 和 slider 会及时加载,有时则不会。就好像页面底部的内联“require”不知道页面上的主要 RequireJS 或依赖规则,但是我的断点在 main.js 中命中,所以我知道它正在被调用。是因为 main.js 是异步加载的,但是页面底部的内联“require”块是在页面渲染时加载的?我该如何解决这个问题?

我之前成功使用过 RequireJS,但没有使用 CMS。我总是使用“定义”并且总是异步调用模块,但从来不需要像这样内联调用 RequireJS 函数。有关正确方法的任何想法?

【问题讨论】:

    标签: asynchronous javascript requirejs js-amd


    【解决方案1】:

    这里重要的是在请求任何模块之前设置配置选项。正如您正确识别的那样,存在竞争条件,这意味着您的 main.js 中的配置选项没有及时加载。最简单的方法是在加载 require.js 脚本之前将配置选项内联。

    <script>
    var require = {
        baseUrl: <?= $someVar ?>,
        paths: {
            // etc
        }
    }
    </script>
    <script src="scripts/require.js" data-main="scripts/main"></script>
    

    在页面下方:

    <script>
        require([
            'jquery',
            'utils',
            'slider'
          ], function ($, utils, slider) {
            slider.start();
          });
    </script>
    

    另见How does RequireJS work with multiple pages and partial views?

    【讨论】:

    • 这个设置的一个问题是当脚本/主文件包含多个模块时资源可能会被加载两次(通常是使用 r.js 优化器的情况)。如果这是一个不使用 require 定义的文件,这尤其是一个问题。假设scripts/main 文件包含LESS JS 模块。此外,假设内联 require 调用也需要这个模块。现在,如果在加载主脚本之前访问内联调用(通常是这种情况),模块将被获取两次。如果内容不是 AMD 模块,这可能会导致错误!
    【解决方案2】:

    似乎正在发生的事情是 main.js 正在异步加载,而内联 require 被立即调用。这就是结果不一致的原因。解决方案是不使用 data-main 属性,而是通过 require.js 脚本标签下的脚本标签调用 main.js 文件。

    您仍然可以通过在其中执行以下操作从加载的 main.js 文件中确定 baseUrl:

    //DETERMINE BASE URL FROM CURRENT SCRIPT PATH
    var scripts = document.getElementsByTagName("script");
    var src = scripts[scripts.length-1].src;
    var baseUrl = src.substring(src.indexOf(document.location.pathname), src.lastIndexOf('/'));
    
    //CONFIGURE LIBRARIES AND DEPENDENCIES VIA REQUIREJS
    require.config({
        baseUrl: baseUrl,
    ....
    

    【讨论】:

    • 或者您可以将内联代码放入 main.js 文件中。或者您可以将路径定义放入内联代码块中。
    • 使用 RequireJS 的原因之一是避免对全局变量的依赖,所以要避免这样做。
    • @Simon,谢谢您的建议。使用 CMS 系统很难避免这种情况。在我看来,几乎所有的 CMS 都已经过时了。
    • 添加了一个答案,因为它很长;)
    • 这把我逼疯了!谢谢你。愚蠢的部分是:我在一年前就遇到了这个确切的问题,但没有马上想到。
    猜你喜欢
    • 1970-01-01
    • 2012-09-09
    • 1970-01-01
    • 1970-01-01
    • 2018-01-06
    • 2014-12-15
    • 1970-01-01
    • 2013-08-24
    • 2013-12-05
    相关资源
    最近更新 更多