Pipeable operators

We haven't mentioned it much so far, but the RxJS library weighs in quite heavily when used in an app. In today's world of mobile first, every kilobyte counts when it comes to libraries that you include in your app. They count because the user may be on a 3G connection, and if it takes too long to load, your user may leave, or just may end up not liking your app, as it feels slow to load, and this may cause you to have bad reviews or lose users. So far, we have used two different ways of importing RxJS:

  • Importing the whole library; this one is quite costly in terms of size
  • Importing only the operators we need; this ensures that the bundle decreases significantly

The different options have looked like this, for importing the whole library and all its operators:

import Rx from "rxjs/Rx";

Or like this, to only import what we need:

import { Observable } from 'rxjs/Observable';
import "rxjs/add/operator/map";
import "rxjs/add/operator/take";

let stream = Observable.interval(1000)
.map(x => x +1)
.take(2)

That looks good, right? Well, yes, but it is a flawed approach. Let's explain what happens when you type:

import "rxjs/add/operator/map";

By typing the preceding, we add to the prototype of the Observable. Looking in the source code for RxJS, it looks like this:

var Observable_1 = require('../../Observable');
var map_1 = require('../../operator/map');

Observable_1.Observable.prototype.map = map_1.map;

As you can see from the preceding code, we import the Observable as well as the operator in question and we add the operator to the prototype by assigning it to a map property on the prototype. What's flawed with that, you might wonder? The problem is tree shaking, a process we use to get rid of unused code. Tree shaking has a hard time determining what you use and don't use, respectively. You may actually import a map() operator and it gets added to the Observable. As the code changes over time, you may end up not using it anymore. You may argue that you should remove the import at that point, but you might have a lot of code, and it is easy to overlook. It would be better if only used operators were included in the final bundle. It is, as we mentioned before, hard for the tree-shaking process to know what is used and what is not, with the current approach. For that reason, a big rewrite has happened in RxJS, adding something called pipeable operators, which help us with the above problem. There is also another downside to patching the prototype, and that is the fact that it creates a dependency. If the library changes and the operator is no longer added when we patch it (calling the import), then we have a problem. We won't detect the problem until runtime. We would rather be told that the operator has gone through us importing and explicitly using it, like so:

import { operator } from 'some/path';

operator();
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.19.74.29