Web ****************
**** NPM Git TagGit Submodule
Mooa ****
Backbone.jsAngular.jsVue.js 1 Angular.js Angular 2+
**** To Bto Bussiness
Web ****
===
Web ****
**************** NPM Git TagGit Submodule
************ HTTP ********
CRUD Web -> ->
Spring
@RequestMapping(value="/")
public ModelAndView homePage(){
return new ModelAndView("/WEB-INF/jsp/index.jsp");
}
@RequestMapping(value="/detail/{detailId}")
public ModelAndView detail(HttpServletRequest request, ModelMap model){
....
return new ModelAndView("/WEB-INF/jsp/detail.jsp", "detail", detail);
}
@RequestMapping("/name")
public String name(){
String name = restTemplate.getForObject("http://account/name", String.class);
return Name" + name;
}
const appRoutes: Routes = [
{ path: 'index', component: IndexComponent },
{ path: 'detail/:id', component: DetailComponent },
];
A
const appRoutes: Routes = [
{ path: 'index', component: IndexComponent },
];
B
const appRoutes: Routes = [
{ path: 'detail/:id', component: DetailComponent },
];
******** HTTP
**** A B
Nginx
Nginx
http {
server {
listen 80;
server_name www.phodal.com;
location /api/ {
proxy_pass http://http://172.31.25.15:8000/api;
}
location /web/admin {
proxy_pass http://172.31.25.29/web/admin;
}
location /web/notifications {
proxy_pass http://172.31.25.27/web/notifications;
}
location / {
proxy_pass /;
}
}
}
**** Angluar Angular Angular.js
iframe
iFrame
**HTML **
<iframe>
HTML
iframe iframe
Desktop Web
iframe
**** postMessage
iframeEl.contentWindow
iFrame Window ****
iframe KPI
Web Components Angular VirtualDOM React HTML DOM
DOM DOM
Single-SPA ReactAngularVue Single-SPA Angular Mooa
iFrame **** iframe
blabla
************ Lazyload
Pollyfill CSS
Web Components Web Components oan Web ****
Web Components Web
<template>
<slot>
link
<link rel="import" href="components/di-li.html">
<link rel="import" href="components/d-header.html">
HTML Web Components
iframe Scripts
Styles
**** Web Components
Web Components ShadowDOM DOM Web Components
Web Components Web Components
Web Components
Web Web Components Angular createCustomElement Web Components
platformBrowser()
.bootstrapModuleFactory(MyPopupModuleNgFactory)
.then(({injector}) => {
const MyPopupElement = createCustomElement(MyPopup, {injector});
customElements.define(my-popup, MyPopupElement);
});
Web Components
Stencil Web Components React Angular
React Stencil Web Components
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import 'test-components/testcomponents';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
Stencil ChromeSafariFirefoxEdge IE11
~~
===
**** Python
**IE ** IE IE IE WebComponents
| | | | | |
---------|---------|--------|-------|----------|-------|-------
| | | | | |
iFrame | | | | | |
| | | | | | Hook
| | | | | | webpack hack
| | | | | |
Web Components | | | | | |
Web Components | | | | | |
**** Single-SPA mooa
**** hack****
|
------------------|--------------- a. | b. | c. | AngularVueReact d. | e. | f. | g. | h. | i. |
a~j
PS Web Components WC~~)
| a | b | c | d | e | f | g | h | i
-----------|---|---|---|---|---|---|---|---|---
| O | O | O | O | O | O | | |
iFrame | O | O | O | O | O | O | | |
| O | O | O | | | O | | |
| O | O | | | - | - | O | - |
| O | O | | O | - | - | O | - | O
WC | O | O | | O | O | O | - | - | O
WC | O | O | O | O | O | O | | | O
O -
PS Keynote
===
No
Web Component
iFrame
Single-SPA Production Ready
Single-SPA Single-SPA
declareChildApplication('inferno', () => import('src/inferno/inferno.app.js'), pathPrefix('/inferno'));
Tab 2 4
jscss
Java Java Python
Angular
DNS TAB
**
(
Single-SPA
load
apps.json
apps.json
{
"name": "help",
"selector": "help-root",
"baseScriptUrl": "/assets/help",
"styles": [
"styles.bundle.css"
],
"prefix": "help",
"scripts": [
"inline.bundle.js",
"polyfills.bundle.js",
"main.bundle.js"
]
}
selector
DOM prefix URL index.html
package.json
if (event.detail.app.name === appName) {
let urlPrefix = 'app'
if (urlPrefix) {
urlPrefix = `/${window.mooa.option.urlPrefix}/`
}
router.navigate([event.detail.url.replace(urlPrefix + appName, '')])
}
A B
window.addEventListener('mooa.routing.navigate', function(event: CustomEvent) {
const opts = event.detail
if (opts) {
navigateAppByName(opts)
}
})
Loading
Angular Angular Lazyload Lazyload ****
Angular
AngularVue + Webpack
** Vendor **
Route Lazyload ****
4 2 Tab
**** Angular
Mooa Mooa + Angular HTML
<app-root _nghost-c0="" ng-version="4.2.0">
...
<app-home _nghost-c2="">
<app-app1 _nghost-c0="" ng-version="5.2.8" style="display: none;"><nav _ngcontent-c0="" class="navbar"></app-app1>
<iframe frameborder="" width="100%" height="100%" src="http://localhost:4200/app/help/homeassets/iframe.html" id="help_206547"></iframe>
</app-home>
</app-root>
Mooa Single-SPA Angular iFrame
x | Lazyload | | |
--------|--------------|------------|-------------|-------------
| | | |
| | | |
| | | |
| | | |
x | Lazyload | | |
--------|--------------|------------|-------------|-------------
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| AoT | AoT | | AoT
Mooa Angular single-spa IE 10 IFRAME
Mooa Single-SPA Mooa Master-Slave -
Web Angular Angular
Mooa angular-cli
ng new hello-world
mooa
yarn add mooa
apps.json
assets
[{
"name": "help",
"selector": "app-help",
"baseScriptUrl": "/assets/help",
"styles": [
"styles.bundle.css"
],
"prefix": "help",
"scripts": [
"inline.bundle.js",
"polyfills.bundle.js",
"main.bundle.js"
]
}
]]
app.component.ts
mooa = new Mooa({
mode: 'iframe',
debug: false,
parentElement: 'app-home',
urlPrefix: 'app',
switchMode: 'coexist',
preload: true,
includeZone: true
});
constructor(private renderer: Renderer2, http: HttpClient, private router: Router) {
http.get<IAppOption[]>('/assets/apps.json')
.subscribe(
data => {
this.createApps(data);
},
err => console.log(err)
);
}
private createApps(data: IAppOption[]) {
data.map((config) => {
this.mooa.registerApplication(config.name, config, mooaRouter.hashPrefix(config.prefix));
});
const that = this;
this.router.events.subscribe((event) => {
if (event instanceof NavigationEnd) {
that.mooa.reRouter(event);
}
});
return mooa.start();
}
{
path: 'app/:appName/:route',
component: HomeComponent
}
Mooa
Mooa
git clone https://github.com/phodal/mooa-boilerplate
npm install
help
yarn build
dist
src/assets/help
Mooa mooaPlatform.navigateTo
mooaPlatform.navigateTo({
appName: 'help',
router: 'home'
});
MOOA_EVENT.ROUTING_NAVIGATE
mooa.start()
window.addEventListener(MOOA_EVENT.ROUTING_NAVIGATE, function(event: CustomEvent) {
if (event.detail) {
navigateAppByName(event.detail)
}
})
DEMO
GitHub phodal/mooa
Angular Component Angular DOM Angular
<app-home _nghost-c3="" ng-version="5.2.8">
<app-help _nghost-c0="" ng-version="5.2.2" style="display:block;"><div _ngcontent-c0=""></div></app-help>
<app-app1 _nghost-c0="" ng-version="5.2.3" style="display:none;"><nav _ngcontent-c0="" class="navbar"></div></app-app1>
<app-app2 _nghost-c0="" ng-version="5.2.2" style="display:none;"><nav _ngcontent-c0="" class="navbar"></div></app-app2>
</app-home>
**** Mooa iframe
Component
iframe
Mooa Mooa
iframe **** Angular ****
iframe iframe **** Tree-Shaking
IFrame iframe
<app-home _nghost-c2="" ng-version="5.2.8">
<iframe frameborder="" width="100%" height="100%" src="http://localhost:4200/assets/iframe.html" id="help_206547" style="display:block;"></iframe>
<iframe frameborder="" width="100%" height="100%" src="http://localhost:4200/assets/iframe.html" id="app_235458 style="display:none;"></iframe>
</app-home>
iframe src iframe iframe.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>App1</title>
<base href="/">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
</body>
</html>
PS phodal/mooa
iframe Angular iframe IFrame
Mooa iframe
---
###
Mooa iframe ``document.getElementById`` iframe ``iframeEl.contentWindow``
```typescript
let iframeEl: any = document.getElementById(iframeId)
if (iframeEl && iframeEl.contentWindow) {
iframeEl.contentWindow.mooa.option = window.mooa.option
iframeEl.contentWindow.dispatchEvent(
new CustomEvent(MOOA_EVENT.ROUTING_CHANGE, { detail: eventArgs })
)
}
```
###
```
iframeEl.contentWindow.addEventListener(MOOA_EVENT.ROUTING_NAVIGATE, function(event: CustomEvent) {
if (event.detail) {
navigateAppByName(event.detail)
}
})
```
---
Mooa mooa iframe
```typescript
this.mooa = new Mooa({
mode: 'iframe',
debug: false,
parentElement: 'app-home',
urlPrefix: 'app',
switchMode: 'coexist',
preload: true,
includeZone: true
});
...
that.mooa.registerApplicationByLink('help', '/assets/help', mooaRouter.matchRoute('help'));
that.mooa.registerApplicationByLink('app1', '/assets/app1', mooaRouter.matchRoute('app1'));
this.mooa.start();
...
this.router.events.subscribe((event: any) => {
if (event instanceof NavigationEnd) {
that.mooa.reRouter(event);
}
});
```
[https://github.com/phodal/mooa-boilerplate](https://github.com/phodal/mooa-boilerplate)
===
- [MDN DOMShadow DOM](https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/%E5%BD%B1%E5%AD%90_DOM)
- [Web Components](https://developer.mozilla.org/zh-CN/docs/Web/Web_Components)
- [Shadow DOM v1](https://developers.google.com/web/fundamentals/web-components/shadowdom?hl=zh-cn)