Import UMD Javascript Modules into Browser
Asked Answered
T

6

16

Hi I am doing some research on RxJS. I am able to use the library simply by referencing it in my browser as such:

<script src="https://unpkg.com/@reactivex/[email protected]/dist/global/Rx.js"></script>

It imports with the global object namespace variable of 'Rx'. I can make observables and do all the fun stuff.

Where everything breaks down is when I change the src to point to the latest UMD file like this <script src="https://unpkg.com/rxjs/bundles/rxjs.umd.js"></script>

The import seems to not be working as exported object functions don't seem to exist?

There is a specific function I am trying to use called 'fromEvent' that allows an observable to be created from any DOM event.

I am getting an error when using the latest RxJS 6.2.2 UMD file.

Why is this? If you look inside the js file at the bottom you can see the export of the function and at the top of the file you see the global namespace called 'rxjs'.

I am not using any loaders like requirejs nor do I have any experimental browser features enabled. I am not using any 'import' statements.

I am simply trying to reference the global namespace of the script object. The syntax for the module definition is identical except for Rx vs rxjs.

To replicate the error, simply create an Observable.fromEvent(.... and watch the error console.

Thanks!

Te answered 22/7, 2018 at 3:12 Comment(0)
R
5
  1. Recently the UMD bundle was renamed to just rxjs, see https://github.com/ReactiveX/rxjs/commit/556c904ea61a8424e5d24f170b20eadbc05d01f0#diff-6d2911fe563068b8126098588db98a84

  2. If you want to use RxJS 6 you need to switch to "pipable" operators (and creation functions), see https://github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/v6/migration.md#operator-pipe-syntax

So for example this works:

<script src="https://unpkg.com/rxjs/bundles/rxjs.umd.js"></script>
<script>
rxjs.fromEvent(document, 'click').subscribe(console.log);
</script>

Demo: https://stackblitz.com/edit/rxjs6-demo-r2rtbz?file=index.html

Richardo answered 22/7, 2018 at 8:42 Comment(1)
The piping was the issue all along. I feel like I should just pipe everything just in case :) Thank-you for the nuance of possible piping, with out that hint I'd be still doing some nice head smashing on the keyboard.Te
E
10

Here's a oneliner to import UMD modules using browser modules and dynamic imports in 2020.

export default async (url, module = {exports:{}}) =>
  (Function('module', 'exports', await (await fetch(url)).text()).call(module, module, module.exports), module).exports

Usage example:

const ednToJS = await importUMD(`https://unpkg.com/[email protected]/dist/main.js`)
const rxjs = await importUMD('https://unpkg.com/[email protected]/bundles/rxjs.umd.js')

tada

Evapotranspiration answered 6/11, 2020 at 20:35 Comment(1)
How do you get around potential "require not defined" errors with this?Scheider
R
5
  1. Recently the UMD bundle was renamed to just rxjs, see https://github.com/ReactiveX/rxjs/commit/556c904ea61a8424e5d24f170b20eadbc05d01f0#diff-6d2911fe563068b8126098588db98a84

  2. If you want to use RxJS 6 you need to switch to "pipable" operators (and creation functions), see https://github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/v6/migration.md#operator-pipe-syntax

So for example this works:

<script src="https://unpkg.com/rxjs/bundles/rxjs.umd.js"></script>
<script>
rxjs.fromEvent(document, 'click').subscribe(console.log);
</script>

Demo: https://stackblitz.com/edit/rxjs6-demo-r2rtbz?file=index.html

Richardo answered 22/7, 2018 at 8:42 Comment(1)
The piping was the issue all along. I feel like I should just pipe everything just in case :) Thank-you for the nuance of possible piping, with out that hint I'd be still doing some nice head smashing on the keyboard.Te
L
5
export default async function (url, module = {exports:{}})
{
    const response = await fetch(url);
    const script = await response.text();
    const func = Function("module", "exports", script)
    func.call(module, module, module.exports);
    return module.exports;
};

Same code reformatted

Laise answered 28/11, 2021 at 23:12 Comment(0)
T
3

Here is an example after doing the proper import , note the pipe.

submission = rxjs.fromEvent($('#mybutton'), 'click')
    .pipe(rxjs.operators.map((event) => {
        return "something"
    }));

I may rename the globals to 'r' and 'ro' to avoid the new verbosity.

Also bonus points if someone can point to piped error handling in 6.0!

Te answered 22/7, 2018 at 17:19 Comment(0)
G
1

It imports with the global object namespace variable of 'Rx'.

Maybe version 5.5.6 does but the latest version which you're trying to use, 6.2.2, does not. The object it exports to the global namespace is called rxjs. If you load https://unpkg.com/rxjs/bundles/rxjs.umd.js in a browser you'll see this in the source in the UMD module definition:

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

If you want to use fromEvent you can do so via rxjs.fromEvent.

Gliadin answered 22/7, 2018 at 3:23 Comment(1)
Thanks, indeed I was aware of this, this was observed in the file. I had actually moved to the rxjs.fromEvent() but the same error was occurring then on the map call so really the issue was to move to the new piping syntax.Te
I
1

To import any umd module from unpkg or jsdeliver in the browser with JavaScript, what I find mostly useful was using d3@require. Since actually importing the umd modules give me a bare "Module" object.

In your case it would work like this, notice I dont actually use any HTML, as a bonus this would also work for deno

import("https://raw.githack.com/d3/d3-require/main/src/index.mjs")
.then(
_=>_.require("https://unpkg.com/@reactivex/[email protected]/dist/global/Rx.js")
)
.then(Object.keys)
.then(console.log)

Now, here I show an use case of require, where I require 2 modules, one is the Rx library, and the other is just an inspector library that shows off elements as if it were in the console

import("https://raw.githack.com/d3/d3-require/main/src/index.mjs").then(async _=>{
    var inspector=await _.require("@observablehq/inspector");
var Rx=_.require("https://unpkg.com/@reactivex/[email protected]/dist/global/Rx.js");
var x=new inspector.Inspector(window.inspect);
x.fulfilled(await Rx)
return x;
})
@import url("https://raw.githack.com/observablehq/inspector/main/src/style.css")
<div id="inspect" />
Impasse answered 11/10, 2022 at 13:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.