Angular2 2.0.x 和 Rx 5 beta.12 包
Angular2 2.0.x and Rx 5 beta.12 bundle
我目前正在更新我的项目的依赖项,该项目使用 Angular2 npm 包,因此也使用 RxJs。我正在更新到 angular 的 2.0.2 稳定版本,它依赖于 Rx5 beta.12。
对于我的 Web 应用程序,我只部署 Rx.min.js 包并在我的 index.html 文件中使用脚本标记加载它。这种方法在 Rx umd bundle 之前工作得很好,但同时会导致错误,因为在我看来,RxJs 的贡献者为了一个通用的 bundle 文件而放弃了不同的 bundle 版本。即 Rx.js 而不是 Rx.umd.js 等等。
我正在使用 SystemJs 模块加载器,如果我不执行额外的步骤,这些错误将出现在 RxJs 框架的任何符号上:
GET http://localhost:8080/rxjs/Subject.js 404 (Not Found)
我认识到 Rx 现在是全局定义的 (window.Rx) 并且包含所有必要的东西。所以我尝试通过这样的方式在 SystemJs 中手动定义这些符号:
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 );
这使得 'rxjs/Subject' 样式导入再次起作用。但现在我收到很多这样的错误:
GET http://localhost:8080/rxjs/operator/toPromise.js 404 (Not Found)
GET http://localhost:8080/rxjs/observable/fromPromise.js 404 (Not Found)
例如,这些文件由 angular forms.umd.js 包导入。
Angular2 2.0.x 在导入 Rx.js bundle 而不部署 node_module 本身。我需要捆绑版本!我使用的是 Rx.js 捆绑包的 umd 版本,之前似乎不再存在了。
我用 Angular2
和 rxjs@5.0.0-beta.12
做的也许正是您正在寻找的,现在分发为 globals
并且 umd
包可能不受任何支持更多(正如你所说):
观看现场演示:https://plnkr.co/edit/z4gg2XBoQDgYXev0Csuq
基本上,我刚刚更新了我的 SystemJS 配置:
paths: {
'rxjs*': 'https://unpkg.com/@reactivex/rxjs@5.0.0-beta.12/dist/global/Rx.js'
},
然后我从 map
列表中删除了 rxjs
。现在它加载单个 Rx.js
文件。
这对我有用,一旦我开始使用 Angular2
的其他位(例如 routing
),通过 rxjs*
加载就会出现问题。
这个问题讨论的很详细here and the solution is to use your own loader such as (code credit nros)
显然,它会在未来的版本中得到修复我怀疑这是因为 rxjs 仍处于测试阶段而被阻止。
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, "").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"
}
}
}
}
});
我目前正在更新我的项目的依赖项,该项目使用 Angular2 npm 包,因此也使用 RxJs。我正在更新到 angular 的 2.0.2 稳定版本,它依赖于 Rx5 beta.12。 对于我的 Web 应用程序,我只部署 Rx.min.js 包并在我的 index.html 文件中使用脚本标记加载它。这种方法在 Rx umd bundle 之前工作得很好,但同时会导致错误,因为在我看来,RxJs 的贡献者为了一个通用的 bundle 文件而放弃了不同的 bundle 版本。即 Rx.js 而不是 Rx.umd.js 等等。
我正在使用 SystemJs 模块加载器,如果我不执行额外的步骤,这些错误将出现在 RxJs 框架的任何符号上:
GET http://localhost:8080/rxjs/Subject.js 404 (Not Found)
我认识到 Rx 现在是全局定义的 (window.Rx) 并且包含所有必要的东西。所以我尝试通过这样的方式在 SystemJs 中手动定义这些符号:
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 );
这使得 'rxjs/Subject' 样式导入再次起作用。但现在我收到很多这样的错误:
GET http://localhost:8080/rxjs/operator/toPromise.js 404 (Not Found)
GET http://localhost:8080/rxjs/observable/fromPromise.js 404 (Not Found)
例如,这些文件由 angular forms.umd.js 包导入。
Angular2 2.0.x 在导入 Rx.js bundle 而不部署 node_module 本身。我需要捆绑版本!我使用的是 Rx.js 捆绑包的 umd 版本,之前似乎不再存在了。
我用 Angular2
和 rxjs@5.0.0-beta.12
做的也许正是您正在寻找的,现在分发为 globals
并且 umd
包可能不受任何支持更多(正如你所说):
观看现场演示:https://plnkr.co/edit/z4gg2XBoQDgYXev0Csuq
基本上,我刚刚更新了我的 SystemJS 配置:
paths: {
'rxjs*': 'https://unpkg.com/@reactivex/rxjs@5.0.0-beta.12/dist/global/Rx.js'
},
然后我从 map
列表中删除了 rxjs
。现在它加载单个 Rx.js
文件。
这对我有用,一旦我开始使用 Angular2
的其他位(例如 routing
),通过 rxjs*
加载就会出现问题。
这个问题讨论的很详细here and the solution is to use your own loader such as (code credit nros)
显然,它会在未来的版本中得到修复我怀疑这是因为 rxjs 仍处于测试阶段而被阻止。
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, "").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"
}
}
}
}
});