Skip to main content
There are different ways to import RxJS depending on your version and build setup. Understanding the import patterns helps you take advantage of tree-shaking and optimize your bundle size.

Modern Import Patterns (v7.2.0+)

Starting with RxJS v7.2.0, most operators have been moved to the main 'rxjs' export site. The 'rxjs/operators' export site is now deprecated.
The preferred way to import operators is now from 'rxjs':
import { of, map, filter, take } from 'rxjs';

of(1, 2, 3, 4, 5)
  .pipe(
    filter(x => x % 2 === 0),
    map(x => x * 2),
    take(2)
  )
  .subscribe(console.log);
// Output: 4, 8

Export Sites

RxJS v7 provides 6 different export locations for different functionality:
1

rxjs - Core Library

The main export site includes Observable, operators, creation functions, subjects, and schedulers.
import { Observable, of, map, Subject, asyncScheduler } from 'rxjs';
2

rxjs/operators - Legacy Operators

Deprecated location for operators. Only contains legacy operators that have been replaced.
// Avoid this - use the new operators from 'rxjs' instead
import { map } from 'rxjs/operators';
3

rxjs/ajax - AJAX Utilities

Specialized exports for making AJAX requests.
import { ajax } from 'rxjs/ajax';

ajax.getJSON('https://api.example.com/data')
  .subscribe(data => console.log(data));
4

rxjs/fetch - Fetch API

Observables for the Fetch API.
import { fromFetch } from 'rxjs/fetch';
import { switchMap, catchError } from 'rxjs';

fromFetch('https://api.example.com/data')
  .pipe(
    switchMap(response => response.json()),
    catchError(err => of({ error: err.message }))
  )
  .subscribe(result => console.log(result));
5

rxjs/webSocket - WebSocket

Observable-based WebSocket implementation.
import { webSocket } from 'rxjs/webSocket';

const socket$ = webSocket('ws://localhost:8081');

socket$.subscribe(
  msg => console.log('message received: ' + msg),
  err => console.log(err),
  () => console.log('complete')
);

socket$.next({ message: 'Hello Server!' });
6

rxjs/testing - Test Utilities

Testing utilities including TestScheduler for marble testing.
import { TestScheduler } from 'rxjs/testing';

const testScheduler = new TestScheduler((actual, expected) => {
  expect(actual).toEqual(expected);
});

Tree-Shaking Benefits

Modern bundlers like Webpack, Rollup, and esbuild automatically eliminate unused code when you use ES module imports.
By importing only what you need, you can significantly reduce your bundle size:
// Good: Only includes Observable, of, and map in your bundle
import { of, map } from 'rxjs';

const result$ = of(1, 2, 3).pipe(map(x => x * 2));
// Avoid: Imports the entire RxJS library
import * as rxjs from 'rxjs';
// Even if you only use a few operators, all exports are included in the bundle

Migrating from Legacy Operators

Some operators from 'rxjs/operators' have been deprecated and replaced:
Legacy OperatorStatic CreationNew Operator Name
combineLatestcombineLatestcombineLatestWith
concatconcatconcatWith
mergemergemergeWith
onErrorResumeNextonErrorResumeNextonErrorResumeNextWith
raceraceraceWith
zipzipzipWith
import { merge } from 'rxjs/operators';

a$.pipe(merge(b$)).subscribe();

CommonJS vs ESM

RxJS is primarily designed for ES modules. CommonJS support is maintained for compatibility but may have larger bundle sizes.
import { of, map } from 'rxjs';

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

TypeScript Configuration

For optimal TypeScript support, ensure your tsconfig.json includes:
tsconfig.json
{
  "compilerOptions": {
    "target": "ES2015",
    "module": "ES2015",
    "moduleResolution": "node",
    "lib": ["ES2015", "DOM"],
    "esModuleInterop": true
  }
}

CDN Usage

When using RxJS from a CDN, all exports are available under the global rxjs namespace.
<!-- Include RxJS from CDN -->
<script src="https://unpkg.com/rxjs@7/dist/bundles/rxjs.umd.min.js"></script>

<script>
  const { of, map, filter } = rxjs;
  
  of(1, 2, 3, 4, 5)
    .pipe(
      filter(x => x % 2 === 0),
      map(x => x * 2)
    )
    .subscribe(x => console.log(x));
</script>

Best Practices

1

Use Named Imports

Import only what you need for optimal tree-shaking:
import { of, map, filter } from 'rxjs';
2

Avoid Namespace Imports in Production

Namespace imports can prevent tree-shaking:
// Avoid in production code
import * as rxjs from 'rxjs';
3

Group Related Imports

Organize imports by functionality:
// Creation functions
import { of, from, interval } from 'rxjs';

// Operators
import { map, filter, take, debounceTime } from 'rxjs';

// Subjects
import { Subject, BehaviorSubject } from 'rxjs';
4

Use Subpath Imports for Specialized Features

Keep your bundle lean by using subpath imports:
import { ajax } from 'rxjs/ajax';
import { webSocket } from 'rxjs/webSocket';
import { TestScheduler } from 'rxjs/testing';