【问题标题】:How to conditional bootstrap angular app?如何有条件地引导角度应用程序?
【发布时间】:2019-12-24 14:09:07
【问题描述】:

我正在尝试根据条件引导我的 Angular 5 应用程序。基本上我有两个模块MobileModuleWebModule,分别包含web和mobile的UI组件。

如果用户在移动浏览器中打开了应用程序,我正在尝试引导MobileModule,否则WebModule

这是我的main.ts 来源。

import { enableProdMode }         from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { environment }    from './environments/environment';

import { AppSettings }    from './app/core/app-settings';
import { MobileModule }   from './app/mobile/mobile.module';
import { WebModule }      from './app/web/web.module';


if (environment.production) {
    enableProdMode();
}


/*
 * Bootstrap mobile or web module based on mobile
 * or desktop client.
 */
if (AppSettings.isMobileDevice) {

  platformBrowserDynamic().bootstrapModule(MobileModule)
      .catch(err => console.log(err));
} else {

  platformBrowserDynamic().bootstrapModule(WebModule)
      .catch(err => console.log(err));
}

web.module.ts

import { BrowserModule }  from '@angular/platform-browser';
import { NgModule }       from '@angular/core';

import { AppRoutingModule } from './app-routing/app-routing.module';
import { CoreModule }       from '../core/core.module';
import { SharedModule }     from '../shared/shared.module';
import { AuthModule }       from './auth/auth.module';

import { SignupComponent }  from './auth/signup/signup.component';


@NgModule({
  imports: [
    BrowserModule,        // Support for common angular directives and services
    AppRoutingModule,     // Web routing controller module.
    CoreModule,           // Core modules
    SharedModule,         // Shared modules
    AuthModule,           // App authentication module (signup and login)
  ],
  declarations: [],
  providers: [],
  bootstrap: [SignupComponent]    // Bootstrap Signup component
})
export class WebModule { }

mobile.module.ts

import { BrowserModule }  from '@angular/platform-browser';
import { NgModule }       from '@angular/core';

import { AppRoutingModule } from './app-routing/app-routing.module';
import { CoreModule }       from '../core/core.module';
import { SharedModule }     from '../shared/shared.module';
import { AuthModule }       from './auth/auth.module';

import { SignupComponent }  from './auth/signup/signup.component';


@NgModule({
  imports: [
    BrowserModule,        // Support for common angular directives and services
    AppRoutingModule,     // Mobile app routing controller module
    CoreModule,           // Core modules
    SharedModule,         // Shared modules
    AuthModule,           // App authentication module (signup and login)
  ],
  declarations: [],
  providers: [],
  bootstrap: [SignupComponent]    // Bootstrap Signup component
})
export class MobileModule { }

上述方法适用于ng serve,但是当我尝试使用ng serve --aot 选项运行它时,它在chrome 控制台中抛出错误。

Uncaught Error: No NgModule metadata found for 'WebModule'.  
    at NgModuleResolver.resolve (compiler.js:20242)  
    at CompileMetadataResolver.getNgModuleMetadata (compiler.js:15195)  
    at JitCompiler._loadModules (compiler.js:34405)  
    at JitCompiler._compileModuleAndComponents (compiler.js:34366)  
    at JitCompiler.compileModuleAsync (compiler.js:34260)  
    at CompilerImpl.compileModuleAsync (platform-browser-dynamic.js:239)  
    at PlatformRef.bootstrapModule (core.js:5567)  
    at eval (main.ts:26)  
    at Object../src/main.ts (main.bundle.js:53)  
    at __webpack_require__ (inline.bundle.js:55)  

我的项目结构是

|-node_modules
|-src
   |-app
      |-core
      |-mobile
         |-mobile.module.ts
      |-shared
      |-web
         |-web.module.ts

我尝试了几件事来有条件地引导应用程序,但没有成功。任何建议将不胜感激。

【问题讨论】:

  • 请同时添加两个模块文件
  • @AnasBinNazeer 我已经更新了两个模块源。
  • 你可以尝试升级 typescript 和 angular-cli 版本吗?
  • 试过但没有成功。打字稿版本^2.6.2 和角度cli 1.7.3

标签: angular typescript angular2-bootstrapping


【解决方案1】:

我认为 Angular 5 不支持多个根模块,因为 AOT(Ahead of Time 编译)目前的工作方式。它似乎只编译第一个模块及其依赖项。

一种解决方法是使用仅用于引导的根模块,并使用带 Guards 的路由器,并仅在根模块内延迟加载所需的模块。

参考资料:

【讨论】:

    【解决方案2】:

    经过大量研究,我发现我们一次只能引导单个模块。这意味着每个 Angular 应用程序只有一个根模块。

    但是,从angular lazy loading of modules 开始,我们可以动态加载所有功能模块。因此,我们的想法是加载一个根模块,并根据条件动态加载任何子模块。

    让我们考虑上面的例子。

    import { enableProdMode }         from '@angular/core';
    import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
    
    import { environment }    from './environments/environment';
    import { AppModule }      from './app/app.module';
    
    
    if (environment.production) {
        enableProdMode();
    }
    
    
    /*
     * Bootstrap single root module
     */
    platformBrowserDynamic().bootstrapModule(AppModule)
          .catch(err => console.log(err));
    

    app.module.ts

    import { BrowserModule }  from '@angular/platform-browser';
    import { NgModule }       from '@angular/core';
    import { RouterModule, Routes }     from '@angular/router';
    
    import { CoreModule }       from '../core/core.module';
    import { SharedModule }     from '../shared/shared.module';
    
    import { AppComponent }  from './app.component';
    
    
    const isMobileDevice = true; // Mobile device condition    
    
    
    const routes: Routes = [
      {
        path        : 'app',
        loadChildren: isMobileDevice ? './mobile/mobile.module#MobileModule' : './web/web.module#WebModule'    // Conditionally load mobile or web module
      }
    ];
    
    
    @NgModule({
      imports: [
        BrowserModule,        // Support for common angular directives and services
        RouterModule.forRoot(routes),
        CoreModule,           // Core modules
      ],
      declarations: [],
      providers: [],
      bootstrap: [AppComponent]    // Bootstrap Signup component
    })
    export class AppModule { }
    

    希望这对其他希望在他们的 Angular 应用中出现这种行为的人有所帮助。

    【讨论】:

      【解决方案3】:

      我通过在 angular.json 文件中使用 fileReplacements 在配置下创建一个对象,实现了在 main.ts 中的模块的有条件加载,并在其中添加了如下替换:

      "fileReplacements": [
          {
              "replace": "src/environments/environment.ts",
              "with": "src/environments/environment.lib.ts"
          },
          {
              "replace": "src/main.ts",
              "with": "src/main.lib.ts"
          }
      ]
      

      以上解决了我的问题。

      希望这对某人有所帮助。

      谢谢...

      【讨论】:

        猜你喜欢
        • 2013-12-02
        • 1970-01-01
        • 1970-01-01
        • 2023-03-16
        • 2014-12-30
        • 2017-10-16
        • 2016-11-26
        • 1970-01-01
        • 2018-11-20
        相关资源
        最近更新 更多