导入可出租的 RxJS 操作符 [英] Importing lettable RxJS operators

查看:16
本文介绍了导入可出租的 RxJS 操作符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

RxJS 5.5 进行了重大的突破性更改并引入了 lettable 运算符 基本上替换了我们以前使用的所有运算符(称为补丁"运算符).

RxJS 5.5 makes a big breaking change and introduces lettable operators to replace basically all operators (called "patch" operators) we used to use before.

那篇文章包含一个注释:

That article contains a note:

Lettable 操作符现在可以从 rxjs/operators 导入,但是做所以不改变你的构建过程通常会导致更大的应用程序包.这是因为默认情况下 rxjs/operators 会解析为 rxjs 的 CommonJS 输出.

Lettable operators can now be imported from rxjs/operators, but doing so without changing your build process will often result in a larger application bundle. This is because by default rxjs/operators will resolve to the CommonJS output of rxjs.

这个声明很容易在使用全新的 AngularCLI 生成的应用程序的实践中证明.

This statement is easy to proof on the practice with the brand new AngularCLI-generated app.

当我们有一个不从 RxJS 导入任何东西的应用程序时:

When we have an application that doesn't import anything from RxJS:

import { Component, OnInit } from '@angular/core';
import { HttpClient } from "@angular/common/http";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  public title = 'app';

  constructor(private readonly http: HttpClient) {
  }

  public ngOnInit(): void {
    this.http.get('https://api.github.com/users')
      .subscribe(response => {
        console.log(response);
      });
  }
}

我们可以看到:

ng build --prod
chunk {0} polyfills.e1f97a0070e18e96a6be.bundle.js (polyfills) 61.4 kB {4} [initial] [rendered]
chunk {1} main.b2b5d212102ca9d103e8.bundle.js (main) 4.92 kB {3} [initial] [rendered]
chunk {2} styles.d41d8cd98f00b204e980.bundle.css (styles) 0 bytes {4} [initial] [rendered]
chunk {3} vendor.4b7be3dbe842aec3f0ab.bundle.js (vendor) 236 kB [initial] [rendered]
chunk {4} inline.387c7023e5627ac04221.bundle.js (inline) 1.45 kB [entry] [rendered]

当我们以旧"方式导入 RxJS 操作符并使用它时:

When we import a RxJS operator the "old" way and use it:

import { Component, OnInit } from '@angular/core';
import { HttpClient } from "@angular/common/http";
import "rxjs/add/operator/map";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  public title = 'app';

  constructor(private readonly http: HttpClient) {
  }

  public ngOnInit(): void {
    this.http.get('https://api.github.com/users')
      .map((u: any) => 1)
      .subscribe(response => {
        console.log(response);
      });
  }
}

我们看不到捆绑包的大小:

We can see no gain in size of bundles:

chunk {0} polyfills.e1f97a0070e18e96a6be.bundle.js (polyfills) 61.4 kB {4} [initial] [rendered]
chunk {1} main.229ad10195bbb426b3e8.bundle.js (main) 4.96 kB {3} [initial] [rendered]
chunk {2} styles.d41d8cd98f00b204e980.bundle.css (styles) 0 bytes {4} [initial] [rendered]
chunk {3} vendor.933334fc50e7008778fe.bundle.js (vendor) 236 kB [initial] [rendered]
chunk {4} inline.6a52179d8b19cd3cc179.bundle.js (inline) 1.45 kB [entry] [rendered]

当我们尝试按照推荐的方式导入和使用可出租运算符但不修改构建过程时:

When we try to import and use the lettable operator instead as recommended but without modifying the build process:

import { Component, OnInit } from '@angular/core';
import { HttpClient } from "@angular/common/http";
import { map } from "rxjs/operators";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  public title = 'app';

  constructor(private readonly http: HttpClient) {
  }

  public ngOnInit(): void {
    this.http.get('https://api.github.com/users').pipe(
        map((u: any) => 1))
      .subscribe(response => {
        console.log(response);
      });
  }
}

我们看到 vendor bundle 大了 108 kB,这告诉我们 RxJS 没有经过 tree-shaked:

We see that the vendor bundle is 108 kB bigger which tells us that RxJS hasn't been tree-shaked:

