rxjs vs rxjs-compat
Managing Reactive Streams and Migration Paths in JavaScript
rxjsrxjs-compatSimilar Packages:

Managing Reactive Streams and Migration Paths in JavaScript

rxjs is the core library for reactive programming using Observables, providing tools for handling async data streams. rxjs-compat was a compatibility layer created specifically for RxJS version 6 to support legacy import paths from version 5. While rxjs is the active standard for modern development, rxjs-compat served as a bridge to help teams update older codebases without rewriting every import statement immediately.

Npm Package Weekly Downloads Trend

3 Years

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
rxjs031,6794.5 MB294a year agoApache-2.0
rxjs-compat0---5 years agoApache-2.0

RxJS vs RxJS-Compat: Modern Reactive Streams vs Legacy Migration

Both rxjs and rxjs-compat deal with reactive programming using Observables, but they serve different purposes in the lifecycle of the library. rxjs is the main package used for building applications today. rxjs-compat was a temporary tool designed to help developers move from version 5 to version 6. Let's compare how they handle imports, operators, and long-term support.

📦 Import Paths: Modular vs Legacy

rxjs uses modular import paths introduced in version 6.

  • You import creators and operators from specific sub-paths.
  • This allows bundlers to remove unused code (tree-shaking).
// rxjs: Modern modular imports
import { Observable } from 'rxjs';
import { map, filter } from 'rxjs/operators';

const source = new Observable(subscriber => {
  subscriber.next(1);
});

source.pipe(
  map(x => x * 2),
  filter(x => x > 2)
);

rxjs-compat allowed old version 5 import paths to work in version 6.

  • You could import directly from deep paths like rxjs/Observable.
  • This prevented immediate breakage but blocked tree-shaking benefits.
// rxjs-compat: Legacy import paths (v5 style)
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/filter';

const source = new Observable(subscriber => {
  subscriber.next(1);
});

source
  .map(x => x * 2)
  .filter(x => x > 2);

🛠️ Operator Usage: Pipeable vs Prototype

rxjs relies on pipeable operators used inside the .pipe() method.

  • Operators are pure functions passed as arguments.
  • This makes testing easier and reduces side effects.
// rxjs: Pipeable operators
import { of } from 'rxjs';
import { map } from 'rxjs/operators';

of(1, 2, 3).pipe(
  map(value => value * 10)
).subscribe(console.log);

rxjs-compat supported prototype methods chained directly on Observables.

  • Operators were added to the Observable prototype globally.
  • This pattern is no longer supported in RxJS version 7.
// rxjs-compat: Prototype chaining (v5 style)
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';

Observable.of(1, 2, 3)
  .map(value => value * 10)
  .subscribe(console.log);

📅 Maintenance and Version Support

rxjs is actively maintained and receives regular updates.

  • Current versions (7+) require the standard import style.
  • Using this package ensures compatibility with the wider ecosystem.
// rxjs: Current standard (v7+)
import { interval } from 'rxjs';
import { take } from 'rxjs/operators';

interval(1000).pipe(take(5)).subscribe();

rxjs-compat is deprecated and should not be used in new projects.

  • It was removed entirely in RxJS version 7.
  • Relying on it prevents you from upgrading to newer versions.
// rxjs-compat: Deprecated pattern
// This will fail if you upgrade to RxJS v7
import { Observable } from 'rxjs/Observable'; 

🤝 Similarities: Shared Core Concepts

Despite the differences in syntax, both packages share the same underlying logic for handling streams. Here are key overlaps:

1. 🔄 Observable Streams

  • Both use the Observable type to represent data over time.
  • Support subscription and unsubscription patterns.
// Shared concept: Creating a stream
// Works in both (with different imports)
const stream = new Observable(observer => {
  observer.next('data');
  observer.complete();
});

2. 👀 Subscription Management

  • Both require subscribing to start execution.
  • Both return a Subscription object to cancel work.
// Shared concept: Subscribing
const sub = stream.subscribe({
  next: value => console.log(value),
  complete: () => console.log('done')
});

sub.unsubscribe();

3. ⚡ Async Handling

  • Both handle async events like clicks, timers, or HTTP requests.
  • Provide tools to manage concurrency and ordering.
// Shared concept: Handling async events
// rxjs
import { fromEvent } from 'rxjs';
fromEvent(document, 'click').subscribe();

// rxjs-compat (v5 style)
import { Observable } from 'rxjs/Observable';
Observable.fromEvent(document, 'click').subscribe();

📊 Summary: Key Similarities

