Angular2 2.0.x and Rx 5 beta.12 bundle

2019-01-29 02:57发布

I am currently updating the dependencies of my project which uses the Angular2 npm packages and therefore RxJs as well. I am updating to the 2.0.2 stable release of angular which depends on Rx5 beta.12. For my web application i only deploy the Rx.min.js bundle and load it with a script tag in my index.html file. That approach worked perfectly before with the Rx umd bundle, but causes errors meanwhile, since it appears to me that the contributors of RxJs dropped the different bundle versions for the sake of one common bundle file. i.e. Rx.js instead of Rx.umd.js and so on.

I am using SystemJs module loader and if i do no additional steps these errors will occur with any symbol of the RxJs Framework:

GET http://localhost:8080/rxjs/Subject.js 404 (Not Found)

I recognized that Rx is now globally defined (window.Rx) and contains all the necessary stuff. So i tried to define those symbols in SystemJs manually by doing smth like this:

function defineGlobalModule( parentModuleName, simpleName, moduleValue ) {
  var fqModuleName = parentModuleName + simpleName;
  System.amdDefine( fqModuleName, ["require", "exports"], function (require, exports) {
       "use strict";
       exports[ simpleName ] = moduleValue;
  }); 

  if( typeof moduleValue === "object" )
     for( var key in moduleValue )
       defineGlobalModule( fqModuleName + "/", key, moduleValue[ key ] )
}

defineGlobalModule( "", "rxjs", global.Rx );

That made the 'rxjs/Subject' style imports work again. But now i get lots of errors like this:

GET http://localhost:8080/rxjs/operator/toPromise.js 404 (Not Found)
GET http://localhost:8080/rxjs/observable/fromPromise.js 404 (Not Found)

These files are imported by the angular forms.umd.js bundle for example.

What is the state of the art for Angular2 2.0.x when it comes to importing the Rx.js bundle without deploying the node_module itself. I need the bundled version! I was using the umd version of the Rx.js bundle before which seems not to exist anymore.

2条回答
手持菜刀,她持情操
2楼-- · 2019-01-29 03:04

I did maybe exactly what you're looking for with Angular2 and rxjs@5.0.0-beta.12 which is now distributed as globals and the umd package is probably not supported any more (just as you said):

See live demo: https://plnkr.co/edit/z4gg2XBoQDgYXev0Csuq

Basically, I just updated my SystemJS config:

paths: {
  'rxjs*': 'https://unpkg.com/@reactivex/rxjs@5.0.0-beta.12/dist/global/Rx.js'
},

Then I removed rxjs from map list. Now it loads a single Rx.js file.

查看更多
Ridiculous、
3楼-- · 2019-01-29 03:06

This worked for me, loading via rxjs* caused issue once I started to use other bits of Angular2 such as routing.

This issue is discussed in detail here and the solution is to use your own loader such as (code credit nros)

Apparently, it's going to be fixed in a future release I suspect this is being held back as rxjs is still in beta.

rxjsLoader.js

// see: https://github.com/angular/angular/issues/9359
// in case all parts of RxJS are loaded with a single file (eg: Rx.js), Angular 2 may have
// difficulties using/requiring the various parts.
// this custom loader translates requests to these parts to the already loaded Rx entity.
//
// eg: Angular:
//      require('rxjs/observable/from')  -->  Rx.Observable
//      require('rxjs/operator/concatMap')  -->  Rx.Observable.prototype
//      require('rxjs/util/EmptyError')  -->  Rx
//
// Angular will access 'rxjs/observable/from' as rxjs_observable_from.from
// so, the last part of the included module (eg: 'from') denotes the property name to access
// the required value.
SystemJS.amdDefine(SystemJS.baseURL + "rxjsLoader.js", ["rxjs"], function (Rx) {
    'use strict';

    // custom loader for RX.js to instantiate the correct value
    // see: https://github.com/ModuleLoader/es-module-loader/blob/v0.17.0/docs/loader-extensions.md
    return {
        fetch: function fetch(loadData) {
            return ""; // no fetch - "Rx" is already loaded!
        },

        translate: function translate(loadData) {
            return "";
        },

        instantiate: function instantiate(loadData) {

            // loadData.name contains the full URL
            var propertyName = loadData.name.replace(/^.*\/rxjs-parts\/(.*)$/i, "$1").replace(/\.js$/i, "");

            // if property name is not empty, evaluate and use it
            if (propertyName.length > 0 && !(/^\s*$/.test(propertyName))) {
                var parts = propertyName.split("/"),
                    targetObject = Rx
                ;

                // Angular 2 expects the return value to be an object
                // and the last part of the name to be the property of that object

                for (var i=0; i < parts.length-1; i++) {
                     var partName = parts[i],
                         upperCaseName = partName.charAt(0).toUpperCase() + partName.slice(1)
                     ;

                     // handle special case for "operator/*"
                     if (partName === "operator") {
                         return Rx.Observable.prototype;

                     } else if (targetObject[partName] !== undefined) {
                         targetObject = targetObject[partName];

                     } else if (targetObject[upperCaseName] !== undefined) {
                         targetObject = targetObject[upperCaseName];

                     } else {
                         // skip name and try with next part name. eg: "utils"
                         continue;
                     }
                }

                return targetObject;

            } else {
                // return the Rx as default
                return Rx;
            }
        }
    };
});

systemjs-config-using-custom-rx-loader.js

SystemJS.config({

    baseURL: '/',

    map: {
        "rxjs": "Rx.js"
    },
    paths: {
        "Rx.js/*": "rxjs-parts/*"
    },
    packages: {
       "rxjs-parts": {
            meta: {
                "*": {
                    loader: "rxjsLoader.js"
                }
            }
        }
    }
});
查看更多
登录 后发表回答