@maxelms/create-plugin-cli 1.1.25-master.1 → 1.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/package.json +1 -1
  2. package/templates/angular-micro-app/.eslintrc.js +3 -0
  3. package/templates/angular-micro-app/README.md +5 -0
  4. package/templates/angular-micro-app/examples/main.css +2 -0
  5. package/templates/angular-micro-app/examples/main.js +2 -0
  6. package/templates/angular-micro-app/examples/main.js.LICENSE.txt +52 -0
  7. package/templates/angular-micro-app/examples/playground.html +1 -0
  8. package/templates/angular-micro-app/examples/react-dom.production.min.js +2 -0
  9. package/templates/angular-micro-app/examples/react-dom.production.min.js.LICENSE.txt +8 -0
  10. package/templates/angular-micro-app/examples/react.production.min.js +2 -0
  11. package/templates/angular-micro-app/examples/react.production.min.js.LICENSE.txt +8 -0
  12. package/templates/angular-micro-app/examples/vue.runtime.global.js +9054 -0
  13. package/templates/angular-micro-app/examples/zone.umd.min.js +2 -0
  14. package/templates/angular-micro-app/examples/zone.umd.min.js.LICENSE.txt +29 -0
  15. package/templates/angular-micro-app/manifest.json.tpl +3 -0
  16. package/templates/angular-micro-app/package.json.tpl +40 -0
  17. package/templates/angular-micro-app/pnpm-lock.yaml +7998 -0
  18. package/templates/angular-micro-app/public/configuration.json +34 -0
  19. package/templates/angular-micro-app/public/index.html.tpl +15 -0
  20. package/templates/angular-micro-app/src/about.component.ts +42 -0
  21. package/templates/angular-micro-app/src/app-routing.module.ts +12 -0
  22. package/templates/angular-micro-app/src/app.component.css +22 -0
  23. package/templates/angular-micro-app/src/app.component.html +304 -0
  24. package/templates/angular-micro-app/src/app.component.ts +42 -0
  25. package/templates/angular-micro-app/src/app.module.ts +27 -0
  26. package/templates/angular-micro-app/src/contact.component.ts +42 -0
  27. package/templates/angular-micro-app/src/home.component.ts +42 -0
  28. package/templates/angular-micro-app/src/index.ts +54 -0
  29. package/templates/angular-micro-app/src/props.service.ts +18 -0
  30. package/templates/angular-micro-app/src/single-spa-props.ts +7 -0
  31. package/templates/angular-micro-app/tsconfig.json +25 -0
  32. package/templates/angular-micro-app/webpack.config.js +112 -0
  33. package/templates/angular-micro-button/.eslintrc.js +3 -0
  34. package/templates/angular-micro-button/README.md +5 -0
  35. package/templates/angular-micro-button/manifest.json.tpl +3 -0
  36. package/templates/angular-micro-button/package.json.tpl +39 -0
  37. package/templates/angular-micro-button/pnpm-lock.yaml +7977 -0
  38. package/templates/angular-micro-button/public/configuration.json +34 -0
  39. package/templates/angular-micro-button/public/index.html.tpl +15 -0
  40. package/templates/angular-micro-button/src/app.component.css +10 -0
  41. package/templates/angular-micro-button/src/app.component.html +2 -0
  42. package/templates/angular-micro-button/src/app.component.ts.tpl +38 -0
  43. package/templates/angular-micro-button/src/app.module.ts +27 -0
  44. package/templates/angular-micro-button/src/components/content.component.css +116 -0
  45. package/templates/angular-micro-button/src/components/content.component.html +3 -0
  46. package/templates/angular-micro-button/src/components/content.component.ts +16 -0
  47. package/templates/angular-micro-button/src/index.ts.tpl +107 -0
  48. package/templates/angular-micro-button/src/master-props.ts +7 -0
  49. package/templates/angular-micro-button/tsconfig.json +25 -0
  50. package/templates/angular-micro-button/webpack.config.js +112 -0
  51. package/templates/angular-micro-field/.eslintrc.js +3 -0
  52. package/templates/angular-micro-field/README.md +5 -0
  53. package/templates/angular-micro-field/examples/main.css +2 -0
  54. package/templates/angular-micro-field/examples/main.js +2 -0
  55. package/templates/angular-micro-field/examples/main.js.LICENSE.txt +52 -0
  56. package/templates/angular-micro-field/examples/playground.html +1 -0
  57. package/templates/angular-micro-field/examples/react-dom.production.min.js +2 -0
  58. package/templates/angular-micro-field/examples/react-dom.production.min.js.LICENSE.txt +8 -0
  59. package/templates/angular-micro-field/examples/react.production.min.js +2 -0
  60. package/templates/angular-micro-field/examples/react.production.min.js.LICENSE.txt +8 -0
  61. package/templates/angular-micro-field/examples/vue.runtime.global.js +9054 -0
  62. package/templates/angular-micro-field/examples/zone.umd.min.js +2 -0
  63. package/templates/angular-micro-field/examples/zone.umd.min.js.LICENSE.txt +29 -0
  64. package/templates/angular-micro-field/manifest.json.tpl +3 -0
  65. package/templates/angular-micro-field/package.json.tpl +39 -0
  66. package/templates/angular-micro-field/pnpm-lock.yaml +7977 -0
  67. package/templates/angular-micro-field/public/configuration.json +34 -0
  68. package/templates/angular-micro-field/public/index.html.tpl +15 -0
  69. package/templates/angular-micro-field/src/app.component.css +10 -0
  70. package/templates/angular-micro-field/src/app.component.html +8 -0
  71. package/templates/angular-micro-field/src/app.component.ts.tpl +60 -0
  72. package/templates/angular-micro-field/src/app.module.ts +14 -0
  73. package/templates/angular-micro-field/src/components/content.component.css +116 -0
  74. package/templates/angular-micro-field/src/components/content.component.html +10 -0
  75. package/templates/angular-micro-field/src/components/content.component.ts +21 -0
  76. package/templates/angular-micro-field/src/index.ts.tpl +101 -0
  77. package/templates/angular-micro-field/src/master-props.ts +7 -0
  78. package/templates/angular-micro-field/tsconfig.json +25 -0
  79. package/templates/angular-micro-field/webpack.config.js +112 -0
  80. package/templates/angular-micro-plugin/package.json.tpl +2 -2
  81. package/templates/react-micro-app/package.json.tpl +6 -0
  82. package/templates/react-micro-button/package.json.tpl +5 -0
  83. package/templates/react-micro-button/src/index.tsx +1 -0
  84. package/templates/react-micro-field/package.json.tpl +5 -0
  85. package/templates/react-micro-field-umi/package.json.tpl +5 -0
  86. package/templates/react-micro-plugin/package.json.tpl +5 -0
  87. package/templates/react-micro-plugin-umi/package.json.tpl +5 -0
  88. package/templates/vue3-micro-button/package.json.tpl +1 -1
  89. package/templates/vue3-micro-field/package.json.tpl +1 -1
  90. package/templates/vue3-micro-plugin/package.json.tpl +1 -1
  91. package/templates/vue3vite-micro-button/package.json.tpl +1 -1
  92. package/templates/vue3vite-micro-plugin/package.json.tpl +1 -1
