如何在浏览器中使用UMD而不需要任何额外的依赖。

43

假设我有一个UMD模块,就像这样(保存在'js/mymodule.js'):

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ?     factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (factory((global.mymodule = global.mymodule || {})));
}(this, function (exports) { 'use strict';
    function myFunction() {
        console.log('hello world');
    }
}));

我该如何在这样的HTML文件中使用此模块?(不使用requirejs、commonjs、systemjs等)

<!doctype html>
<html>
<head>
    <title>Using MyModule</title>
    <script src="js/mymodule.js"></script>
</head>
<body>
<script>
/* HOW TO USE myFunction from mymodule.js ??? */
</script>
</body>
</html>

非常感谢您提前的任何帮助。

5个回答

27

好的,所以您正在没有RequireJS、CommonJS、SystemJS等环境下运行。

关键代码是factory((global.mymodule = global.mymodule || {})),它完成了一些操作:

  1. 如果global.mymodule为真值,则相当于

    global.mymodule = global.mymodule // A noop.
    factory(global.mymodule)
    
  2. 否则,它等同于:

  3. global.mymodule = {}
    factory(global.mymodule)
    

在工厂内部:你的工厂应该通过将exports赋值来出口你想要从模块中出口的内容。所以,通过执行exports.myFunction = myFunction来导出myFunction

在工厂外部:在外部,导出的值将位于已导出到全局空间的mymodule上。例如,当你想要使用myFunction时,你可以执行mymodule.myFunction(...)

如果这不清楚,请注意,代码中的工厂是以function (exports) {开头的函数,你已经正确地放置了myFunction


5
这是最佳答案,提供了许多原本被埋藏和隐藏的信息。似乎每个人都期望你会使用RequireJS、SystemJS、Webpack等工具。 - user9903
1
我在尝试使用由Rollup生成的捆绑UMD文件时来到了这个页面。很棒的问题,也有很棒的答案... - Marco Faustinelli
3
我不熟悉UMD或者"factory"是什么("inside the factory"和"outside the factory"的含义是什么?)- 我不确定如何实施这个答案。我需要哪些代码(无论是可以复制粘贴的,还是可以用作起点的),我需要自己重新实现function require(moduleName)吗? - Dai
有没有什么窍门可以让打包工具做到这一点?特别是 Vite? - undefined

21

简单回答:如果您使用常规的UMD,它应该在window['mymodule'](或window.mymodule)或库所使用的任何名称中可用。


我正在将一个UMD模块加载到我的页面中(通过在另一个脚本内创建一个<script async="" src="">元素)。新脚本加载后(即HTMLScriptElement.load事件触发后),没有定义window['myScriptName']成员。这是否意味着我没有使用真正的UMD模块,或者window['mymodule']只是所有UMD模块子集中使用的约定?它们在哪里添加自己? - Dai
2
@Dai 可能可以这样做。打开您的模块代码,使用“漂亮打印”格式化它,然后查找文件的开头或结尾,可能会出现 exportsglobal. 等等。可能您的库是用另一个名称导出的,或者在 commonJsStrict 对象内部或其他地方导出。 - Vladimir Tolstikov
我想再举一个例子:在您的页面中包含 rxJS,例如 <script src="https://unpkg.com/rxjs@7.1.0/dist/bundles/rxjs.umd.min.js"></script>。之后,您应该能够使用 rxJS,例如 rxjs.range(1,10).subscribe(x => console.log(x))。请注意,rxjs.range 是该方法的完全限定引用。这可能是另一种情况下的导入方式:import { range } from "rxjs";。此外,请注意,window['bla'] 引用全局作用域中的变量 bla。因此,您也可以使用 window['rxjs'].range - mihca
2
如果您不确定模块的名称,那么您可能需要打开 DevTools 并检查 window 对象。 在 DevTools 中输入 window.,则自动完成应显示全局范围内的名称。其中一个名称应该是您的模块。 - mihca

8

当前形式下,你无法从myModule.js中使用myFunction()。因为myModule.js没有任何暴露(导出)的内容。你需要首先在myModule.js中添加以下代码:


exports.myFunction = myFunction;

这样你的模块代码就会变成:


(function(global, factory) {
  typeof exports === 'object' 
  && typeof module !== 'undefined' 
  ? factory(exports) :
    typeof define === 'function' 
    && define.amd 
    ? define(['exports'], factory) :
      (factory(
          (global.mymodule = global.mymodule || {})
        )
      );
}(this, function(exports) {
  'use strict';

  function myFunction() {
    console.log('hello world');
  }
  // expose the inner function on the module to use it
  exports.myFunction = myFunction;
}));


现在当你在你的 .html 文件中运行这段代码时,浏览器会创建一个名为'mymodule'的全局对象并拥有方法'myFunction'。
您可以在您的 .html 文件中调用此方法:
myModule.myFunction();

完整的HTML文件如下:

完整的 .html 文件将是:


    <!doctype html>
    <html>
    <head>
        <title>Using MyModule</title>
        <script src="js/mymodule.js"></script>
    </head>
    <body>
    <script>
    /* HOW TO USE myFunction from mymodule.js ??? */
    /* Answer: */
    mymodule.myFunction();
    </script>
    </body>
    </html>




-2

这是一个如何渲染UMD React组件的示例:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <script src="https://unpkg.com/react@16.1.1/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@16.1.1/umd/react-dom.development.js"></script>
  <script src="my-component.js"></script>
  <title>React App</title>
</head>
<body>
  <div id="root"></div>
  <script>
    ReactDOM.render(
      React.createElement(MyComponent),
      document.getElementById('root')
    );
  </script>
</body>
</html>


1
我对这个答案进行了负评,因为问题提出者没有询问有关React的内容,而React自带其自身的模块助手逻辑。 - Dai

-4

amd模块格式旨在异步加载,因此您不能直接在


6
抱歉,您混淆了UMD和AMD。 - Marco Faustinelli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接