Click here to Skip to main content
13,141,821 members (69,629 online)
Click here to Skip to main content
Add your own
alternative version

Stats

8.1K views
141 downloads
3 bookmarked
Posted 7 Mar 2017

A Note on Angular 2 Bootstrap Multiple Apps

, 7 Mar 2017
Rate this:
Please Sign up or sign in to vote.
This is a note on how to bootstrap multiple apps in a single HTML page.

Introduction

This is a note on how to bootstrap multiple apps in a single HTML page.

Background

The Angular's website has examples on how to bootstrap an Angular application, but the examples only bootstrap a single application in an HTML page. It is not absolutely necessary, but you may find the need to bootstrap multiple applications in a single HTML page.

  • Structural reason - In an ASP.NET MVC application, you typically put the components common to all the pages into the layout page. You may want to bootstrap these components separately from the page specific components;
  • Performance reason - By default, the scope of the Angular's change detection is the whole component tree in the application. If you know that the actions (DOM events, and callbacks) in certain components have no impact on the states of the other components, you may want to bootstrap them separately, so the change detection runs in a smaller scope.

The attached example is an ASP.NET MVC application in Visual Studio 2015 Update 3. If you want to run it, I strongly recommend you to take a look at my early posting, because it is not a trivial task to compile and run an Angular 2 application of Typescript.

The example bootstraps two angular applications in a single HTML page.

  • The components for each Angular application are in the "app1" and "app2" folders;
  • The "shared-sub-component" and the "math-service" are shared in both Angular applications to demonstrate that different bootstraps can share common code;
  • Both Angular applications will be bootstrapped in the "Index.cshtml" page.

The following sections are a little verbose just for completeness. If you are interested in bootstrapping multiple Angular applications only, you can skip most of them.

The Shared Service and the Shared Component

In order to demonstrate that different bootstraps can share common code, I created a simple service and a simple component.

import { Injectable } from '@angular/core';
    
@Injectable()
export class MathService {
    public AddOne(n) {
        return n + 1;
    }
}

The "math-service.ts" performs a simple math operation. It will be used in all the components to demonstrate that the code of an Angular service can be shared among components bootstrapped separately.

import { Component, DoCheck } from '@angular/core';
import { MathService } from '../../services/math-service';
    
@Component({
    selector: 'shared-sub-component',
    template: '<div class="component">' +
    '<h3>Shared Component</h3>' +
    '<div><button (click)="Add()">Click to add Count</button>' +
    '&nbsp;-&nbsp;{{Count}}</div>' +
    '</div>'
})
    
export class SharedSubComponent implements DoCheck {
    public Count = 0;
    constructor(private math: MathService) { }
    
    public ngDoCheck() {
        console.log('Shared Change detection!')
    }
    
    public Add() {
        this.Count = this.math.AddOne(this.Count);
    }
}

The "shared-sub-component.ts" implements an Angular component. It will be used as a sub-component by the other components to demonstrate that an Angular component can be shared among components bootstrapped separately.

The Angular App No.1

In this note, I will bootstrap two Angular applications in the same web page. The first application is implemented in the "app1" folder.

The "component-1.ts" implements the application's only component.

import { Component, DoCheck } from '@angular/core';
import { MathService } from '../../services/math-service';
    
@Component({
    selector: 'component-1',
    template: '<div class="component">' +
    '<h3>Component-1</h3>' +
    '<div><button (click)="Add()">Click to add Count</button>' +
    '&nbsp;-&nbsp;{{Count}}</div>' +
    '<shared-sub-component></shared-sub-component>' +
    '</div>'
})
    
export class Component1 implements DoCheck {
    public Count = 0;
    constructor(private math: MathService) { }
    
    public ngDoCheck() {
        console.log('component-1 Change detection!')
    }
    
    public Add() {
        this.Count = this.math.AddOne(this.Count);
    }
}

The "component-1" components uses the "MathService" to make a simple math operation. It also uses the "shared-sub-component" as a sub-component. The "component-1" is packaged in the "app.module.ts" file.

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { Component1 } from './components/component-1';
import { SharedSubComponent } from '../common/components/shared-sub-component';
    
import { MathService } from '../services/math-service';
    
@NgModule({
    imports: [BrowserModule],
    providers: [
        MathService
    ],
    declarations: [
        Component1,
        SharedSubComponent
    ],
    bootstrap: [
        Component1
    ]
})
    
export class AppModule { }

The "AppModule" will be bootstrapped through the "app1.ts" file.

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
    
try { enableProdMode(); } catch(e) { }
const platform = platformBrowserDynamic();
    
platform.bootstrapModule(AppModule);

The Angular App No.2

The second Angular application is implemented in the "app2" folder. It is virtually the same as the first application. You do not need to spend time to look at it. It is listed here just for completeness.

The "component-2.ts" component.

import { Component, DoCheck } from '@angular/core';
import { MathService } from '../../services/math-service';
    
