-
Notifications
You must be signed in to change notification settings - Fork 190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RxJS V6 Support #78
RxJS V6 Support #78
Conversation
… if on Observable or require User to pass them in to plugin config due to v6's breaking changes. Separated tests into v5 and v6.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, I'm confused by what seems to be a use of UMD globals for RxJS, there's a LOT of bundle size that will be lost from this choice, but that doesn't appear to have anything to do with this PR, per se.
I'd recommend using Webpack 4 and RxJS 6 without compat if possible to get the smallest output bundle size possible.
package.json
Outdated
@@ -43,7 +43,8 @@ | |||
"rollup": "^0.50.0", | |||
"rollup-plugin-buble": "^0.16.0", | |||
"rollup-watch": "^4.3.1", | |||
"rxjs": "^5.2.0", | |||
"rxjs": "^6.0.0-beta.3", | |||
"rxjs-compat": "^6.0.0-beta.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rxjs-compat and rxjs should be the same version here. both are at beta.4 right now.
@@ -45,7 +45,8 @@ export default { | |||
}) | |||
}) | |||
} else { | |||
if (!Rx.Observable.fromEvent) { | |||
const fromEvent = Rx.fromEvent || Rx.Observable.fromEvent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is apparently using the umd global?
All locations in the v6 global are a mirror of the module locations, only with periods. This should be:
const fromEvent = rxjs.fromEvent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This library passes in it's own Rx
that comes from the configuration, so Rx
is valid here.
@@ -13,7 +13,8 @@ export default function createObservableMethod (methodName, passContext) { | |||
} | |||
const vm = this | |||
|
|||
if (!Rx.Observable.prototype.share) { | |||
const share = Rx.share || Rx.Observable.prototype.share | |||
if (!share) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const share = rxjs.operators.share
if we're using the umd global
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above
@@ -52,5 +53,8 @@ export default function createObservableMethod (methodName, passContext) { | |||
} | |||
|
|||
// Must be a hot stream otherwise function context may overwrite over and over again | |||
if (Rx.share) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rxjs.operators.share
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above
@@ -52,5 +53,8 @@ export default function createObservableMethod (methodName, passContext) { | |||
} | |||
|
|||
// Must be a hot stream otherwise function context may overwrite over and over again | |||
if (Rx.share) { | |||
return Rx.Observable.create(creator).pipe(share()) | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rxjs.Observable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the Rx
references are an object passed into the plugin, not the actual Rx package (I know that's confusing). Take a look at how install
works:
expect(param).toEqual('hola') | ||
done() | ||
}) | ||
this.$createObservableMethod('add').subscribe(function (param) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was the formatting change necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why format so many test code😢
Reviewed @yyx990803 Basically, v6 support pipe operators. Users may want import each individual operators (not on Rx.Observable as used do on v5). |
@regou sorry about the formatting. I ran the linter and had the editor config plugin running as well... I can manually fix it if you'd like. |
@johnlindquist, I believe Rxjs v6 RC is out - 6.0.0-rc.0. |
RxJS 6 is out! Maybe it's time to pass that pull request... ;) |
@johnlindquist can you update this PR to use official RxJS 6? |
@johnlindquist you should probably update the readme, with the requirements of |
I'm doing some testing with this locally (with rxjs6), and running into a fun issue. Since the This means that the types can only really work for rxjs6 or rxjs5... I think the best solution to this is to just copy the required interfaces from rxjs, so that the library isn't coupled to either version. Thoughts? My current import Vue from 'vue'
import { WatchOptions } from 'vue'
export interface Unsubscribable {
unsubscribe(): void;
}
export interface Subscribable<T> {
subscribe(observerOrNext?: PartialObserver<T> | ((value: T) => void),
error?: (error: any) => void,
complete?: () => void): Unsubscribable;
}
export interface NextObserver<T> {
closed?: boolean;
next: (value: T) => void;
error?: (err: any) => void;
complete?: () => void;
}
export interface ErrorObserver<T> {
closed?: boolean;
next?: (value: T) => void;
error: (err: any) => void;
complete?: () => void;
}
export interface CompletionObserver<T> {
closed?: boolean;
next?: (value: T) => void;
error?: (err: any) => void;
complete: () => void;
}
export type PartialObserver<T> = NextObserver<T> | ErrorObserver<T> | CompletionObserver<T>;
export type Observables = Record<string, Subscribable<any>>
declare module 'vue/types/options' {
interface ComponentOptions<V extends Vue> {
subscriptions?: Observables | ((this: V) => Observables)
domStreams?: string[]
observableMethods?: string[] | Record<string, string>
}
}
export interface WatchObservable<T> {
newValue: T
oldValue: T
}
declare module "vue/types/vue" {
interface Vue {
$observables: Observables;
$watchAsObservable(expr: string, options?: WatchOptions): Subscribable<WatchObservable<any>>
$watchAsObservable<T>(fn: (this: this) => T, options?: WatchOptions): Subscribable<WatchObservable<T>>
$eventToObservable(event: string): Subscribable<{name: string, msg: any}>
$subscribeTo<T>(
observable: Subscribable<T>,
next: (t: T) => void,
error?: (e: any) => void,
complete?: () => void): void
$fromDOMEvent(selector: string | null, event: string): Subscribable<Event>
$createObservableMethod(methodName: string): Subscribable<any>
}
}
export declare function install(V: typeof Vue): void |
rxjs5:
rxjs6
|
Since I'm not a frequent RxJS user, a few questions for everyone in this thread:
Ideally, we probably want to do a new build setup where we export two builds:
|
@yyx990803 It can be... however, what a library should do that's using RxJS is just use v6. Then it's up to the consumer of that library to include
v6 is totally ready.. the only reason that importing would go into rxjs-compat is if you imported from a deprecated path underneath Again, RxJS 6 is a win, especially when combined with Webpack 4, and it's setting up for v7 which will be massively reduced in size and much faster overall. |
@@ -43,14 +36,13 @@ | |||
"rollup": "^0.50.0", | |||
"rollup-plugin-buble": "^0.16.0", | |||
"rollup-watch": "^4.3.1", | |||
"rxjs": "^5.2.0", | |||
"rxjs": "^6.0.0", | |||
"rxjs-compat": "^6.0.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably don't want this included by default, leave that to consumers of the library to decide whether they need it or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are dev deps
const Subscription = require('rxjs/Subscription').Subscription | ||
require('rxjs/add/observable/fromEvent') | ||
require('rxjs/add/operator/share') | ||
const Observable = require('rxjs-compat/Observable').Observable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would import from the proper locations expected in v6... other rxjs
or rxjs/operators
. Not from rxjs-compat
. That should never be imported from directly anyhow.
@@ -151,7 +153,8 @@ test('v-stream directive (basic)', done => { | |||
domStreams: ['click$'], | |||
subscriptions () { | |||
return { | |||
count: this.click$.map(() => 1) | |||
count: this.click$ | |||
.map(() => 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All operator use should be convered to "pipeable" operators:
this.click$.pipe(
map(() => 1),
....
)
The underlying problem is that the current typings will require Personally I'm fine saying just use My solution solves the issue for both current consumers and allows new consumes to strictly target just rxjs6. |
That shouldn't at all be the case. This is precisesly what Case in point: Angular v6 is using rxjs v6 exclusively, and apps with rxjs 5 code can "just work" if they install |
The meaning of the For rxjs5: For rxjs6: If we copy |
@david-driscoll is there something that needs fixed on our end? Because the general idea is that libraries and frameworks should be using For this issue, my advice stands, Vue, Angular, et al, should be using |
Nothing on the rxjs side can really be fixed because of the way the new imports are different between the two. Unless we stopped requiring The changes here I'm proposing are just for the typings in this library, so that it can work with rxjs5 and rxjs6 without causing a headache for either user. |
@david-driscoll if this library just uses v6, all consumers will be able to use v5 if they want by simply including |
The imports currently are: Lines 1 to 3 in 44dfefd
The type declarations for This library however does not import rxjs at all by itself, instead you pass it an object that includes a thing that is named So now when I install this library with rxjs6. import Vue from 'vue';
import VueRx from 'vue-rx';
import { fromEvent, Observable, Subject, Subscription } from 'rxjs';
import { share } from 'rxjs/operators';
Vue.use(VueRx as any, { Observable, Subject, Subscription, fromEvent, share }); When the types get imported they use Lines 1 to 3 in 44dfefd
Which then forces me into installing rxjs-compat, even though I'm strictly using rxjs6. If we reverse things and want to use rxjs5 (or are an existing user), and the types are updated to strictly use import Vue from 'vue';
import VueRx from 'vue-rx';
import { Observable } from 'rxjs/Observable'
import { Subscription } from 'rxjs/Subscription' // Disposable if using RxJS4
import { Subject } from 'rxjs/Subject' // required for domStreams option
Vue.use(VueRx as any, { Observable, Subject, Subscription }); Now my type system has been polluted with types that I have not explicitly imported, so I'll start seeing |
That is why I proposed bringing in the types with the comment above: #78 (comment) |
The imports should be updated to be |
Okay, I've submitted a separate PR that follows what I'd recommend doing here. (Sorry, @johnlindquist) It's got breaking changes, so if you decide you want to go with it, you'd want to move up a major version. See #84 |
Closing in favor of #84 - but thanks for getting this off the ground @johnlindquist ! |
RxJS v6 now uses a "pipeable" operators paradigm thus changing how
fromEvent
andshare
are required when installing.Plugin Installation API
API-wise:
Vue.use(VueRx, {Observable, Subject, Subscription})
now requires
fromEvent
andshare
Vue.use(VueRx, {Observable, Subject, Subscription, fromEvent, share})
stream.js
andcreateObservableMethod.js
were updated to support either API.Tests
v5.test.js
andv6.test.js
.v5
now usesrxjs-compat
for backwards compatibility.** Note a small breaking change with errors: https://twitter.com/johnlindquist/status/979408339858845704
v6
are the same tests, but usingrxjs
and "pipeable" operators