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':
Named Imports
Namespace Import
Global Bundle
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:
rxjs - Core Library
The main export site includes Observable, operators, creation functions, subjects, and schedulers. import { Observable , of , map , Subject , asyncScheduler } from 'rxjs' ;
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' ;
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 ));
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 ));
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!' });
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:
Deprecated Operators Migration Guide
Legacy Operator Static Creation New Operator Name combineLatestcombineLatestcombineLatestWithconcatconcatconcatWithmergemergemergeWithonErrorResumeNextonErrorResumeNextonErrorResumeNextWithraceraceraceWithzipzipzipWith
Old Way (Deprecated)
New Static Creation
New Pipeable Operator
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.
ESM (Recommended)
CommonJS
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:
{
"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
Use Named Imports
Import only what you need for optimal tree-shaking: import { of , map , filter } from 'rxjs' ;
Avoid Namespace Imports in Production
Namespace imports can prevent tree-shaking: // Avoid in production code
import * as rxjs from 'rxjs' ;
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' ;
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' ;