Search code examples
angularrxjssystemjsplunker

Bundled RxJS in Angular 4 SystemJS plunk


Official Angular 4 plunk has a constant problem because it loads unbundled RxJS and often chokes on requests to unpkg.com

Can SystemJS configuration be modified to use bundled RxJS in bundled Angular modules?

  map: {
    ...
    'rxjs': 'npm:rxjs/bundles/Rx.js'
  },
  packages: {
    ...
    rxjs: {
      defaultExtension: 'js'
    }
  }

doesn't work well and results in 404 errors:

unpkg.com/[email protected]/bundles/Rx.js/operator/share.js:1

GET https://unpkg.com/[email protected]/bundles/Rx.js/operator/share.js 404 ()

because Angular bundled modules contain imports like:

import {Observable} from 'rxjs/Observable';
import {of } from 'rxjs/observable/of';
import {concatMap} from 'rxjs/operator/concatMap';
import {filter} from 'rxjs/operator/filter';
import {map} from 'rxjs/operator/map';

Solution

  • One simple way is to remove rxjs from map and add it as rxjs* into path (I think you'll need to use absolute path here):

    paths: {
      'rxjs*': 'https://unpkg.com/[email protected]/bundles/Rx.min.js'
    },
    

    This however works only with SystemJS 0.19.* because since 0.20 the wildcard * is no longer supported, see: https://github.com/systemjs/systemjs/issues/1039

    For Angular2: I'm not aware if there's any recommended way for SystemJS 0.20 but this has been discussed on RxJS GitHub page so you can read the entire thread https://github.com/ReactiveX/rxjs/issues/2458. In particular from my comment https://github.com/ReactiveX/rxjs/issues/2458#issuecomment-286706048 and then another comment where I create a custom AMD bundle which is pretty simple to do and works with SystemJS 0.20 as well https://github.com/ReactiveX/rxjs/issues/2458#issuecomment-287193937.

    Edit: So apparently this now works only with Angular2 and not in Angular4: https://plnkr.co/edit/ddRnL2I4ps2U2pdoRo04?p=info

    For Angular4 the easies way I found is to create a new file that polyfills missing exports (see commends bellow):

    import {Observable} from 'rxjs/Observable';
    import 'rxjs/add/operator/share';
    import 'rxjs/add/observable/merge';
    
    export function merge(...observables: Observable[]) {
      return Observable.merge(observables);
    }
    
    export function share(observable: Observable) {
      if (!observable) {
        return;
      }
      return observable.share();
    }
    

    And then load this file instead of the bundled RxJS:

    paths: {
      'npm:': 'https://unpkg.com/',
      'rxjs/observable/merge': './src/rxjs-polyfill.ts',
      'rxjs/operator/share': './src/rxjs-polyfill.ts',
      'rxjs*': 'https://unpkg.com/[email protected]/bundles/Rx.min.js'
    },
    

    Working demo with Angular4: http://plnkr.co/edit/tu561CX0n1I9f53iVv12