如何在 Angular 5 通用应用程序中排除浏览器模块

How to exclude browser modules from being built in Angular 5 Universal app

我正在尝试创建一个 Angular 通用应用程序,它在构建时构建一个特定的路由,以将应用程序 Shell 注入 Index.html 页面,作为在其中获取有意义内容的一种方式尽快出现在用户面前(Angular 应用程序正在下载)。我按照 Angular University 中的说明进行操作,并按照说明进行操作。但是,当我系统地将现有应用程序的功能添加到此测试应用程序中时,我 运行 进入 'Unexpected token import' 错误,该错误源于浏览器应用程序所需的第 3 方插件,但不是非常需要简单的服务器应用程序我正在尝试构建并注入 Index.html 作为我的应用程序 Shell.

我花了几个小时研究这个,发现有很多帖子推荐 webpack,但是,我使用的是 Angular CLI。我不确定如何将 webpack 与 Angular CLI 构建过程结合起来。

我发现这个 post 似乎表明您可以使用 tsconfig.server.json 的排除部分从 Angular 通用构建中排除模块。我已经尝试在 tsconfig.server.json 中列出要排除的模块,但是,我仍然遇到 'Unexpected token import' 错误。

我有一个路由需要构建并注入到我的索引页面中。我会 hope/think 我应该能够排除绝大多数我的应用程序,因为它与创建应用程序无关 Shell。我认为 Angular 应该简单地构建为服务器应用程序注册的路由所需的必要位。

我正在使用 Angular CLI 版本 1.7.3 和 Angular 版本 5.2.4。

有没有人知道如何将不必要的模块排除在 Angular 通用应用程序之外?

感谢您的宝贵时间。

您可以尝试创建专门用于浏览器的第三个模块。 这个 BrowserModule 将包含您在浏览器中需要的一切。

import { NgModule } from '@angular/core';    
import { AppModule} from './app.module';
import { AppComponent } from './app.component';
// other browser exlusive imports

@NgModule({
  imports: [
    // browser exlusive imports
    AppModule
  ],
  bootstrap: [AppComponent]
})
export class AppBrowserModule { }

然后你 bootstrap 这个新模块而不是 main.ts 文件中的 AppModule。这个 Whosebug 问题中也讨论了这种方法:
这里要在服务器上排除的模块是 BrowserAnimationsModule,但对于您不需要的任何其他模块,它应该几乎相同服务器。
如果您需要将脚本包含到浏览器中,您可以将它们导入到您的 main.ts 中,并且它们应该可用于您的整个应用程序。

如果您需要检查您是否在浏览器上,您可以使用来自 angular 的 isPlatformBrowser:https://angular.io/api/common/isPlatformBrowser
@Optional 装饰器也可以非常方便(https://angular.io/api/core/Optional),如果你想通过依赖注入只在你的组件或服务之一的浏览器上包含一些东西。
您可能需要这些来防止错误,这些错误是由于服务器呈现的应用程序中缺少文件而引起的。

您描述的 import-bug 是由于 third-party 库没有正确构建它们的库。解决此问题的一种简单方法是对抛出这些错误的文件使用 babel。 例如,如果您有一个名为 "failingPackage":

的包
babel ./node_modules/failingPackage -d ./node_modules/failingPackage --presets es2015

你基本上是在编译损坏包的所有文件,并用新文件覆盖旧文件。我告诉你这种方法,因为你可能 运行 在你想在你的服务器呈现的应用程序上使用的包上遇到这个错误。

您可以在此处阅读有关此问题的更多信息:https://github.com/angular/angular-cli/issues/7200

这里讨论babel的解决方案:https://github.com/SebastianM/angular-google-maps/issues/1052 全部归功于 Anthony Nahas。

或者您可以尝试这个解决方案:

  • 使用 ng eject 创建一个 webpack.config.js
  • 安装webpack-node-externals
  • 将 webpack.config.js
  • 的外部部分中的失败包列入白名单

以下方法对我有用。假设我想使用浏览器动画库 PIXI.js。所以,就这样吧。请注意,我在 if (this.isBrowser) 条件中使用 import。因此,只有当平台是浏览器时,才会导入并执行该库。

import { AfterViewInit, Component, OnInit, Inject, PLATFORM_ID } from '@angular/core';
import { Router } from '@angular/router';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';

@Component({
  selector: 'app-front-face',
  templateUrl: './front-face.component.html',
  styleUrls: ['./front-face.component.scss']
})
export class FrontFaceComponent implements OnInit, AfterViewInit {

  constructor(private router: Router,
    @Inject(PLATFORM_ID) private platformId: string) { }

  ngOnInit() {
    this.isBrowser = isPlatformBrowser(this.platformId);
  }

  constructor(private router: Router,
    @Inject(PLATFORM_ID) private platformId: string) { }

  ngOnInit() {
    this.isBrowser = isPlatformBrowser(this.platformId);
  }

  ngAfterViewInit() {
    if (this.isBrowser) {

        import('pixi.js').then(PIXI => {
          this.renderer = PIXI.autoDetectRenderer({ transparent: true });
          this.stage = new PIXI.Container();
          // Other PIXI related calls
        });
    }
  }
}