Importing RxJS 6 in browser?
Asked Answered
A

3

21

Now that all modern browser support javascript modules, I'm trying out importing code right in the browser. We can get npm modules from unpkg.com, and I've found the jspm project, which wraps npm modules into a format that can be consumed by the browser.

But I'm still having problems, most notably with RxJS. RxJS, as of version 6, recommends you import constructors and operators like this:

import { Observable, Subject, ReplaySubject, from, of, range } from 'rxjs';
import { map, filter, switchMap } from 'rxjs/operators';

But if I try to do that in the browser with:

import { Observable, Subject, ReplaySubject, from, of, range } from 'https://dev.jspm.io/rxjs@6';
import { map, filter, switchMap } from 'https://dev.jspm.io/rxjs@6/operators';

I get errors along these lines:

Uncaught SyntaxError: The requested module 'https://dev.jspm.io/rxjs@6/operators' does not provide an export named 'map'

I can get around it by importing the whole rxjs module and teasing out what I need, like I would using a CDN:

import rxjs from 'https://dev.jspm.io/rxjs@6';
const { Observable } = rxjs;
import operators from 'https://dev.jspm.io/rxjs@6/operators';
const { map } = operators;

but this defeats what the Rx team is trying to do to decrease the final bundle size, etc.

I'm sure this isn't just an RxJS problem.

What is the solution here moving forward to get our dev javascript (imports directly into the browser) to look like what we'd finally want to pass to a bundler?

Alate answered 12/5, 2018 at 15:49 Comment(1)
Even more difficult seems to be using the import 'rxjs/add/operator... syntax... I'm sure the answer is not simple, what I'd investigate (would I have some time on hand) is an approach to package individual modules of rxjs into individual es6-compatible units. I think it can be achieved using something like rollup.Requiescat
A
12

The es6 module export syntax is inside the subfolder _esm2015. So you need to import:

import { Observable, Subject, ReplaySubject, from, of, range } from 'https://dev.jspm.io/rxjs@6/_esm2015';
import { map, filter, switchMap } from 'https://dev.jspm.io/rxjs@6/_esm2015/operators';

Sadly you can't just install rxjs with npm install rxjs@6 and then import in the browser, because the distribution source is missing the file extension .js in the import statements: https://unpkg.com/@reactivex/[email protected]/dist/esm2015/index.js.

But the browser needs the file extensions for import (at the moment): (https://developers.google.com/web/fundamentals/primers/modules#specifiers):

// Not supported (yet):
import {shout} from 'jquery';
import {shout} from 'lib.mjs';
import {shout} from 'modules/lib.mjs';

// Supported:
import {shout} from './lib.mjs';
import {shout} from '../lib.mjs';
import {shout} from '/modules/lib.mjs';
import {shout} from 'https://simple.example/modules/lib.mjs';

There is also an issue for this: https://github.com/ReactiveX/rxjs/issues/4416 .

For now you have to rely on https://jspm.io or make your own bundle (e.g. with rollup as suggested by @Ovidiu Dolha).

Arlinda answered 6/1, 2019 at 12:45 Comment(0)
H
16

Here's a simple rxjs starter example stackblitz:

In short:

Make sure you have a script to add the rxjs js file (for example from a CDN)

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.1.0/rxjs.umd.js">

Everything is imported under the rxjs namespace, so to a simple example usage:

rxjs.of(1, 2, 3)
  .subscribe(x => {
    const element = document.createElement('div');
    element.innerText = 'Data: ' + x;
    document.body.appendChild(element)
  },
  err => { },
  () => {
    const element = document.createElement('div');
    element.innerText = 'All done';
    document.body.appendChild(element)
  });
Humfried answered 13/5, 2018 at 3:11 Comment(4)
I think this answer is not really answering the original question. The problem is not only loading rxjs, but loading it in an ESModules-friendly way.Requiescat
And if you want to use an operator: var tap = rxjs.operators.tap; and then rxjs.of(1,2,3).pipe(tap(value=>console.log(value)))Buskined
const may even better, const tap = rxjs.operators.tap; Tours
further improve with destructuring, like const { debounceTime, tap } = rxjs.operators, and now you can add to the list as requiredBenares
A
12

The es6 module export syntax is inside the subfolder _esm2015. So you need to import:

import { Observable, Subject, ReplaySubject, from, of, range } from 'https://dev.jspm.io/rxjs@6/_esm2015';
import { map, filter, switchMap } from 'https://dev.jspm.io/rxjs@6/_esm2015/operators';

Sadly you can't just install rxjs with npm install rxjs@6 and then import in the browser, because the distribution source is missing the file extension .js in the import statements: https://unpkg.com/@reactivex/[email protected]/dist/esm2015/index.js.

But the browser needs the file extensions for import (at the moment): (https://developers.google.com/web/fundamentals/primers/modules#specifiers):

// Not supported (yet):
import {shout} from 'jquery';
import {shout} from 'lib.mjs';
import {shout} from 'modules/lib.mjs';

// Supported:
import {shout} from './lib.mjs';
import {shout} from '../lib.mjs';
import {shout} from '/modules/lib.mjs';
import {shout} from 'https://simple.example/modules/lib.mjs';

There is also an issue for this: https://github.com/ReactiveX/rxjs/issues/4416 .

For now you have to rely on https://jspm.io or make your own bundle (e.g. with rollup as suggested by @Ovidiu Dolha).

Arlinda answered 6/1, 2019 at 12:45 Comment(0)
B
-3

var button = document.querySelector("button");

var obs1 = rxjs.fromEvent(button, "click");

var obs2 = rxjs.interval(1000);

// obs2.subscribe((val) => {
//   console.log(val);
// });


obs1.pipe(rxjs.switchMap(() => obs2)).subscribe((val) => console.log(val));
    <!DOCTYPE html>
    <html>

    <head>
        <meta charset='utf-8'>
        <meta http-equiv='X-UA-Compatible' content='IE=edge'>
        <title>Page Title</title>
        <meta name='viewport' content='width=device-width, initial-scale=1'>
        <link rel='stylesheet' type='text/css' media='screen' href='main.css'>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/bundles/rxjs.umd.min.js"></script>
        <script defer src='main.js'></script>
    </head>

    <body>
        <button id="btn">
            Click Me
        </button>
    </body>

    </html>
Barbados answered 16/3 at 12:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.