无需rxjs-compat,在RxJS 6中如何仅导入已用操作符?
RxJS 6 按需导入实现减小打包体积的正确方式
嘿,我明白你现在的困扰——之前用RxJS老版本靠单独导入操作符能把vendor体积压得很小,换成RxJS6不依赖compat之后,怎么试都没法避免打包整个库,对吧?我来给你捋捋问题出在哪,以及正确的做法:
首先,RxJS6的模块结构和导入逻辑跟之前完全不一样了,你之前沿用的旧导入路径(比如rxjs/Observable、rxjs/operators/map)其实是坑!这些旧路径的模块内部会偷偷导入整个RxJS库,直接导致Webpack没法做摇树优化,所以你的bundle里才会出现所有操作符。
第一步:修正导入方式(核心!)
RxJS6把所有核心类都统一放到了rxjs主模块下,操作符则全部集中在rxjs/operators里,而且_throw已经改名为throwError了,正确的导入应该是这样:
// 核心类统一从rxjs导入 import { Observable, Subscription, Subject, throwError } from 'rxjs'; // 操作符从rxjs/operators统一导入,不用每个操作符单独写子路径 import { map, mergeMap, catchError, finalize } from 'rxjs/operators';
你之前的vendor.ts和业务代码里的导入都是旧路径,这是导致体积过大的根本原因,一定要改成上面这种写法。
第二步:修正操作符的使用方式
RxJS6废弃了原型链挂载操作符的方式,所有操作符都要通过pipe方法串联调用,比如之前的:
// 旧写法(RxJS5及之前) myObservable.map(res => res.data).mergeMap(id => fetchDetail(id)).catch(err => handleErr(err))
现在必须改成:
// 新写法(RxJS6) myObservable.pipe( map(res => res.data), mergeMap(id => fetchDetail(id)), catchError(err => handleErr(err)), finalize(() => cleanUp()) )
第三步:确保打包配置正确(针对Webpack 3)
你提到已经改了Webpack配置,但要确认这几点:
- 如果你用Babel,一定要在
.babelrc里设置presets: [['env', { modules: false }]],因为只有ES模块语法才能被Webpack摇树,转成CommonJS就不行了。 - 开启
webpack.optimize.ModuleConcatenationPlugin,这个插件能帮助Webpack更好地分析和剔除未使用的代码。 - 打包时一定要用
production模式,只有生产模式下Webpack才会自动开启摇树和代码压缩。
额外提醒:避开这些坑
- 绝对不要写
import 'rxjs';,这会直接把整个RxJS库打包进去,体积瞬间爆炸。 - 如果你用的是Angular CLI,早期版本对RxJS6的摇树支持有问题,升级到最新稳定版应该能解决类似你提到的issue里的问题。
按照上面的步骤改完之后,再用Webpack Bundle Analyzer看一下,应该就能看到只有你用到的核心类和操作符被打包进去了。
内容的提问来源于stack exchange,提问作者Sandro Simas
相关产品推荐
相关产品推荐

