需要JS:检测脚本中的data-main

时间:2017-02-28 19:26:13

标签: javascript requirejs

在require js中,是否可以判断脚本是否作为data-main加载?例如,我有一个可以用作data-main或模块的脚本:

// script.js
if (this_is_data_main()) {
   console.log('do something main');
} else {
   console.log('do something else');
}

我可以通过将信息写为全局变量来考虑黑客攻击,例如:

//index.html
<!doctype html>
...
<script> window.app.main = 'script'; </script>
<script data-main="script.js" src="require.js"></script>

更新了script.js:

// script.js
if (window.app && window.app.main === 'script') {
   console.log('do something main');
} else {
   console.log('do something else');
}

1 个答案:

答案 0 :(得分:1)

摘要

RequireJS不提供&#34;官方&#34;做你想做的事。这是一种非官方的方式,很脆弱。但是,我认为您不应该依赖于检测脚本是否通过data-main加载。

长解释

RequireJS没有直接的方法去做你想做的事情。如果您阅读RequireJS的代码,您会看到它显示data-main并最终将其附加到当前配置的deps选项。除了一些路径计算之外,没有其他处理。 (路径计算详细信息对于您在此处提出的较大问题并不重要,因此我会跳过这些详细信息。)当RequireJS完成data-main时,您问题中的代码大致相同相当于:

<script src="require.js"></script>
<script>
  require.config({
    deps: ["script"]
  });
</script>

可以检查deps并查看您的模块是否在那里。您在此位置deps找到require.s.contexts._.config.deps。顺便说一句,下划线是默认上下文的名称。但正如您可以通过这个奇怪的位置告诉我这是使用私有API,可能会随着RequireJS的未来版本而改变。这是一个问题。另一个问题是,如果require.config再次被deps值调用,则deps的第一个值将被覆盖。所以这将取决于具体情况而失败。我的味道太脆了。

最终,我不会依赖于模块行为取决于模块是否通过data-main列出而不是其他方式加载。我上面显示的是使用data-main的等效内容。这是另一个:

<script src="require.js"></script>
<script>
  require(["script"]);
</script>

我可以列出一堆其他变体。 关键是从模块加载的角度来看data-main是一种便利。它不应该被赋予更多的意义而不是方便。我已经在各种情况下使用data-main和上面显示的两个替代方案。上下文通常会确定哪些选项是可行的或可取的。例如,我已经在SO上回答了问题,其中OP在其自己的代码运行时已经加载了RequireJS的上下文中运行。所以他们就不会甚至能够依赖data-main。 (例如,对于在较大框架中充当插件的组件,可能会发生这种情况:框架使用RequireJS,因此它使RequireJS可用于插件,但插件仅限于添加script元素。)

依赖data-main的另一个问题是这是一个RequireJS的事情。可以使用其他工具(如Webpack)加载AMD模块,也可以使用其他工具(如Webpack)加载AMD模块。 如果您的代码取决于data-main,则在使用其他工具时,它无法正常工作。

您可以让主模块导出一个初始化函数,该函数根据用户需要选择并配置模块。

如果您希望在加载模块后立即启动并且不必调用任何函数,那么在不污染全局JavaScript空间的情况下执行此操作的一种方法是让您的模块查找着名的script具有类型id的元素(特定class或特定application/json)。由于它是JSON,因此浏览器不会执行它,但是需要它的脚本可以访问它。它将包含模块读取配置的JSON对象。 This question处理如何从脚本中获取JSON。