Skip to content

Commit 258a808

Browse files
committed
First commit
0 parents  commit 258a808

6 files changed

+229
-0
lines changed

README.md

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Micro Front End
2+
3+
P.O.C. para avaliar os desafios da implementação técnica do modelo arquitetural micro-fronted.
4+
5+
Foram criados 4 microfronts, o **combinado** foi que cada microfrontend tenha um counter, composto por display, botão - e botão +, quando o botão é precionado ele aumenta ou dominui o valor que estava no display e dispara evento através do window.dispatchEvent que poderia ser ouvido pelo compositor e ouvido por todos os mifro-fronteds compostos.
6+
7+
## Composição por Iframe
8+
9+
A utilização do iframe a princípio pareceu ser a mais simples de ser utilizada, mas
10+
durante a implementação diversos desafios e limitações foram encontadas.
11+
12+
13+
### Limitações na propagação do evento
14+
15+
A propagação do evento através de ***window.dispatchEvent*** não funcionou, pois os microfrontends encapsulados no iframe tem seu contexto totalmente isolado. Para propagar o evento para o compositor é necessário disparar o evento para ***window.parent.dispatchEvent***, com essa alteração tivemos duas consequencias a primeira foi a execução de dois disparos um para a ***window.dispatchEvent*** e ***window.parent.dispatchEvent***.
16+
17+
A segunda consequência foi que os microfrontends foram bloqueados ao tentar disparar evento para o compositor.
18+
19+
### Desafios: Bloqueio por validação de origem
20+
21+
![alt text](assets/iframe-origin-block.png)
22+
23+
Para solucionar essa questão foi criado um proxypass com o Nginx para expor todos os microfrontends no mesmo hostname e porta da composição, sendo diferenciada pelo context /angular /vue /react
24+
25+
O microfrontend em Angular está rodando em localhost:4200 e o microfrontend em Vue está rodando em localhost:8001. Foi criado a seguinte configuração com proxy-pass e rewrite do content.
26+
27+
```
28+
server {
29+
listen 8090;
30+
server_name localhost;
31+
32+
root /usr/share/nginx/html;
33+
index iframe.html;
34+
ssi off;
35+
36+
location /angular {
37+
proxy_set_header Host $host;
38+
proxy_set_header X-Real-IP $remote_addr;
39+
proxy_pass http://localhost:4200/;
40+
sub_filter_once off;
41+
sub_filter_types text/html;
42+
sub_filter "http://localhost:4200" "http://localhost:8090/angular";
43+
sub_filter '<script src="' '<script src="/angular/';
44+
}
45+
46+
location /vue {
47+
proxy_set_header Host $host;
48+
proxy_set_header X-Real-IP $remote_addr;
49+
proxy_pass http://172.18.0.1:8001/;
50+
sub_filter_once off;
51+
sub_filter_types text/html;
52+
sub_filter "http://localhost:8001" "http://localhost:8090/vue";
53+
}
54+
55+
# All locations should render through index.html
56+
error_page 404 /index.html;
57+
}
58+
```
59+
60+
61+
## Novas limitações
62+
63+
- Quando um microfrontend disparava o evento ele propagava somente até o compositor, seu parent, os seus mifrofrontends pares, irmãos, não recebem o evento;
64+
65+
- Responsividade é algo muito dificil de se trabalhar;
66+
67+
- Search Engine Optimization é impactado de forma fulminante;
68+
69+
- Sobrecarga de objetos window, causando lentidão na navegação;
70+
71+
72+
73+
74+
*Para propagar o evento entre os microfrontends foi criada uma função chamada repeater:*
75+
76+
```
77+
function repeater(ev) {
78+
var iframes = document.getElementsByTagName('iframe')
79+
for(var i = 0; i < iframes.length; i++){
80+
iframes[i].contentWindow.dispatchEvent(
81+
new CustomEvent(
82+
'increment',
83+
{
84+
detail : ev.detail
85+
}
86+
)
87+
)
88+
}
89+
}
90+
91+
```
92+
93+
---
94+
95+
96+
## Composição por Backend

