diff --git a/apps/multiple-parcels-same-config/child/project.json b/apps/multiple-parcels-same-config/child/project.json
new file mode 100644
index 00000000..3fede48d
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/project.json
@@ -0,0 +1,77 @@
+{
+ "name": "multiple-parcels-same-config-child",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "projectType": "application",
+ "sourceRoot": "apps/multiple-parcels-same-config/child/src",
+ "prefix": "single-spa-angular",
+ "targets": {
+ "build": {
+ "executor": "@angular-builders/custom-webpack:browser",
+ "options": {
+ "customWebpackConfig": {
+ "libraryTarget": "system",
+ "excludeAngularDependencies": true,
+ "path": "apps/multiple-parcels-same-config/child/webpack.config.ts"
+ },
+ "outputPath": "dist/apps/multiple-parcels-same-config-child",
+ "index": "apps/multiple-parcels-same-config/child/src/index.html",
+ "main": "apps/multiple-parcels-same-config/child/src/main.single-spa.ts",
+ "tsConfig": "apps/multiple-parcels-same-config/child/tsconfig.app.json",
+ "aot": true,
+ "assets": ["apps/multiple-parcels-same-config/child/src/favicon.ico", "apps/multiple-parcels-same-config/child/src/assets"],
+ "styles": ["apps/multiple-parcels-same-config/child/src/styles.scss"],
+ "deployUrl": "http://localhost:9000/"
+ },
+ "configurations": {
+ "development": {
+ "buildOptimizer": false,
+ "optimization": false,
+ "vendorChunk": true,
+ "extractLicenses": false,
+ "sourceMap": true,
+ "namedChunks": true
+ },
+ "production": {
+ "fileReplacements": [
+ {
+ "replace": "apps/multiple-parcels-same-config/child/src/environments/environment.ts",
+ "with": "apps/multiple-parcels-same-config/child/src/environments/environment.prod.ts"
+ }
+ ],
+ "optimization": true,
+ "outputHashing": "none",
+ "sourceMap": false,
+ "namedChunks": false,
+ "extractLicenses": true,
+ "vendorChunk": false,
+ "buildOptimizer": true,
+ "budgets": [
+ {
+ "type": "initial",
+ "maximumWarning": "2mb",
+ "maximumError": "5mb"
+ },
+ {
+ "type": "anyComponentStyle",
+ "maximumWarning": "6kb",
+ "maximumError": "10kb"
+ }
+ ]
+ }
+ },
+ "defaultConfiguration": "production"
+ },
+ "serve": {
+ "executor": "@angular-builders/custom-webpack:dev-server",
+ "options": {
+ "browserTarget": "multiple-parcels-same-config-child:build:development"
+ },
+ "configurations": {
+ "production": {
+ "browserTarget": "multiple-parcels-same-config-child:build:production"
+ }
+ }
+ }
+ },
+ "tags": []
+}
diff --git a/apps/multiple-parcels-same-config/child/src/app/app-routing.module.ts b/apps/multiple-parcels-same-config/child/src/app/app-routing.module.ts
new file mode 100755
index 00000000..ad10774a
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/src/app/app-routing.module.ts
@@ -0,0 +1,15 @@
+import { APP_BASE_HREF } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { EmptyRouteComponent } from './empty-route/empty-route.component';
+
+const routes: Routes = [
+ { path: '**', component: EmptyRouteComponent }
+];
+
+@NgModule({
+ imports: [RouterModule.forRoot(routes)],
+ exports: [RouterModule],
+ providers: [{ provide: APP_BASE_HREF, useValue: '/' }]
+})
+export class AppRoutingModule { }
diff --git a/apps/multiple-parcels-same-config/child/src/app/app.component.html b/apps/multiple-parcels-same-config/child/src/app/app.component.html
new file mode 100644
index 00000000..971fbd39
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/src/app/app.component.html
@@ -0,0 +1,4 @@
+
+
parcel name: {{props.name}}
+
time now is {{time}}
+
\ No newline at end of file
diff --git a/apps/multiple-parcels-same-config/child/src/app/app.component.ts b/apps/multiple-parcels-same-config/child/src/app/app.component.ts
new file mode 100644
index 00000000..8d79e319
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/src/app/app.component.ts
@@ -0,0 +1,26 @@
+import { Component } from '@angular/core';
+import { singleSpaPropsSubject } from '../single-spa/single-spa-props';
+import { first } from 'rxjs';
+
+@Component({
+ selector: 'multiple-parcels-same-config-child',
+ templateUrl: './app.component.html'
+})
+export class AppComponent {
+ constructor() {}
+
+ props: any = null;
+ time: number = Date.now();
+
+ ngOnInit() {
+ singleSpaPropsSubject
+ .pipe(first())
+ .subscribe((props) => {
+ this.props = props;
+ });
+
+ setInterval(() => {
+ this.time = Date.now();
+ }, 1000);
+ }
+}
diff --git a/apps/multiple-parcels-same-config/child/src/app/app.module.ts b/apps/multiple-parcels-same-config/child/src/app/app.module.ts
new file mode 100644
index 00000000..097863ad
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/src/app/app.module.ts
@@ -0,0 +1,21 @@
+import { ApplicationRef, DoBootstrap, NgModule } from '@angular/core';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { APP_BASE_HREF } from '@angular/common';
+
+import { AppComponent } from './app.component';
+import { AppRoutingModule } from './app-routing.module';
+import { EmptyRouteComponent } from './empty-route/empty-route.component';
+
+export const AppModule = (name: string) => {
+ @NgModule({
+ declarations: [AppComponent, EmptyRouteComponent],
+ imports: [BrowserAnimationsModule, AppRoutingModule],
+ providers: [],
+ })
+ class AppModule implements DoBootstrap {
+ ngDoBootstrap(appRef: ApplicationRef) {
+ appRef.bootstrap(AppComponent, `multiple-parcels-same-config-child-${name}`);
+ }
+ }
+ return AppModule;
+}
diff --git a/apps/multiple-parcels-same-config/child/src/app/empty-route/empty-route.component.ts b/apps/multiple-parcels-same-config/child/src/app/empty-route/empty-route.component.ts
new file mode 100755
index 00000000..b8380398
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/src/app/empty-route/empty-route.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app1-empty-route',
+ template: '',
+})
+export class EmptyRouteComponent {}
diff --git a/apps/multiple-parcels-same-config/child/src/assets/.gitkeep b/apps/multiple-parcels-same-config/child/src/assets/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/apps/multiple-parcels-same-config/child/src/environments/environment.prod.ts b/apps/multiple-parcels-same-config/child/src/environments/environment.prod.ts
new file mode 100644
index 00000000..c9669790
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/src/environments/environment.prod.ts
@@ -0,0 +1,3 @@
+export const environment = {
+ production: true,
+};
diff --git a/apps/multiple-parcels-same-config/child/src/environments/environment.ts b/apps/multiple-parcels-same-config/child/src/environments/environment.ts
new file mode 100644
index 00000000..a20cfe55
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/src/environments/environment.ts
@@ -0,0 +1,3 @@
+export const environment = {
+ production: false,
+};
diff --git a/apps/multiple-parcels-same-config/child/src/favicon.ico b/apps/multiple-parcels-same-config/child/src/favicon.ico
new file mode 100644
index 00000000..997406ad
Binary files /dev/null and b/apps/multiple-parcels-same-config/child/src/favicon.ico differ
diff --git a/apps/multiple-parcels-same-config/child/src/index.html b/apps/multiple-parcels-same-config/child/src/index.html
new file mode 100644
index 00000000..27968ca3
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/src/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+ AngularMultipleParcelsSameConfigChild
+
+
+
+
+
+
+
+
diff --git a/apps/multiple-parcels-same-config/child/src/main.single-spa.ts b/apps/multiple-parcels-same-config/child/src/main.single-spa.ts
new file mode 100644
index 00000000..72756bcd
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/src/main.single-spa.ts
@@ -0,0 +1,31 @@
+import { NgZone } from '@angular/core';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { NavigationStart, Router } from '@angular/router';
+import { singleSpaAngular, getSingleSpaExtraProviders, enableProdMode } from 'single-spa-angular';
+
+import { AppModule } from './app/app.module';
+import { environment } from './environments/environment';
+import { singleSpaPropsSubject } from './single-spa/single-spa-props';
+
+if (environment.production) {
+ enableProdMode();
+}
+
+const lifecycles = singleSpaAngular({
+ bootstrapFunction: singleSpaProps => {
+ singleSpaPropsSubject.next(singleSpaProps);
+ return platformBrowserDynamic(getSingleSpaExtraProviders()).bootstrapModule(
+ AppModule(singleSpaProps.name)
+ );
+ },
+ template: singleSpaProps => {
+ return ``;
+ },
+ NgZone,
+ Router,
+ NavigationStart,
+});
+
+export const bootstrap = lifecycles.bootstrap;
+export const mount = lifecycles.mount;
+export const unmount = lifecycles.unmount;
diff --git a/apps/multiple-parcels-same-config/child/src/single-spa/asset-url.ts b/apps/multiple-parcels-same-config/child/src/single-spa/asset-url.ts
new file mode 100644
index 00000000..d8cb3be3
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/src/single-spa/asset-url.ts
@@ -0,0 +1,12 @@
+// In single-spa, the assets need to be loaded from a dynamic location,
+// instead of hard coded to `/assets`. We use webpack public path for this.
+// See https://webpack.js.org/guides/public-path/#root
+
+export function assetUrl(url: string): string {
+ // @ts-ignore
+ const publicPath = __webpack_public_path__;
+ const publicPathSuffix = publicPath.endsWith('/') ? '' : '/';
+ const urlPrefix = url.startsWith('/') ? '' : '/';
+
+ return `${publicPath}${publicPathSuffix}assets${urlPrefix}${url}`;
+}
diff --git a/apps/multiple-parcels-same-config/child/src/single-spa/single-spa-props.ts b/apps/multiple-parcels-same-config/child/src/single-spa/single-spa-props.ts
new file mode 100644
index 00000000..fc133a22
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/src/single-spa/single-spa-props.ts
@@ -0,0 +1,8 @@
+import { ReplaySubject } from 'rxjs';
+import { AppProps } from 'single-spa';
+
+export const singleSpaPropsSubject = new ReplaySubject(1);
+
+// Add any custom single-spa props you have to this type def
+// https://single-spa.js.org/docs/building-applications.html#custom-props
+export type SingleSpaProps = AppProps & Record;
diff --git a/apps/multiple-parcels-same-config/child/src/styles.scss b/apps/multiple-parcels-same-config/child/src/styles.scss
new file mode 100644
index 00000000..90d4ee00
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/src/styles.scss
@@ -0,0 +1 @@
+/* You can add global styles to this file, and also import other style files */
diff --git a/apps/multiple-parcels-same-config/child/tsconfig.app.json b/apps/multiple-parcels-same-config/child/tsconfig.app.json
new file mode 100644
index 00000000..79f5c904
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/tsconfig.app.json
@@ -0,0 +1,4 @@
+{
+ "extends": "./tsconfig.json",
+ "files": ["src/main.single-spa.ts"]
+}
diff --git a/apps/multiple-parcels-same-config/child/tsconfig.json b/apps/multiple-parcels-same-config/child/tsconfig.json
new file mode 100644
index 00000000..11a1eafd
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../../../tsconfig.base.json",
+ "references": [
+ {
+ "path": "./tsconfig.app.json"
+ }
+ ],
+ "compilerOptions": {
+ "target": "es2020"
+ }
+}
diff --git a/apps/multiple-parcels-same-config/child/webpack.config.ts b/apps/multiple-parcels-same-config/child/webpack.config.ts
new file mode 100644
index 00000000..4411334e
--- /dev/null
+++ b/apps/multiple-parcels-same-config/child/webpack.config.ts
@@ -0,0 +1 @@
+export { default } from '../../../libs/single-spa-angular/webpack';
diff --git a/apps/multiple-parcels-same-config/parent/project.json b/apps/multiple-parcels-same-config/parent/project.json
new file mode 100644
index 00000000..76038e0a
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/project.json
@@ -0,0 +1,77 @@
+{
+ "name": "multiple-parcels-same-config",
+ "$schema": "../../../node_modules/nx/schemas/project-schema.json",
+ "projectType": "application",
+ "sourceRoot": "apps/multiple-parcels-same-config/parent/src",
+ "prefix": "single-spa-angular",
+ "targets": {
+ "build": {
+ "executor": "@angular-builders/custom-webpack:browser",
+ "options": {
+ "customWebpackConfig": {
+ "libraryTarget": "system",
+ "excludeAngularDependencies": true,
+ "path": "apps/multiple-parcels-same-config/parent/webpack.config.ts"
+ },
+ "outputPath": "dist/apps/multiple-parcels-same-config",
+ "index": "apps/multiple-parcels-same-config/parent/src/index.html",
+ "main": "apps/multiple-parcels-same-config/parent/src/main.single-spa.ts",
+ "tsConfig": "apps/multiple-parcels-same-config/parent/tsconfig.app.json",
+ "aot": true,
+ "assets": ["apps/multiple-parcels-same-config/parent/src/favicon.ico", "apps/multiple-parcels-same-config/parent/src/assets"],
+ "styles": ["apps/multiple-parcels-same-config/parent/src/styles.scss"],
+ "deployUrl": "http://localhost:9000/"
+ },
+ "configurations": {
+ "development": {
+ "buildOptimizer": false,
+ "optimization": false,
+ "vendorChunk": true,
+ "extractLicenses": false,
+ "sourceMap": true,
+ "namedChunks": true
+ },
+ "production": {
+ "fileReplacements": [
+ {
+ "replace": "apps/multiple-parcels-same-config/parent/src/environments/environment.ts",
+ "with": "apps/multiple-parcels-same-config/parent/src/environments/environment.prod.ts"
+ }
+ ],
+ "optimization": true,
+ "outputHashing": "none",
+ "sourceMap": false,
+ "namedChunks": false,
+ "extractLicenses": true,
+ "vendorChunk": false,
+ "buildOptimizer": true,
+ "budgets": [
+ {
+ "type": "initial",
+ "maximumWarning": "2mb",
+ "maximumError": "5mb"
+ },
+ {
+ "type": "anyComponentStyle",
+ "maximumWarning": "6kb",
+ "maximumError": "10kb"
+ }
+ ]
+ }
+ },
+ "defaultConfiguration": "production"
+ },
+ "serve": {
+ "executor": "@angular-builders/custom-webpack:dev-server",
+ "options": {
+ "browserTarget": "multiple-parcels-same-config:build:development"
+ },
+ "configurations": {
+ "production": {
+ "browserTarget": "multiple-parcels-same-config:build:production"
+ }
+ }
+ }
+ },
+ "tags": []
+}
diff --git a/apps/multiple-parcels-same-config/parent/src/app/app-routing.module.ts b/apps/multiple-parcels-same-config/parent/src/app/app-routing.module.ts
new file mode 100755
index 00000000..ad10774a
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/src/app/app-routing.module.ts
@@ -0,0 +1,15 @@
+import { APP_BASE_HREF } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { EmptyRouteComponent } from './empty-route/empty-route.component';
+
+const routes: Routes = [
+ { path: '**', component: EmptyRouteComponent }
+];
+
+@NgModule({
+ imports: [RouterModule.forRoot(routes)],
+ exports: [RouterModule],
+ providers: [{ provide: APP_BASE_HREF, useValue: '/' }]
+})
+export class AppRoutingModule { }
diff --git a/apps/multiple-parcels-same-config/parent/src/app/app.component.html b/apps/multiple-parcels-same-config/parent/src/app/app.component.html
new file mode 100644
index 00000000..090b621b
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/src/app/app.component.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ parcel 1
+
+
+
+ parcel 2
+
+
+
diff --git a/apps/multiple-parcels-same-config/parent/src/app/app.component.ts b/apps/multiple-parcels-same-config/parent/src/app/app.component.ts
new file mode 100644
index 00000000..dcab473d
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/src/app/app.component.ts
@@ -0,0 +1,51 @@
+import { Component, ElementRef, ViewChild } from '@angular/core';
+import { mountRootParcel } from 'single-spa';
+
+@Component({
+ selector: 'multiple-parcels-same-config',
+ templateUrl: './app.component.html',
+})
+export class AppComponent {
+ constructor() {}
+
+ @ViewChild('parcelContainer1') parcelContainer1!: ElementRef;
+ @ViewChild('parcelContainer2') parcelContainer2!: ElementRef;
+
+ mountRootParcel = mountRootParcel;
+
+ props1 = { id: 1 };
+ props2 = { id: 2 };
+
+ parcel1: any;
+ parcel2: any;
+
+ config() {
+ return (window as any).System.import('multiple-parcels-same-config-child');
+ }
+
+ mount1() {
+ this.parcel1 = this.mountRootParcel(this.config, {
+ domElement: this.parcelContainer1.nativeElement,
+ ...this.props1,
+ });
+ }
+
+ mount2() {
+ this.parcel2 = this.mountRootParcel(this.config, {
+ domElement: this.parcelContainer2.nativeElement,
+ ...this.props2,
+ });
+ }
+
+ unmount1() {
+ if (this.parcel1) {
+ this.parcel1.unmount();
+ }
+ }
+
+ unmount2() {
+ if (this.parcel2) {
+ this.parcel2.unmount();
+ }
+ }
+}
diff --git a/apps/multiple-parcels-same-config/parent/src/app/app.module.ts b/apps/multiple-parcels-same-config/parent/src/app/app.module.ts
new file mode 100644
index 00000000..a742cd14
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/src/app/app.module.ts
@@ -0,0 +1,15 @@
+import { NgModule } from '@angular/core';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { APP_BASE_HREF } from '@angular/common';
+
+import { AppComponent } from './app.component';
+import { AppRoutingModule } from './app-routing.module';
+import { EmptyRouteComponent } from './empty-route/empty-route.component';
+
+@NgModule({
+ imports: [BrowserAnimationsModule, AppRoutingModule],
+ declarations: [AppComponent, EmptyRouteComponent],
+ bootstrap: [AppComponent],
+ providers: [],
+})
+export class AppModule {}
diff --git a/apps/multiple-parcels-same-config/parent/src/app/empty-route/empty-route.component.ts b/apps/multiple-parcels-same-config/parent/src/app/empty-route/empty-route.component.ts
new file mode 100755
index 00000000..b8380398
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/src/app/empty-route/empty-route.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app1-empty-route',
+ template: '',
+})
+export class EmptyRouteComponent {}
diff --git a/apps/multiple-parcels-same-config/parent/src/assets/.gitkeep b/apps/multiple-parcels-same-config/parent/src/assets/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/apps/multiple-parcels-same-config/parent/src/environments/environment.prod.ts b/apps/multiple-parcels-same-config/parent/src/environments/environment.prod.ts
new file mode 100644
index 00000000..c9669790
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/src/environments/environment.prod.ts
@@ -0,0 +1,3 @@
+export const environment = {
+ production: true,
+};
diff --git a/apps/multiple-parcels-same-config/parent/src/environments/environment.ts b/apps/multiple-parcels-same-config/parent/src/environments/environment.ts
new file mode 100644
index 00000000..a20cfe55
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/src/environments/environment.ts
@@ -0,0 +1,3 @@
+export const environment = {
+ production: false,
+};
diff --git a/apps/multiple-parcels-same-config/parent/src/favicon.ico b/apps/multiple-parcels-same-config/parent/src/favicon.ico
new file mode 100644
index 00000000..997406ad
Binary files /dev/null and b/apps/multiple-parcels-same-config/parent/src/favicon.ico differ
diff --git a/apps/multiple-parcels-same-config/parent/src/index.html b/apps/multiple-parcels-same-config/parent/src/index.html
new file mode 100644
index 00000000..adb5f057
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/src/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+ AngularMultipleParcelsSameConfigParent
+
+
+
+
+
+
+
+
diff --git a/apps/multiple-parcels-same-config/parent/src/main.single-spa.ts b/apps/multiple-parcels-same-config/parent/src/main.single-spa.ts
new file mode 100644
index 00000000..39507b4f
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/src/main.single-spa.ts
@@ -0,0 +1,29 @@
+import { NgZone } from '@angular/core';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { NavigationStart, Router } from '@angular/router';
+import { singleSpaAngular, getSingleSpaExtraProviders, enableProdMode } from 'single-spa-angular';
+
+import { AppModule } from './app/app.module';
+import { environment } from './environments/environment';
+import { singleSpaPropsSubject } from './single-spa/single-spa-props';
+
+if (environment.production) {
+ enableProdMode();
+}
+
+const lifecycles = singleSpaAngular({
+ bootstrapFunction: singleSpaProps => {
+ singleSpaPropsSubject.next(singleSpaProps);
+ return platformBrowserDynamic(getSingleSpaExtraProviders()).bootstrapModule(
+ AppModule,
+ );
+ },
+ template: '',
+ NgZone,
+ Router,
+ NavigationStart,
+});
+
+export const bootstrap = lifecycles.bootstrap;
+export const mount = lifecycles.mount;
+export const unmount = lifecycles.unmount;
diff --git a/apps/multiple-parcels-same-config/parent/src/single-spa/asset-url.ts b/apps/multiple-parcels-same-config/parent/src/single-spa/asset-url.ts
new file mode 100644
index 00000000..d8cb3be3
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/src/single-spa/asset-url.ts
@@ -0,0 +1,12 @@
+// In single-spa, the assets need to be loaded from a dynamic location,
+// instead of hard coded to `/assets`. We use webpack public path for this.
+// See https://webpack.js.org/guides/public-path/#root
+
+export function assetUrl(url: string): string {
+ // @ts-ignore
+ const publicPath = __webpack_public_path__;
+ const publicPathSuffix = publicPath.endsWith('/') ? '' : '/';
+ const urlPrefix = url.startsWith('/') ? '' : '/';
+
+ return `${publicPath}${publicPathSuffix}assets${urlPrefix}${url}`;
+}
diff --git a/apps/multiple-parcels-same-config/parent/src/single-spa/single-spa-props.ts b/apps/multiple-parcels-same-config/parent/src/single-spa/single-spa-props.ts
new file mode 100644
index 00000000..fc133a22
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/src/single-spa/single-spa-props.ts
@@ -0,0 +1,8 @@
+import { ReplaySubject } from 'rxjs';
+import { AppProps } from 'single-spa';
+
+export const singleSpaPropsSubject = new ReplaySubject(1);
+
+// Add any custom single-spa props you have to this type def
+// https://single-spa.js.org/docs/building-applications.html#custom-props
+export type SingleSpaProps = AppProps & Record;
diff --git a/apps/multiple-parcels-same-config/parent/src/styles.scss b/apps/multiple-parcels-same-config/parent/src/styles.scss
new file mode 100644
index 00000000..90d4ee00
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/src/styles.scss
@@ -0,0 +1 @@
+/* You can add global styles to this file, and also import other style files */
diff --git a/apps/multiple-parcels-same-config/parent/tsconfig.app.json b/apps/multiple-parcels-same-config/parent/tsconfig.app.json
new file mode 100644
index 00000000..79f5c904
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/tsconfig.app.json
@@ -0,0 +1,4 @@
+{
+ "extends": "./tsconfig.json",
+ "files": ["src/main.single-spa.ts"]
+}
diff --git a/apps/multiple-parcels-same-config/parent/tsconfig.json b/apps/multiple-parcels-same-config/parent/tsconfig.json
new file mode 100644
index 00000000..11a1eafd
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../../../tsconfig.base.json",
+ "references": [
+ {
+ "path": "./tsconfig.app.json"
+ }
+ ],
+ "compilerOptions": {
+ "target": "es2020"
+ }
+}
diff --git a/apps/multiple-parcels-same-config/parent/webpack.config.ts b/apps/multiple-parcels-same-config/parent/webpack.config.ts
new file mode 100644
index 00000000..4411334e
--- /dev/null
+++ b/apps/multiple-parcels-same-config/parent/webpack.config.ts
@@ -0,0 +1 @@
+export { default } from '../../../libs/single-spa-angular/webpack';
diff --git a/apps/navbar/src/app/components/primary-nav/primary-nav.component.ts b/apps/navbar/src/app/components/primary-nav/primary-nav.component.ts
index d3cccdf8..14a31bf4 100644
--- a/apps/navbar/src/app/components/primary-nav/primary-nav.component.ts
+++ b/apps/navbar/src/app/components/primary-nav/primary-nav.component.ts
@@ -32,6 +32,10 @@ export class PrimaryNavComponent {
label: 'Angular standalone',
url: '/standalone',
},
+ {
+ label: "Multiple parcels from same config",
+ url: "/multiple-parcels-same-config"
+ }
];
constructor(private router: Router) {}
diff --git a/apps/root-config/src/index.ejs b/apps/root-config/src/index.ejs
index c1b4e4b9..2155dcc8 100644
--- a/apps/root-config/src/index.ejs
+++ b/apps/root-config/src/index.ejs
@@ -34,6 +34,8 @@
"elements": "http://localhost:4000/main.js",
"parcel": "http://localhost:4400/main.js",
"standalone": "http://localhost:4500/main.js",
+ "multiple-parcels-same-config": "http://localhost:4600/main.js",
+ "multiple-parcels-same-config-child": "http://localhost:4700/main.js",
"rxjs": "https://cdn.jsdelivr.net/npm/@esm-bundle/rxjs/system/es2015/rxjs.min.js",
"rxjs/operators": "https://cdn.jsdelivr.net/npm/@esm-bundle/rxjs/system/es2015/rxjs-operators.min.js"
}
diff --git a/apps/root-config/src/main.js b/apps/root-config/src/main.js
index 15ac2d0f..299fae7c 100644
--- a/apps/root-config/src/main.js
+++ b/apps/root-config/src/main.js
@@ -41,5 +41,11 @@ System.import('single-spa').then(({ registerApplication, start }) => {
activeWhen: location => location.pathname.startsWith('/standalone'),
});
+ registerApplication({
+ name: 'multiple-parcels-same-config',
+ app: () => System.import('multiple-parcels-same-config'),
+ activeWhen: location => location.pathname.startsWith('/multiple-parcels-same-config'),
+ });
+
start();
});
diff --git a/cypress/integration/multiple-parcels-same-config.spec.js b/cypress/integration/multiple-parcels-same-config.spec.js
new file mode 100644
index 00000000..f9d0f50d
--- /dev/null
+++ b/cypress/integration/multiple-parcels-same-config.spec.js
@@ -0,0 +1,50 @@
+///
+
+Cypress.Screenshot.defaults({
+ screenshotOnRunFailure: false,
+});
+
+describe('https://github.com/single-spa/single-spa-angular/issues/234', () => {
+ it('should render the same Angular parcel twice', () => {
+ cy.visit('/multiple-parcels-same-config')
+ // Mount the first parcel.
+ .get('button.mount1')
+ .click()
+ // The `wait` command is used because Cypress on the CI level is slower than locally,
+ // basically it clicks the `