How to use UMD in browser without any additional dependencies
Asked Answered
L

5

45

Suppose I have an UMD module like this (saved in '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');
    }
}));

How can I use this module in an HTML file like this? (without requirejs, commonjs, systemjs, etc...)

<!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>

Many thanks in advance for any help.

Lipps answered 28/7, 2016 at 13:40 Comment(0)
R
27

Ok, so you are running in an environment without RequireJS, CommonJS, SystemJS, etc.

The key line is factory((global.mymodule = global.mymodule || {})) this does a few things:

  1. If global.mymodule truthy, then it is equivalent to

    global.mymodule = global.mymodule // A noop.
    factory(global.mymodule)
    
  2. Otherwise it is equivalent to:

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

Inside the factory: Your factory you should export what you want to export from your module by assigning to exports. So you'd export myFunction by doing exports.myFunction = myFunction.

Outside the factory: Outside, the exported values will be on mymodule which was exported to the global space. When you want to use myFunction, for instance, you do mymodule.myFunction(...).

In case that's not clear. The factory in your code is the function that starts with function (exports) {, where you've correctly put myFunction.

Rote answered 28/7, 2016 at 16:37 Comment(4)
This is the best answer and gives a lot of information that is otherwise buried and hidden. Everyone seems to expect that you will use RequireJS, SystemJS, Webpack, etc.Rockett
I came to this page while trying to use a bundled UMD file produced with Rollup. Great question, and great answer...Countermark
I'm not familiar with UMD or whatever "factory" is (what does "inside the factory" and "outside the factory" mean?) - I'm unsure how to implement this answer. What code (either something I can copy+paste, or something I can use as a starting-point) do I need? Do I need to reimplement function require( moduleName ) myself?Allophone
Is there a trick to get bundlers to do this? In particular, vite?Metalinguistics
D
24

Simple answer: if you use usual UMD, it should be available in window['mymodule'] (or window.mymodule) or whatever name lib has. You can inspect window object in DevTools if unsure how it named.

Dagon answered 25/11, 2016 at 10:36 Comment(4)
I'm loading a UMD module into my page (by creating a <script async="" src=""> element inside another script). After the new script is loaded (i.e. the HTMLScriptElement.load event fires) there isn't a window['myScriptName'] member defined. Does this mean I'm not using a true UMD module, or is the window['mymodule']-thing a convention only a subset of all UMD modules use? Where do they add themselves?Allophone
@Allophone maybe. What you can do, open your module code, format it with "pretty print" and look for the beginning or the end of the file, there could be exports, global. etc. Possibly your lib exported with another name or inside commonJsStrict object or somewhere else.Dagon
I want to give another example: include rxJS in your page <script src="https://unpkg.com/[email protected]/dist/bundles/rxjs.umd.min.js"></script>. Afterwards you should be able to use rxJS, e.g., rxjs.range(1,10).subscribe(x => console.log(x)). Note that rxjs.range is the fully qualified reference to the method. This could be an import in another scenario: import { range } from "rxjs";. Further, note that window['bla'] references the variable bla in global scope. Thus, you could also use window['rxjs'].range.Foggy
If you are unsure how the module is named, then you might want to open the DevTools and inspect the window object. When typing window. in the DevTools, then autocompletion should show names in the global scope. One of these names should be your module.Foggy
G
9

In its current form, you cannot use myFunction() from myModule.js at all. Your myModule.js is not exposing (exporting) anything at all. You will have to first add this line to myModule.js


exports.myFunction = myFunction;

So that your module code becomes:


(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;
}));

Now when you will run this code in your .html file, browser creates a global object called 'mymodule' that has this method 'myFunction'.

You can call this method in your .html file as

myModule.myFunction();

Complete .html file will be:


    <!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>



Ginnifer answered 11/3, 2020 at 10:33 Comment(0)
E
-2

Here is an example how to render UMD React component:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
  <script src="https://unpkg.com/[email protected]/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>
Epi answered 29/5, 2018 at 8:37 Comment(1)
I downvoted this answer because the OP isn't asking about React, and React comes with its own module-helper logic.Allophone
N
-4

The amd module format is meant to be loaded asynchronously, so you cannot directly reference the file in a script tag. If this is being used for development, then you can use a loader like requirejs (see this link on amd specifics). If what you're after is to use this in production mode, then a few alternatives are:

1) Use requirejs but run the optimisation process which will bundle up the amd file 2) Use another minification process, such as webpack or build it into your frontend tooling (grunt, gulp etc).

I'm afraid in terms of loading the file directly, this isn't possible, due to the nature of amd (ability to declare dependencies on other modules).

Hope this helps.

Narthex answered 28/7, 2016 at 13:58 Comment(1)
I am afraid you're mixing up UMD with AMD.Countermark

© 2022 - 2024 — McMap. All rights reserved.