I'm using SystemJS to load my es2015 project into the browser.
This is what I did
import {Observable} from 'rxjs/Rx';
const button = document.querySelector('button');
const start$ = Observable.fromEvent(button, 'click');
In this case Observable
is undefined
. So I tried
import Observable from 'rxjs/Observable';
In which case Observable
is an object but Observable.fromEvent
is undefined
(it seems to be an empty object)
Finally I did
import Rx from 'rxjs/Rx' // Rx.Observable
which did work. Any ideas why the other two didn't work? I have seen code in which they used these. What would be the preferred way to import Observable
?
UPDATE: As stated below its all described in the README. However if I do that
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
const start$ = Observable.fromEvent(startButton, 'click');
I get Observable
is undefined
. And if I do
import Observable from 'rxjs/Observable';
the Observable
is an empty object again. The fromEvent
is not added.
I'm using RxJs 5.1.1 and here is my index.html/systemjs part:
<script src="./node_modules/systemjs/dist/system.js"></script>
<script>
SystemJS.config({
baseURL: 'node_modules',
packages: {
'.': {
defaultJSExtensions: 'js'
}
},
map: {
'plugin-babel': 'systemjs-plugin-babel/plugin-babel.js',
'systemjs-babel-build': 'systemjs-plugin-babel/systemjs-babel-browser.js'
},
transpiler: 'plugin-babel'
});
SystemJS.import('/js/main.js');
</script>
As it notes in the README, you can use import { Observable } from 'rxjs/Observable';
:
To import only what you need by patching (this is useful for size-sensitive bundling)
This gives you a very minimal Observable
, to which you need to explicitly add any extra functionality you plan to use; in your case, follow it with:
import 'rxjs/add/observable/fromEvent';
I was having exactly the same issue when transpiling from TypeScript. Then I switched to using just the compiled scripts with exactly the same options and it worked so I'm suspicious it has something to do with transpiling your script. The bad things is there's probably no easy way to check what code it generated.
Anyway, the different types of imports are as follows:
import {Observable} from 'rxjs/Rx'
Since you're using baseURL
option this will look for file node_modules/rxjs/Rx.js
. This is the entry point of RxJS that requires all Observables, Subjects, operator, so on... (about 300 files) and you'll import only Observable
class.
import Observable from 'rxjs/Observable'
This imports only node_modules/rxjs/Observable.js
file and its dependencies (about 20 files).
import Rx from 'rxjs/Rx'
This shouldn't work at all. RxJS doesn't export any Rx
. You can see for yourself at src/Rx.ts
If you're loading single files you can use similar config as this:
System.config({
packages: {
'src': {
defaultExtension: 'js'
},
'rxjs': {
defaultExtension: 'js'
}
},
paths: {
'npm:': 'node_modules/',
'main': 'src/index'
},
map: {
'rxjs': 'npm:rxjs'
}
});
Then all imports are loaded as single files. For example rxjs/util/isFunction
= /node_modules/rxjs/util/isFunction.js
.
This isn't very useful in the browser because it'll be very slow. You can however load the bundled version with wildcard *
. Note that this works only in SystemJS 0.19.*:
System.config({
packages: {
'src': {
defaultExtension: 'js'
},
'rxjs': {
defaultExtension: 'js'
}
},
paths: {
'npm:': 'node_modules/',
'main': 'src/index',
'rxjs*': 'node_modules/rxjs/bundles/Rx.min.js'
}
In SystemJS 0.20.* the wildcard *
doesn't work any more (https://github.com/systemjs/systemjs/issues/1039)
With this config you can use all:
import {Observable} from 'rxjs';
import {Observable} from 'rxjs/Observable';
import {Observable} from 'rxjs/Rx';
Note that the situation in node
environment is different because you can always use just import {Observable} from 'rxjs'
thanks to main
option in its composer.json
.
As I have the same issue on a project of mine, I've been trying to debug systemJs to understand.
Now I can tell that systemJS basically works like this: It transpile module files into setters and executes. setters load dependencies and inject them into IIFE variables. execute runs the module codes when the setters are all set. Those are what you wrote before transpile.
(function(System, SystemJS) {System.register(["node_modules/rxjs/Subject.js"], function (_export, _context) {
"use strict";
var Subject;
return {
setters: [function (_node_modulesRxjsSubjectJs) {
Subject = _node_modulesRxjsSubjectJs.Subject;
}],
execute: function () {
class PetriNode {
constructor(name) {
this.from = [];
this.to = [];
... ...
I found out that systemJS loads modules with this project
within this line: line 612, the RxJs kinds of stuff and all load up fine.
err = dynamicExecute(link.execute, require, moduleObj.default, module);
After executing, the module.exports and moduleObj.__useDefault is loaded perfectly fine. All the Rx Classes and outputs are there.
But All The Defaults are FAILED to get COPIED into moduleObj as after this:
And then, when the setter is called, the inputted argument is moduleObj, which has a .default property has all the proper output, but setter failed to call them from but moduleObj itself.
The importerSetters is called the first time when all the Rx is done and begin to deal with my ECMA2015 modules. It's skipped every time when there is no import but requires.
I don't understand how should I handle commonJS default with .d.ts with import. I've seen that systemJS could deal with commonJS and ECMA2015 before. I've done it independently but not together.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With