2017-10-20 125 views
3

RxJS 5.5做出了重大改變,並引入了lettable operators來替換我們以前用過的所有運營商(稱爲「運營商」)。導入可出租的RxJS運營商

該文章包含一張紙條:

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生成的應用實踐證明。

當我們不從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操作「舊」方式使用方法:

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); 
     }); 
    } 
} 

我們可以看到,在束的大小沒有增益:

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] 

當我們嘗試導入和使用可出租操盤建議,但沒有修改構建過程:

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); 
     }); 
    } 
} 

我們看到供應商捆綁是108 KB更大的告訴我們,RxJS不是招」牛逼了樹搖動:

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節推薦:

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

我得到生成錯誤:

./src/app/app.component.ts 
Module not found: Error: Can't resolve 'rxjs/operators/map' in 'c:\Projects\Angular\src\app' 
@ ./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仍然會被樹形搖動?

UPDATE:包版本(基本全是最新的 「通緝令」 在此刻的AngularCLI應用程序的版本):

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 
+0

這可能相當令人驚訝,請參閱https://github.com/webpack/webpack/issues/2867 – kemsky

+0

@kemsky:感謝您的信息!在我提供的文章中解釋了它不是樹狀搖擺的原因。問題基本上是如何用當前的AngularCLI構建系統來解決它呢? –

+0

您可以發佈'ng版本'輸出。我發現@ angular/cli沒有構建錯誤:1.2.0,@angular/___:4.4.6,[email protected]。 –

回答

2

爲了完整起見,@角/ CLI @ 1.4.9增加了在以下型號/的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 /路徑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:\Dev\Projects\rx55\node_modules\rxjs\_esm5\operators\index.js' to 
    'C:\Dev\Projects\rx55\node_modules\rxjs\_esm5\operators\index.js/map' 
... 
C:\Dev\Projects\rx55\node_modules\rxjs\_esm5\operators\index.js\map doesn't exist 

所以第一映射與所述第二干擾。

通過顛倒映射順序的構建工作,所以在我看來,故障是與rxjs v5.5。

這就是說,亞歷山大的解決方法是直到修復的路徑。

1
  1. 確保你真正使用至少5.5.0 。否則,請檢查文件node_modules/rxjs/operators/map.js是否存在,因爲我不知道該怎麼辦。同樣使用import { map } from "rxjs/operators";導入下面的相同文件,所以我懷疑你的編譯系統有問題。

  2. 使用操作符的正確方法是將它們導入表格rxjs/operators/*(例如,像您使用import { map } from "rxjs/operators/map";那樣)。

    如果您從rxjs/operators導入,則與從rxjs導入RxJS < 5.5中的情況相同。0因爲您實際上正在導入rxjs/operators/index,請參閱https://github.com/ReactiveX/rxjs/blob/master/src/operators/index.ts

    這就是爲什麼它沒有得到「樹木動搖」,它導入了index.ts中列出的所有運營商。

+0

我檢查了我的RxJS版本,它是5.5.0。該文件確實存在。在我的問題中,我在全新的AngularCLI生成的應用程序上進行了測試 - 您可以輕鬆地自行檢查。這不是一個構建系統問題。那篇文章演示瞭如果您無法修改構建過程以添加「ModuleConcnationnationPlugin」插件,以便從「rxjs/operators/map」;中導入像import [map}樹搖可出租操作員。我不確定爲什麼它不能找到使用深度進口的東西。也許這與AngularCLI構建設置有關? –

1

事實證明(學分@RichardMatsen),它在angular-cli 1.4.9的錯誤。

嘗試深進口(如import { map } from "rxjs/operators/map";)與angular-cli 1.4.8,沒有生成錯誤和包大小爲:

chunk {0} polyfills.e1f97a0070e18e96a6be.bundle.js (polyfills) 61.4 kB {4} [initial] [rendered] 
chunk {1} main.d36cf6834f640163ff35.bundle.js (main) 4.97 kB {3} [initial] [rendered] 
chunk {2} styles.d41d8cd98f00b204e980.bundle.css (styles) 0 bytes {4} [initial] [rendered] 
chunk {3} vendor.658e9efd9845db281b29.bundle.js (vendor) 241 kB [initial] [rendered] 
chunk {4} inline.c9d245ca6c859aaeef69.bundle.js (inline) 1.45 kB [entry] [rendered] 

其中僅會顯示5 KB收益相比,完全不使用RxJS運營商版本。

因此,現在我們至少有一個解決辦法:留在angular-cli 1.4.8和進口深進口喜歡可出租operatirs:

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