FeatureShared by RxJS and RxJS-Compat
Core Type🔄 Observable
Execution👀 Lazy (starts on subscribe)
Cancellation🛑 Unsubscription support
Async Flow⚡ Handles events and promises
Ecosystem🧩 Works with Angular and React

🆚 Summary: Key Differences

Featurerxjsrxjs-compat
Status✅ Active Standard⚠️ Deprecated / Legacy
Imports📦 Modular (rxjs/operators)🗂️ Deep paths (rxjs/Observable)
Operators🛠️ Pipeable (.pipe())🔗 Prototype chaining
Tree-Shaking🌲 Supported❌ Limited / None
Version Support🚀 v6, v7+🕰️ v6 only (migration aid)
Bundle Size📉 Optimized📈 Larger due to compat layer

💡 The Big Picture

rxjs is the foundation for modern reactive development 🏗️. It offers a clean, modular API that works well with modern bundlers and TypeScript. Use this for any new work or when updating existing apps to current standards.

rxjs-compat was a temporary bridge 🌉 for teams stuck on version 5. It allowed them to upgrade the core library without rewriting every file at once. However, it is now obsolete. Keeping it in your project blocks future upgrades and adds unnecessary weight.

Final Thought: If you see rxjs-compat in your dependencies, treat it as technical debt. Plan a sprint to refactor imports to the standard rxjs paths so you can remove the compat package and move to the latest version.

How to Choose: rxjs vs rxjs-compat

  • rxjs:

    Choose rxjs for all new projects and when upgrading to RxJS version 7 or higher. It is the actively maintained standard with modular imports and better tree-shaking support. This package ensures your application stays current with security patches and performance improvements.

  • rxjs-compat:

    Choose rxjs-compat only if you are temporarily migrating a large codebase from RxJS version 5 to version 6. Do not use it for new projects because it is deprecated and increases bundle size. You should plan to remove this dependency as soon as the migration is complete.

README for rxjs

RxJS Logo RxJS: Reactive Extensions For JavaScript

CI npm version Join the chat at https://gitter.im/Reactive-Extensions/RxJS

The Roadmap from RxJS 7 to 8

Curious what's next for RxJS? Follow along with Issue 6367.

RxJS 7

FOR 6.X PLEASE GO TO THE 6.x BRANCH

Reactive Extensions Library for JavaScript. This is a rewrite of Reactive-Extensions/RxJS and is the latest production-ready version of RxJS. This rewrite is meant to have better performance, better modularity, better debuggable call stacks, while staying mostly backwards compatible, with some breaking changes that reduce the API surface.

Apache 2.0 License

Versions In This Repository

  • master - This is all of the current work, which is against v7 of RxJS right now
  • 6.x - This is the branch for version 6.X

Most PRs should be made to master.

Important

By contributing or commenting on issues in this repository, whether you've read them or not, you're agreeing to the Contributor Code of Conduct. Much like traffic laws, ignorance doesn't grant you immunity.

Installation and Usage

ES6 via npm

npm install rxjs

It's recommended to pull in the Observable creation methods you need directly from 'rxjs' as shown below with range. If you're using RxJS version 7.2 or above, you can pull in any operator you need from the same spot, 'rxjs'.

import { range, filter, map } from 'rxjs';

range(1, 200)
  .pipe(
    filter(x => x % 2 === 1),
    map(x => x + x)
  )
  .subscribe(x => console.log(x));

If you're using RxJS version below 7.2, you can pull in any operator you need from one spot, under 'rxjs/operators'.

import { range } from 'rxjs';
import { filter, map } from 'rxjs/operators';

range(1, 200)
  .pipe(
    filter(x => x % 2 === 1),
    map(x => x + x)
  )
  .subscribe(x => console.log(x));

CDN

For CDN, you can use unpkg:

https://unpkg.com/rxjs@^7/dist/bundles/rxjs.umd.min.js

The global namespace for rxjs is rxjs:

const { range } = rxjs;
const { filter, map } = rxjs.operators;

range(1, 200)
  .pipe(
    filter(x => x % 2 === 1),
    map(x => x + x)
  )
  .subscribe(x => console.log(x));

Goals

  • Smaller overall bundles sizes
  • Provide better performance than preceding versions of RxJS
  • To model/follow the Observable Spec Proposal to the observable
  • Provide more modular file structure in a variety of formats
  • Provide more debuggable call stacks than preceding versions of RxJS

Building/Testing

  • npm run compile build everything
  • npm test run tests
  • npm run dtslint run dtslint tests

Adding documentation

We appreciate all contributions to the documentation of any type. All of the information needed to get the docs app up and running locally as well as how to contribute can be found in the documentation directory.