@@ -0,0 +1,34 @@
1
+ {
2
+ "propName1": {
3
+ "label": "配置项一",
4
+ "type": "string",
5
+ "defaultValue": "配置项内容"
6
+ },
7
+ "propName2": {
8
+ "label": "配置项二",
9
+ "type": "number",
10
+ "defaultValue": 350
11
+ },
12
+ "propName3": {
13
+ "label": "配置项三",
14
+ "type": "select",
15
+ "options": [
16
+ {
17
+ "label": "选项1",
18
+ "value": "option1"
19
+ },
20
+ {
21
+ "label": "选项2",
22
+ "value": "option2"
23
+ },
24
+ {
25
+ "label": "选项3",
26
+ "value": "option3"
27
+ }
28
+ ]
29
+ },
30
+ "externalParams": {
31
+ "label": "外部参数",
32
+ "type": "string"
33
+ }
34
+ }
@@ -0,0 +1,15 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <title>Maxelms 微应用 angular13</title>
7
+ <base href="/">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1">
9
+ </head>
10
+
11
+ <body>
12
+ <div id="root-<%= timestamp %>"></div>
13
+ </body>
14
+
15
+ </html>
@@ -0,0 +1,42 @@
1
+ import { Component, OnDestroy, OnInit, ChangeDetectorRef } from '@angular/core'
2
+ import { Subscription } from 'rxjs'
3
+ import { PropsService } from './props.service'
4
+
5
+ @Component({
6
+ selector: 'app-about',
7
+ template: `
8
+ <div class="content" role="main">
9
+ app-about
10
+ <p>propName1 = {{ propName1 }}</p>
11
+ <p>propName2 = {{ propName2 }}</p>
12
+ </div>
13
+ `,
14
+ styles: [`
15
+ .content {
16
+ margin-top: 200px;
17
+ }
18
+ `],
19
+ })
20
+ export class AboutComponent {
21
+ propName1: string = '';
22
+ propName2: string = '';
23
+ private propsSub?: Subscription;
24
+
25
+ constructor(
26
+ private propsService: PropsService,
27
+ private cdr: ChangeDetectorRef,
28
+ ) {
29
+ this.init()
30
+ }
31
+
32
+ init() {
33
+ this.propsSub = this.propsService.props$.subscribe((props: any) => {
34
+ const { configurations } = props || {}
35
+ this.propName1 = configurations?.propName1 || ''
36
+ this.propName2 = configurations?.propName2 || ''
37
+ setTimeout(() => {
38
+ this.cdr.detectChanges() // ⚡ 手动刷新视图
39
+ }, 100)
40
+ })
41
+ }
42
+ }
@@ -0,0 +1,12 @@
1
+ import { Routes } from '@angular/router'
2
+ import { HomeComponent } from './home.component'
3
+ import { AboutComponent } from './about.component'
4
+ import { ContactComponent } from './contact.component'
5
+
6
+ export const routes: Routes = [
7
+ { path: '', redirectTo: '/home', pathMatch: 'full' },
8
+ { path: 'home', component: HomeComponent },
9
+ { path: 'about', component: AboutComponent },
10
+ { path: 'contact', component: ContactComponent },
11
+ { path: '**', redirectTo: '/home' },
12
+ ]
@@ -0,0 +1,22 @@
1
+ :host {
2
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
3
+ font-size: 14px;
4
+ color: #333;
5
+ box-sizing: border-box;
6
+ -webkit-font-smoothing: antialiased;
7
+ -moz-osx-font-smoothing: grayscale;
8
+ }
9
+
10
+ h1,
11
+ h2,
12
+ h3,
13
+ h4,
14
+ h5,
15
+ h6 {
16
+ margin: 8px 0;
17
+ }
18
+
19
+ p {
20
+ margin: 0;
21
+ }
22
+
@@ -0,0 +1,304 @@
1
+ <style>
2
+ .spacer {
3
+ flex: 1;
4
+ }
5
+
6
+ .toolbar {
7
+ position: absolute;
8
+ top: 0;
9
+ left: 0;
10
+ right: 0;
11
+ height: 60px;
12
+ display: flex;
13
+ align-items: center;
14
+ background-color: #1976d2;
15
+ color: white;
16
+ font-weight: 600;
17
+ }
18
+
19
+ .toolbar img {
20
+ margin: 0 16px;
21
+ }
22
+
23
+ .toolbar nav {
24
+ display: flex;
25
+ gap: 16px;
26
+ }
27
+
28
+ .toolbar nav a {
29
+ color: white;
30
+ text-decoration: none;
31
+ padding: 8px 16px;
32
+ border-radius: 4px;
33
+ transition: background-color 0.3s;
34
+ }
35
+
36
+ .toolbar nav a:hover {
37
+ background-color: rgba(255, 255, 255, 0.1);
38
+ }
39
+
40
+ .toolbar nav a.active {
41
+ background-color: rgba(255, 255, 255, 0.2);
42
+ }
43
+
44
+ .toolbar #twitter-logo {
45
+ height: 40px;
46
+ margin: 0 16px;
47
+ }
48
+
49
+ .toolbar #twitter-logo:hover {
50
+ opacity: 0.8;
51
+ }
52
+
53
+ .content {
54
+ display: flex;
55
+ margin: 82px auto 32px;
56
+ padding: 0 16px;
57
+ max-width: 960px;
58
+ flex-direction: column;
59
+ align-items: center;
60
+ }
61
+
62
+ svg.material-icons {
63
+ height: 24px;
64
+ width: auto;
65
+ }
66
+
67
+ svg.material-icons:not(:last-child) {
68
+ margin-right: 8px;
69
+ }
70
+
71
+ .card svg.material-icons path {
72
+ fill: #888;
73
+ }
74
+
75
+ .card-container {
76
+ display: flex;
77
+ flex-wrap: wrap;
78
+ justify-content: center;
79
+ margin-top: 16px;
80
+ }
81
+
82
+ .card {
83
+ border-radius: 4px;
84
+ border: 1px solid #eee;
85
+ background-color: #fafafa;
86
+ height: 40px;
87
+ width: 200px;
88
+ margin: 0 8px 16px;
89
+ padding: 16px;
90
+ display: flex;
91
+ flex-direction: row;
92
+ justify-content: center;
93
+ align-items: center;
94
+ transition: all 0.2s ease-in-out;
95
+ line-height: 24px;
96
+ }
97
+
98
+ .card-container .card:not(:last-child) {
99
+ margin-right: 0;
100
+ }
101
+
102
+ .card.card-small {
103
+ height: 16px;
104
+ width: 168px;
105
+ }
106
+
107
+ .card-container .card:not(.highlight-card) {
108
+ cursor: pointer;
109
+ }
110
+
111
+ .card-container .card:not(.highlight-card):hover {
112
+ transform: translateY(-3px);
113
+ box-shadow: 0 4px 17px rgba(black, 0.35);
114
+ }
115
+
116
+ .card-container .card:not(.highlight-card):hover .material-icons path {
117
+ fill: rgb(105, 103, 103);
118
+ }
119
+
120
+ .card.highlight-card {
121
+ background-color: #1976d2;
122
+ color: white;
123
+ font-weight: 600;
124
+ border: none;
125
+ width: auto;
126
+ min-width: 30%;
127
+ position: relative;
128
+ }
129
+
130
+ .card.card.highlight-card span {
131
+ margin-left: 60px;
132
+ }
133
+
134
+ svg#rocket {
135
+ width: 80px;
136
+ position: absolute;
137
+ left: -10px;
138
+ top: -24px;
139
+ }
140
+
141
+ svg#rocket-smoke {
142
+ height: calc(100vh - 95px);
143
+ position: absolute;
144
+ top: 10px;
145
+ right: 180px;
146
+ z-index: -10;
147
+ }
148
+
149
+ a,
150
+ a:visited,
151
+ a:hover {
152
+ color: #1976d2;
153
+ text-decoration: none;
154
+ }
155
+
156
+ a:hover {
157
+ color: #125699;
158
+ }
159
+
160
+ .terminal {
161
+ position: relative;
162
+ width: 80%;
163
+ max-width: 600px;
164
+ border-radius: 6px;
165
+ padding-top: 45px;
166
+ margin-top: 8px;
167
+ overflow: hidden;
168
+ background-color: rgb(15, 15, 16);
169
+ }
170
+
171
+ .terminal::before {
172
+ content: "\2022 \2022 \2022";
173
+ position: absolute;
174
+ top: 0;
175
+ left: 0;
176
+ height: 4px;
177
+ background: rgb(58, 58, 58);
178
+ color: #c2c3c4;
179
+ width: 100%;
180
+ font-size: 2rem;
181
+ line-height: 0;
182
+ padding: 14px 0;
183
+ text-indent: 4px;
184
+ }
185
+
186
+ .terminal pre {
187
+ font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
188
+ color: white;
189
+ padding: 0 1rem 1rem;
190
+ margin: 0;
191
+ }
192
+
193
+ .circle-link {
194
+ height: 40px;
195
+ width: 40px;
196
+ border-radius: 40px;
197
+ margin: 8px;
198
+ background-color: white;
199
+ border: 1px solid #eeeeee;
200
+ display: flex;
201
+ justify-content: center;
202
+ align-items: center;
203
+ cursor: pointer;
204
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
205
+ transition: 1s ease-out;
206
+ }
207
+
208
+ .circle-link:hover {
209
+ transform: translateY(-0.25rem);
210
+ box-shadow: 0px 3px 15px rgba(0, 0, 0, 0.2);
211
+ }
212
+
213
+ footer {
214
+ margin-top: 8px;
215
+ display: flex;
216
+ align-items: center;
217
+ line-height: 20px;
218
+ }
219
+
220
+ footer a {
221
+ display: flex;
222
+ align-items: center;
223
+ }
224
+
225
+ .github-star-badge {
226
+ color: #24292e;
227
+ display: flex;
228
+ align-items: center;
229
+ font-size: 12px;
230
+ padding: 3px 10px;
231
+ border: 1px solid rgba(27, 31, 35, .2);
232
+ border-radius: 3px;
233
+ background-image: linear-gradient(-180deg, #fafbfc, #eff3f6 90%);
234
+ margin-left: 4px;
235
+ font-weight: 600;
236
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
237
+ }
238
+
239
+ .github-star-badge:hover {
240
+ background-image: linear-gradient(-180deg, #f0f3f6, #e6ebf1 90%);
241
+ border-color: rgba(27, 31, 35, .35);
242
+ background-position: -.5em;
243
+ }
244
+
245
+ .github-star-badge .material-icons {
246
+ height: 16px;
247
+ width: 16px;
248
+ margin-right: 4px;
249
+ }
250
+
251
+ svg#clouds {
252
+ position: fixed;
253
+ bottom: -160px;
254
+ left: -230px;
255
+ z-index: -10;
256
+ width: 1920px;
257
+ }
258
+
259
+ /* Responsive Styles */
260
+ @media screen and (max-width: 767px) {
261
+
262
+ .card-container>*:not(.circle-link),
263
+ .terminal {
264
+ width: 100%;
265
+ }
266
+
267
+ .card:not(.highlight-card) {
268
+ height: 16px;
269
+ margin: 8px 0;
270
+ }
271
+
272
+ .card.highlight-card span {
273
+ margin-left: 72px;
274
+ }
275
+
276
+ svg#rocket-smoke {
277
+ right: 120px;
278
+ transform: rotate(-5deg);
279
+ }
280
+ }
281
+
282
+ @media screen and (max-width: 575px) {
283
+ svg#rocket-smoke {
284
+ display: none;
285
+ visibility: hidden;
286
+ }
287
+ }
288
+ </style>
289
+
290
+ <!-- Toolbar -->
291
+ <div class="toolbar" role="banner">
292
+ <img width="40" alt="Angular Logo"
293
+ src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==" />
294
+ <span>Angular Microfrontend</span>
295
+ <div class="spacer"></div>
296
+ <nav>
297
+ <a routerLink="/home" routerLinkActive="active">Home</a>
298
+ <a routerLink="/about" routerLinkActive="active">About</a>
299
+ <a routerLink="/contact" routerLinkActive="active">Contact</a>
300
+ </nav>
301
+ </div>
302
+
303
+ <!-- Router Outlet -->
304
+ <router-outlet></router-outlet>
@@ -0,0 +1,42 @@
1
+ import { Component, OnDestroy, OnInit, ChangeDetectorRef } from '@angular/core'
2
+ import { singleSpaPropsSubject } from './single-spa-props' // 引用你定义的 Subject
3
+ import { PropsService } from './props.service'
4
+
5
+ @Component({
6
+ selector: '#root-<%= timestamp %>',
7
+ templateUrl: './app.component.html',
8
+ styleUrls: ['./app.component.css'],
9
+ })
10
+ export class AppComponent implements OnInit, OnDestroy {
11
+
12
+ title = 'angular13';
13
+ propName1: string = '';
14
+ propName2: string = '';
15
+
16
+ private propsSub?: any;
17
+
18
+ constructor(
19
+ private cdr: ChangeDetectorRef,
20
+ private propsService: PropsService,
21
+ ) {}
22
+
23
+ ngOnInit() {
24
+ console.log('ngOnInit')
25
+
26
+ // 订阅 singleSpaProps
27
+ this.propsSub = singleSpaPropsSubject.subscribe((props: any) => {
28
+ console.log('收到主应用传来的 props: 111', props)
29
+ const { configurations, bizData } = props || {}
30
+ this.propName1 = configurations?.propName1 || ''
31
+ this.propName2 = configurations?.propName2 || ''
32
+
33
+ // 更新服务中的props,供子组件使用
34
+ this.propsService.updateProps(props)
35
+ this.cdr.detectChanges() // 手动触发变更检测
36
+ })
37
+ }
38
+
39
+ ngOnDestroy() {
40
+ this.propsSub?.unsubscribe()
41
+ }
42
+ }
@@ -0,0 +1,27 @@
1
+ import { NgModule } from '@angular/core'
2
+ import { HashLocationStrategy, LocationStrategy } from '@angular/common'
3
+ import { BrowserModule } from '@angular/platform-browser'
4
+ import { RouterModule } from '@angular/router'
5
+ import { AppComponent } from './app.component'
6
+ import { HomeComponent } from './home.component'
7
+ import { AboutComponent } from './about.component'
8
+ import { ContactComponent } from './contact.component'
9
+ import { routes } from './app-routing.module'
10
+
11
+ @NgModule({
12
+ declarations: [
13
+ AppComponent,
14
+ HomeComponent,
15
+ AboutComponent,
16
+ ContactComponent,
17
+ ],
18
+ imports: [
19
+ BrowserModule,
20
+ RouterModule.forRoot(routes, { useHash: true }),
21
+ ],
22
+ providers: [
23
+ { provide: LocationStrategy, useClass: HashLocationStrategy },
24
+ ],
25
+ bootstrap: [AppComponent],
26
+ })
27
+ export class AppModule {}
@@ -0,0 +1,42 @@
1
+ import { Component, OnDestroy, OnInit, ChangeDetectorRef } from '@angular/core'
2
+ import { Subscription } from 'rxjs'
3
+ import { PropsService } from './props.service'
4
+
5
+ @Component({
6
+ selector: 'app-contact',
7
+ template: `
8
+ <div class="content" role="main">
9
+ app-contact
10
+ <p>propName1 = {{ propName1 }}</p>
11
+ <p>propName2 = {{ propName2 }}</p>
12
+ </div>
13
+ `,
14
+ styles: [`
15
+ .content {
16
+ margin-top: 200px;
17
+ }
18
+ `],
19
+ })
20
+ export class ContactComponent {
21
+ propName1: string = '';
22
+ propName2: string = '';
23
+ private propsSub?: Subscription;
24
+
25
+ constructor(
26
+ private propsService: PropsService,
27
+ private cdr: ChangeDetectorRef,
28
+ ) {
29
+ this.init()
30
+ }
31
+
32
+ init() {
33
+ this.propsSub = this.propsService.props$.subscribe((props: any) => {
34
+ const { configurations } = props || {}
35
+ this.propName1 = configurations?.propName1 || ''
36
+ this.propName2 = configurations?.propName2 || ''
37
+ setTimeout(() => {
38
+ this.cdr.detectChanges() // ⚡ 手动刷新视图
39
+ }, 100)
40
+ })
41
+ }
42
+ }
@@ -0,0 +1,42 @@
1
+ import { Component, OnDestroy, OnInit, ChangeDetectorRef } from '@angular/core'
2
+ import { Subscription } from 'rxjs'
3
+ import { PropsService } from './props.service'
4
+
5
+ @Component({
6
+ selector: 'app-home',
7
+ template: `
8
+ <div class="content" role="main">
9
+ app-home
10
+ <p>propName1 = {{ propName1 }}</p>
11
+ <p>propName2 = {{ propName2 }}</p>
12
+ </div>
13
+ `,
14
+ styles: [`
15
+ .content {
16
+ margin-top: 200px;
17
+ }
18
+ `],
19
+ })
20
+ export class HomeComponent {
21
+ propName1: string = '';
22
+ propName2: string = '';
23
+ private propsSub?: Subscription;
24
+
25
+ constructor(
26
+ private propsService: PropsService,
27
+ private cdr: ChangeDetectorRef,
28
+ ) {
29
+ this.init()
30
+ }
31
+
32
+ init() {
33
+ this.propsSub = this.propsService.props$.subscribe((props: any) => {
34
+ const { configurations } = props || {}
35
+ this.propName1 = configurations?.propName1 || ''
36
+ this.propName2 = configurations?.propName2 || ''
37
+ setTimeout(() => {
38
+ this.cdr.detectChanges() // ⚡ 手动刷新视图
39
+ }, 100)
40
+ })
41
+ }
42
+ }
@@ -0,0 +1,54 @@
1
+ import { enableProdMode } from '@angular/core'
2
+ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'
3
+ import { registerPlugin, poweredByMaxelms } from '@maxelms/create-pulgin-api'
4
+
5
+ import { AppModule } from './app.module'
6
+ import { singleSpaPropsSubject } from './single-spa-props'
7
+
8
+ let container = '#root-<%= timestamp %>'
9
+ const environment = process.env.NODE_ENV === 'production'
10
+
11
+ if (environment) {
12
+ enableProdMode()
13
+ }
14
+
15
+ if (!poweredByMaxelms) {
16
+ const props = {
17
+ configurations: {
18
+ 'propName1': '11',
19
+ 'propName2': 3502,
20
+ },
21
+ }
22
+ console.log(props, 'props poweredByMaxelms')
23
+ render(props)
24
+ } else {
25
+ let $root: any
26
+
27
+ registerPlugin?.({
28
+ bootstrap() {
29
+ console.log('Angular microfrontend bootstrap')
30
+ },
31
+ mount(props: any) {
32
+ console.log(props, 'props mount')
33
+ render(props)
34
+ $root = document.querySelector(`#${props.containerId} ${container}`)
35
+ },
36
+ update(props: any) {
37
+ console.log(props, 'props update')
38
+ render(props)
39
+ },
40
+ unmount(props: any) {
41
+ console.log('Angular microfrontend unmount')
42
+ const element = document.querySelector(`#${props.containerId} ${container}`) || $root
43
+ // Angular will handle cleanup automatically
44
+ },
45
+ })
46
+ }
47
+
48
+
49
+ function render(singleSpaProps: any) {
50
+ singleSpaPropsSubject.next(singleSpaProps)
51
+ return platformBrowserDynamic().bootstrapModule(AppModule, {
52
+ ngZone: 'noop',
53
+ })
54
+ }
@@ -0,0 +1,18 @@
1
+ import { Injectable } from '@angular/core'
2
+ import { BehaviorSubject } from 'rxjs'
3
+
4
+ @Injectable({
5
+ providedIn: 'root',
6
+ })
7
+ export class PropsService {
8
+ private propsSubject = new BehaviorSubject<any>({})
9
+ public props$ = this.propsSubject.asObservable()
10
+
11
+ updateProps(props: any) {
12
+ this.propsSubject.next(props)
13
+ }
14
+
15
+ getCurrentProps() {
16
+ return this.propsSubject.value
17
+ }
18
+ }
@@ -0,0 +1,7 @@
1
+ import { ReplaySubject } from 'rxjs'
2
+
3
+ export const singleSpaPropsSubject = new ReplaySubject<SingleSpaProps>(1)
4
+
5
+ // Add any custom single-spa props you have to this type def
6
+ // https://single-spa.js.org/docs/building-applications.html#custom-props
7
+ export type SingleSpaProps = any;
@@ -0,0 +1,25 @@
1
+ {
2
+ "compileOnSave": false,
3
+ "compilerOptions": {
4
+ "baseUrl": "./",
5
+ "outDir": "./dist",
6
+ "sourceMap": true,
7
+ "declaration": false,
8
+ "downlevelIteration": true,
9
+ "experimentalDecorators": true,
10
+ "moduleResolution": "node",
11
+ "importHelpers": true,
12
+ "target": "es2017",
13
+ "module": "es2020",
14
+ "lib": ["es2018", "dom"],
15
+ "skipLibCheck": true,
16
+ "noImplicitAny": false,
17
+ "strict": false
18
+ },
19
+ "files": [
20
+ "src/index.ts"
21
+ ],
22
+ "include": [
23
+ "src/app/**/*",
24
+ ]
25
+ }