@Component({
    selector: 'component-2',
    providers: [
        MathService
    ],
    template: '<div class="component">' +
    '<h3>Component-2</h3>' +
    '<div><button (click)="Add()">Click to add Count</button>' +
    '&nbsp;-&nbsp;{{Count}}</div>' +
    '<shared-sub-component></shared-sub-component>' +
    '</div>'
})
    
export class Component2 implements DoCheck {
    public Count = 0;
    constructor(private math: MathService) { }
    
    public ngDoCheck() {
        console.log('component-2 Change detection!')
    }
    
    public Add() {
        this.Count = this.math.AddOne(this.Count);
    }
}

The "app.module.ts" module.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { Component2 } from './components/component-2';
import { SharedSubComponent } from '../common/components/shared-sub-component';
    
@NgModule({
    imports: [BrowserModule],
    declarations: [
        Component2,
        SharedSubComponent
    ],
    bootstrap: [
        Component2
    ]
})
    
export class AppModule { }

The "app2.ts" application.

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
    
try { enableProdMode(); } catch (e) { }
const platform = platformBrowserDynamic();
    
platform.bootstrapModule(AppModule);

The "systemjs.config.js" File

In order to bootstrap multiple Angular applications in a single web page, I made some change to the "systemjs.config.js" file from the Angular official web page.

// http://plnkr.co/edit/aZqdJe3OZ8K2odHioWkB?p=info
    
let ng2_getstarter = function (option) {
    let configuration = {
        paths: { 'npm:': option.npm },
        map: {
            app: option.appPath,
            '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
            '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
            '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
            '@angular/platform-browser':
                'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
            '@angular/platform-browser-dynamic':
                'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
            '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
            '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
            '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
    
            // other libraries
            'rxjs': 'npm:rxjs'
        },
        packages: {
            rxjs: {
                defaultExtension: 'js'
            },
            app: {
                defaultExtension: 'js'
            }
        }
    }
    
    System.config(configuration);
    
    return {
        bootstrap: function (appFile) {
            System.import(appFile).catch(function (err) { console.error(err);});
        }
    };
};
  • The "ng2_getstarter" function take a JSON "option" object and returns an object to bootstrap the Angular applications;
  • The "option" object needs to provide the path to the "npm" folder and the path to the root folder of the angular applications;

Boostrap the Applications

With the help of the "systemjs.config.js" file, bootstrapping multiple Angular applications in the same page is very simple. The "Index.cshtml" file shows how to use the "ng2_getstarter" function.

<body>
    <component-1></component-1>
    <component-2></component-2>
</body>

In the HTML section, we want to bootstrap both "component-1" and "component-2". The "component-1" is bundled in the "app1.ts" file and the "component-2" is bundled in the "app2.ts" file.

let ng_starter = ng2_getstarter({
    npm: '@Url.Content("~/node_modules/")',
    appPath: '@Url.Content("~/ngApp/")'
});
    
ng_starter.bootstrap('@Url.Content("~/ngApp/app1/app1.js")');
ng_starter.bootstrap('@Url.Content("~/ngApp/app2/app2.js")');
  • We can obtain a "ng_starter" object by passing the path to the "npm" folder and the path to the root of the Angular applications to the "ng2_getstarter" function;
  • To bootstrap the applications, we can simply call the "boostrap()" function on the "ng_starter" object by passing the path to each of the Angular application files.

The "TSC" Error

Depending on the Typescript compiler installed in your Visual Studio, you may encounter a problem to build the application. If you encounter the above error, it is very likely that you have a mis-matched version of Typescript compiler. You can take a look at my early post to figure out the solutions.

Build and Load the Web Page

If everything goes well, you can compile and load the web page into the browser.

You can see both Angular applications bootstrapped well in the same page. You can click on the buttons to check if they function well.

If you open the developer tool and take a look at the console, you can see that the button clicks in each application only trigger change detections within the same application. It should provide some performance advantages if you have no intention to allow the actions in one application to update the state of the other applications.

Points of Interest

  • This is a note on how to bootstrap multiple apps in a single HTML page;
  • It is not always necessary to bootstrap multiple applications in the same page, but it may be of some advantages under certain conditions;
  • I hope you like my postings and I hope this note can help you one way or the other.

History

First Revision - 3/5/2017.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Dr. Song Li
United States United States
I have been working in the IT industry for some time. It is still exciting and I am still learning. I am a happy and honest person, and I want to be your friend.

You may also be interested in...

Pro
Pro

Comments and Discussions

 
QuestionHow to load App1 component in App2 router-outlet and vice versa dynamically Pin
Member 1325778013-Jun-17 11:26
memberMember 1325778013-Jun-17 11:26 
QuestionUse case: ReDoc (Swagger Docs client) Pin
Michael Mooring8-May-17 11:33
memberMichael Mooring8-May-17 11:33 
GeneralMy vote of 5 Pin
Robert_Dyball8-Mar-17 9:10
memberRobert_Dyball8-Mar-17 9:10 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.170915.1 | Last Updated 7 Mar 2017
Article Copyright 2017 by Dr. Song Li
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid