Multiple modules in Angular 2

拜拜、爱过 提交于 2019-12-21 04:52:42

问题


I have an Angular 2 app (RC7) which started as a single component but is quickly becoming used throughout the project in various different (and sometimes completely unrelated) ways.

As a result of this, a single NgModule bootstrapping all the components seems like a terrible idea with a huge amount of bloat. I am struggling to find a way to have multiple modules (Module A would contain Component A, Module B would have Component B, etc) and still allow the bootstrapping of multiple A2 applications on a single page.

In practice, what I am trying to achieve is this:

Page 1 bootstraps Module A - this works.

Page 2 bootstraps Module B - this works.

Page 3 bootstraps Module A & Module B - this doesn't work.

index.html

<script src="/angular2/node_modules/zone.js/dist/zone.js"></script>
<script src="/angular2/node_modules/reflect-metadata/Reflect.js"></script>
<script src="/angular2/node_modules/systemjs/dist/system.src.js"></script>
<script src="/angular2/systemjs.config.js"></script>


<script type="text/javascript">
    System.import('appOne').catch(function(err){ console.error(err); });
    System.import('appTwo').catch(function(err){ console.error(err); });
</script>

systemjs.config.js

(function (global) {
    System.config({
        paths: {
            'npm:': '/angular2/node_modules/'
        },
        map: {
            appOne: '/angular2/',
            appTwo: '/angular2/',
        },
        packages: {
            appOne: {
                main: './appOne.main.js',
                defaultExtension: 'js'
            },
            appTwo: {
                main: './appTwo.main.js',
                defaultExtension: 'js'
            },
        }
    });
})(this);

AppOne and AppTwo's modules simply bootstrap the relevant component (componentOne & componentTwo). However, both will not render on the same page at the same time. I have no errors in the console, but whichever package is listed last within the systemjs.config.js file is the only one to load.

Can anyone see why it might not be working? Or perhaps recommend another way to structure my modules. I'd rather not have one parent module with all components, services, etc listed - this seems to defeat the point of Angular 2's nested Component trees, and will eventually affect page-load times exponentially.

Thanks in advance.


回答1:


You can boostrap an array of components from AppModule, something like this:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {AppComponent} from "./app.component";
import {MainSidebarComponent} from "./menus/main-sidebar.component";
import {FormsModule} from "@angular/forms";
import {appRouting} from "./app.routes";
import {DashBoardComponent} from "./dashboard/dashboard.component";
import {HomeComponent} from "./home/home.component";
import {LoginComponent} from "./login/login.component";
import {UsersModule} from "./users/users.module";
import {TopBarComponent} from "./menus/top-bar.component";

@NgModule({
    imports:      [
        BrowserModule,
        FormsModule,
        appRouting,

        UsersModule
    ],
    declarations: [
        AppComponent,
        MainSidebarComponent,
        TopBarComponent,
        DashBoardComponent,
        HomeComponent,
        LoginComponent
    ],
    bootstrap:    [ AppComponent, MainSidebarComponent, TopBarComponent ]
})
export class AppModule { }

Then in your index.html

<!doctype html>
<head>
    <base href="/">
    <meta charset="UTF-8">

    <!-- 1. Load libraries -->
    <!-- Polyfill(s) for older browsers -->
    <script src="node_modules/core-js/client/shim.min.js"></script>
    <script src="node_modules/zone.js/dist/zone.js"></script>
    <script src="node_modules/reflect-metadata/Reflect.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <!-- 2. Configure SystemJS -->
    <script src="systemjs.config.js"></script>
    <script>
        System.import('app').catch(function (err) {
            console.error(err);
        });
    </script>
</head>
<body class=" sidebar_main_open sidebar_main_swipe">

<header id="header_main">
 <top-bar></top-bar>
</header><


<aside id="sidebar_main">
    <main-sidebar></main-sidebar>
</aside>


<div id="page_content">
    <div id="page_content_inner">
        <my-app>Loading....</my-app>
    </div>
</div>
</body>
</html>



回答2:


For anyone interested, the issue was bootstrapping. Both apps have to be bootstrapped in unison in order to work.

index.html

<script src="/angular2/node_modules/zone.js/dist/zone.js"></script>
<script src="/angular2/node_modules/reflect-metadata/Reflect.js"></script>
<script src="/angular2/node_modules/systemjs/dist/system.src.js"></script>
<script src="/angular2/systemjs.config.js"></script>


<script type="text/javascript">
    System.import('appOneAndTwo').catch(function(err){ console.error(err); });
</script>

systemjs.config.js

(function (global) {
    System.config({
        paths: {
            'npm:': '/angular2/node_modules/'
        },
        map: {
            appOne: '/angular2/',
            appTwo: '/angular2/',
            appOneAndTwo: '/angular2/',
        },
        packages: {
            appOne: {
                main: './appOne.main.js',
                defaultExtension: 'js'
            },
            appTwo: {
                main: './appTwo.main.js',
                defaultExtension: 'js'
            },
            appOneAndTwo: {
                main: './appOneAndTwo.main.js',
                defaultExtension: 'js'
            },
        }
    });
})(this);

appOneAndTwo.main.ts

import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppOneModule} from './app/app.one.module';
import {AppTwoModule} from './app/app.two.module';

platformBrowserDynamic().bootstrapModule(CommentAppModule);
platformBrowserDynamic().bootstrapModule(WorkflowAppModule);

It's still not ideal as I have to create a new main.ts file for every combination of Angular 2 apps I create, but it does mean the imports are only imported strictly when necessary and the payload isn't bloated to the end user.

I am currently looked at the AoT compiler (https://angular.io/docs/ts/latest/cookbook/aot-compiler.html) and uglification/minification using Webpack to further reduce payload size.




回答3:


I don't know if you can achieve the exact solution you want, but you could try to lazy-load some of your modules.

For instance, you create an AppModule (used in bootstrapping). In AppModule you only import your "home" module (I'm gonna call it HomeModule).

Than all the other modules can be lazy-loaded (reference)



来源:https://stackoverflow.com/questions/39836000/multiple-modules-in-angular-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!