2017-10-20 28 views
3

RxJS 5.5 effectue un changement important et introduit lettable operators pour remplacer fondamentalement tous les opérateurs (appelés opérateurs de "patch") que nous utilisions auparavant.Importation d'opérateurs RxJS lisible

Cet article contient une note:

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.

Cette déclaration est facile à la preuve sur la pratique avec la toute nouvelle application générée AngularCLI.

Lorsque nous avons une application qui n'importe pas quelque chose de 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); 
     }); 
    } 
} 

On peut voir les éléments suivants:

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] 

Lorsque nous importons un opérateur RxJS la « vieille » et utiliser:

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

on peut voir aucun gain de la taille des faisceaux:

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] 

Lorsque nous essayons d'importer et d'utiliser l'opérateur louable plutôt comme recommandé, mais sans modifier le processus de construction:

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

On voit que le faisceau de fournisseur est de 108 ko plus qui nous dit que RxJS hasn » t-Shaked été arbre:

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] 

Lorsque je tente d'importer l'opérateur comme recommandé dans louable la section No Control over Build Process de l'article:

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

Je reçois une erreur de construction:

./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. Ce que je fais mal?
  2. Comment pouvons-nous importer de nouveaux opérateurs RxJS Letting dans une application CLI Angular afin que RxJS soit encore arboré?

MISE À JOUR: versions de l'emballage (en gros sont toutes dernières "voulaient" versions d'une application AngularCLI pour le 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 
+0

Il pourrait être tout à fait surprenant, voir https://github.com/webpack/webpack/issues/2867 – kemsky

+0

@kemsky: Merci pour l'info! La raison pour laquelle ce n'est pas un arbre-shaked est expliqué dans l'article que j'ai fourni. La question est essentiellement comment contourner le problème avec le système de construction AngularCLI actuel? –

+0

Pourriez-vous publier la sortie 'ng version'? Je n'ai trouvé aucune erreur de construction avec @ angular/cli: 1.2.0, @angular/___: 4.4.6, [email protected] –

Répondre

2

Pour être complet, @ @ 1.4.9 angulaire/cli ajoute ce qui suit dans modèles/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 
    }, 

et rxjs/_esm5/path-mapping.js a ces deux entrées

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

Le bit essentiel du message d'erreur est

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 

de sorte que le premier mappage interfère avec la seconde. En inversant l'ordre des mappages, la construction fonctionne, donc, à mon avis, la faute est avec rxjs v5.5. Cela dit, le travail d'Alexander est la voie à suivre jusqu'à la solution.

1
  1. Assurez-vous que vous utilisez vraiment au moins 5.5.0 . Sinon, vérifiez que le fichier node_modules/rxjs/operators/map.js existe parce que je ne sais pas comment il pourrait ne pas. En utilisant également import { map } from "rxjs/operators"; importe le même fichier ci-dessous donc je me méfierais qu'il y ait quelque chose de mal avec votre système de construction.

  2. La bonne façon d'utiliser les opérateurs est de les importer sous la forme rxjs/operators/* (par exemple, comme vous l'avez fait avec import { map } from "rxjs/operators/map";).

    Si vous importez à partir de rxjs/operators, c'est la même chose que d'importer de rxjs dans RxJS < 5.5.0 parce que vous importez en fait rxjs/operators/index, voir https://github.com/ReactiveX/rxjs/blob/master/src/operators/index.ts.

    C'est pourquoi il n'a pas été "ébranlé", il a importé tous les opérateurs listés dans index.ts.

+0

J'ai vérifié ma version de RxJS, c'est 5.5.0. Le fichier existe en effet. Dans ma question, je l'ai testé sur la toute nouvelle application générée par AngularCLI - vous pouvez facilement la vérifier vous-même. Ce n'est pas un problème de système de construction. Cet article démontre que faire une importation profonde comme 'import {map} à partir de" rxjs/operators/map ";' est une façon alternative d'importer si vous ne pouvez pas modifier votre processus de construction pour ajouter le plugin 'ModuleConcatenationPlugin' afin de exploitants de maisons en bois. Je ne suis pas sûr pourquoi il ne peut pas trouver quelque chose en utilisant des importations profondes. Peut-être que c'est quelque chose lié aux paramètres de construction AngularCLI? –

1

Comme il est avéré (crédits @RichardMatsen), il y a un bogue dans angular-cli 1.4.9.

Trying importations profondes (comme import { map } from "rxjs/operators/map";) avec angular-cli 1.4.8, il n'y a pas d'erreurs de construction et de tailles d'ensembles sont:

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] 

Ce qui montre que le gain 5 kB par rapport à la version qui n'utilise pas les opérateurs de RxJS du tout .

Pour l'instant, nous avons au moins une solution de contournement: rester sur angular-cli 1.4.8 et importation operatirs avec les importations locatives profondes comme:

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