chunk {0} polyfills.e1f97a0070e18e96a6be.bundle.js (polyfills) 61.4 kB {4} [initial] [rendered]
chunk {1} main.450c741a106157402dcd.bundle.js (main) 4.97 kB {3} [initial] [rendered]
chunk {2} styles.d41d8cd98f00b204e980.bundle.css (styles) 0 bytes {4} [initial] [rendered]
chunk {3} vendor.3f53f0e2283f4c44ec38.bundle.js (vendor) 344 kB [initial] [rendered]
chunk {4} inline.2d973ef5a10aa806b082.bundle.js (inline) 1.45 kB [entry] [rendered]

当我尝试按照文章的 No Control over Build Process 部分中的建议导入可出租运算符时:

When I try to import the lettable operator as recommended in the No Control over Build Process section of the article:

import { map } from "rxjs/operators/map";

我收到构建错误:

./src/app/app.component.ts
Module not found: Error: Can't resolve 'rxjs/operators/map' in 'c:ProjectsAngularsrcapp'
 @ ./src/app/app.component.ts 14:0-41
 @ ./src/app/app.module.ts
 @ ./src/main.ts
 @ multi webpack-dev-server/client?http://localhost:4200 ./src/main.ts

  1. 我做错了什么?
  2. 我们如何在 Angular CLI 应用程序中导入新的 RxJS 可出租操作符这样 RxJS 仍然会被摇树吗?

更新: 包版本(基本上都是目前最新的 AngularCLI 应用想要的"版本):

UPDATE: Package versions (basically all are latest "wanted" versions of an AngularCLI app at the moment):

rxjs: 5.5.0
@angular/cli: 1.4.9
node: 8.6.0
os: win32 x64
@angular/animations: 4.4.6
@angular/common: 4.4.6
@angular/compiler: 4.4.6
@angular/core: 4.4.6
@angular/forms: 4.4.6
@angular/http: 4.4.6
@angular/platform-browser: 4.4.6
@angular/platform-browser-dynamic: 4.4.6
@angular/router: 4.4.6
@angular/cli: 1.4.9
@angular/compiler-cli: 4.4.6
@angular/language-service: 4.4.6
typescript: 2.3.4

推荐答案

为了完整性,@angular/cli@1.4.9 在 models/webpack-configs/common.js 中添加了以下内容>

For completeness, @angular/cli@1.4.9 adds the following in models/webpack-configs/common.js

// Read the tsconfig to determine if we should prefer ES2015 modules.
// Load rxjs path aliases.
// https://github.com/ReactiveX/rxjs/blob/master/doc/lettable-operators.md#build-and-treeshaking
let alias = {};
try {
    const rxjsPathMappingImport = 'rxjs/_esm5/path-mapping';
    const rxPaths = require_project_module_1.requireProjectModule(projectRoot, rxjsPathMappingImport);
    alias = rxPaths(nodeModules);
}
catch (e) { }

    resolve: {
        extensions: ['.ts', '.js'],
        modules: ['node_modules', nodeModules],
        symlinks: !buildOptions.preserveSymlinks,
        alias
    },

rxjs/_esm5/path-mapping.js有这两个条目

"rxjs/operators": path.resolve(PATH_REPLACEMENT, "rxjs/_esm5/operators/index.js"),
...
"rxjs/operators/map": path.resolve(PATH_REPLACEMENT, "rxjs/_esm5/operators/map.js"),

错误信息的基本部分是

aliased with mapping 'rxjs/operators': 
  'C:DevProjects
x55
ode_modules
xjs\_esm5operatorsindex.js' to 
  'C:DevProjects
x55
ode_modules
xjs\_esm5operatorsindex.js/map'
...
C:DevProjects
x55
ode_modules
xjs\_esm5operatorsindex.jsmap doesn't exist

所以第一个映射会干扰第二个.

so the first mapping is interfering with the second.

通过颠倒构建工作的映射顺序,所以在我看来,错误在于 rxjs v5.5.

By reversing the order of the mappings the build works, so to my mind the fault is with rxjs v5.5.

也就是说,Alexander 的变通方法是修复之前要采取的方法.

That said, Alexander's work-around is the path to take until the fix.

这篇关于导入可出租的 RxJS 操作符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