assets/iframe-origin-block.png

43.4 KB
Loading

docker-compose.yml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
version: '3'
2+
services:
3+
web:
4+
image: nginx
5+
ports:
6+
- "8000:8090"
7+
volumes:
8+
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
9+
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
10+
- ./:/usr/share/nginx/html
11+
network_mode: "host"

iframe.html

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Microfront Facade - IFRAME</title>
7+
<script>
8+
9+
window.addEventListener (
10+
'increment',
11+
(ev) => {
12+
console.log(`Composer received: ${JSON.stringify(ev.detail)}`)
13+
console.log(ev.target)
14+
console.log(ev.currentTarget)
15+
repeater(ev)
16+
}
17+
)
18+
19+
function repeater(ev) {
20+
var iframes = document.getElementsByTagName('iframe')
21+
for(var i = 0; i < iframes.length; i++){
22+
iframes[i].contentWindow.dispatchEvent(
23+
new CustomEvent(
24+
'increment',
25+
{
26+
detail : ev.detail
27+
}
28+
)
29+
)
30+
}
31+
}
32+
33+
function counter (val) {
34+
var dt = document.getElementById('total');
35+
dt.innerHTML = parseInt(dt.innerHTML)+val
36+
window.dispatchEvent(
37+
new CustomEvent(
38+
'increment',
39+
{ detail: { target: 'facade', value: dt.innerHTML, origin: 'composer' } }
40+
)
41+
)
42+
}
43+
</script>
44+
</head>
45+
<body>
46+
<iframe src="http://localhost:8090/angular"></iframe>
47+
<iframe src="http://localhost:8090/vue"></iframe>
48+
<hr>
49+
<button onclick="counter(-1)" >-</button>
50+
<span id="total">0</span>
51+
<button onclick="counter( 1)" >+</button>
52+
</body>
53+
</html>

nginx/default.conf

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
server {
2+
listen 8090;
3+
server_name localhost;
4+
5+
root /usr/share/nginx/html;
6+
index iframe.html;
7+
ssi off;
8+
9+
# Redirect / to /browse
10+
#rewrite ^/$ http://localhost:8080/ redirect;
11+
12+
13+
location /angular {
14+
proxy_set_header Host $host;
15+
proxy_set_header X-Real-IP $remote_addr;
16+
proxy_pass http://localhost:4200/;
17+
18+
sub_filter_once off;
19+
sub_filter_types text/html;
20+
sub_filter "http://localhost:4200" "http://localhost:8090/angular";
21+
sub_filter '<script src="' '<script src="/angular/';
22+
}
23+
24+
location /vue {
25+
proxy_set_header Host $host;
26+
proxy_set_header X-Real-IP $remote_addr;
27+
proxy_pass http://172.18.0.1:8001/;
28+
29+
sub_filter_once off;
30+
sub_filter_types text/html;
31+
sub_filter "http://localhost:8001" "http://localhost:8090/vue";
32+
33+
}
34+
35+
# All locations should render through index.html
36+
error_page 404 /index.html;
37+
}

nginx/nginx.conf

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
user nginx;
2+
worker_processes 1;
3+
4+
error_log /var/log/nginx/error.log warn;
5+
pid /var/run/nginx.pid;
6+
7+
events {
8+
worker_connections 1024;
9+
}
10+
11+
http {
12+
13+
server {
14+
listen 8090 default_server;
15+
}
16+
17+
include /etc/nginx/mime.types;
18+
default_type application/octet-stream;
19+
20+
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
21+
'$status $body_bytes_sent "$http_referer" '
22+
'"$http_user_agent" "$http_x_forwarded_for"';
23+
access_log /var/log/nginx/access.log main;
24+
25+
sendfile on;
26+
#tcp_nopush on;
27+
28+
keepalive_timeout 65;
29+
30+
#gzip on;
31+
include /etc/nginx/conf.d/*.conf;
32+
}

0 commit comments

Comments
 (0)