SlideShare a Scribd company logo
Micro Frontends with Vue.js
PRESENTATION CONTENT
Intro
Tech part
Q&A
PMLAB – это украинская продуктовая компания c
full-cycle development в сфере Entertainment.
Мы являемся частью международного Холдинга,
который представлен в шести странах мира с
общим числом сотрудников - 1 600 человек.
У нас есть стенд, подходите пообщаемся
In web dev since 2008
JS Fest program committee member
Consultant in tech recruiting and Full Stack
JavaScript architecture
Author of the top 1 2016-2018 DOU article
https://dou.ua/lenta/articles/dont-move-abroad/
Oleksandr Tserkovnyi
FE Architect Backoffice & C team
micro-frontends-with-vuejs
Front-end Developer Handbook 2019
http://bit.ly/2GiDP3o
Image link
http://bit.ly/2UKlxSH
https://hackernoon.com/understanding-micro-frontends-b1c11585a297
Micro Frontends
https://www.cygnismedia.com/blog/micro-frontends-development/
https://www.cygnismedia.com/blog/micro-frontends-development/
Independent
deploy
When one team wants to
deploy without triggering
regression or just another
team’s part.
Clear boundaries
Test coverage, monitoring,
version control.
A&B testing ease
Easier to cover with A&B
testing individual parts
instead of hacking on top
of monolith.
Use/update any
contact/library
Micro Frontend team
decides what to use in
their project.
You might NOT need it
Is your delivery long?
Do you have many product owners in one project?
Might you trigger regression of another team?
Is your code reusable as much as possible?
You have 2-3 devs in the whole team and it is enough.
Do you need different setup for various user groups?
It is expensive
Much time, regression, communication
Hard to sell to business
Make it incremental
Dedicate only a part of resource
Sell it as multiplier
Sell it as individual products following common standard (ind. deploy)
No technologies, no tools
No industrial standard
Only two runtime options (iframe and lazy load)
It is not something, which is inevitably will become all frontends
14
Issues are the same
1. Size
2. Scalability
3. Upgrade version of main framework/library
4. Long delivery
5. Long CI&CD
One REST API to glue them all?
micro-frontends-with-vuejs
Front-end specificity
Different consumers
Not only code, but markup
No concept of scalability rules for a “container”
You cannot enter a “container” by user behalf (2g, device, surr.)
Others code might break yours
18
TECH PART
Intro
Tech part
Q&A
micro-frontends-with-vuejs
micro-frontends-with-vuejs
Backoffice
Internal usage only
Latest chrome (CSS Grids, no polyfills)
Operating since 2016
Universal for the whole company
We want
independent deploy
Team 1 wants to delivery
their small change not
affecting Team 2.
We don’t want to
stop development
Please continue delivery
of the features.
We want standards
Please be able to pass
experience to other teams,
even the outsource without
loosing the quality.
We want identical
look and feel
Every section should look
the same.
Business requirements
1. Business have to continue operating
2. Time to market
24
micro-frontends-with-vuejs
Discuss the request and possible solutions
Share the experience
POC
Set requirements (DO NOT create a spaceship, solve only your issues)
Only Vue.js
Drawn architecture
Tickets, planning and finally sprint
Grooming
Components reusability
Services reusability (data fetching, user identity etc.)
Caching of the libraries which are in use by other Micro Frontends
Routing
Integration testing
UX adaptation
TECH DEBT
Components in the common folder
Utils in the utils folder or scattered around
Unit tests coverage is something around ~0%
Constants in one file
Components reusability
https://storybook.js.org/
Industrial standard for reusable components
Separate testing (snapshot, unit, screen
capturing testing)
Force to think components concepts
Versatile (разносторонний)
to npm and global find&replace
Vue.use(BoKit) plugin instead of
import BoButton from './BoButton';
Vue.component('BoButton', BoButton);
Utilities and constants
31
Adapter
npm library
instead of global find&replace
imports left untouched but the inside
content was changed:
import { httpClient } from ‘bo-utils’;
export default httpClient;
Unit tests after separation
POC schema
1. User enters website
2. Page with core.js and other vital small JavaScript
code is loaded
3. Router is downloaded
4. User goes to some page via router
5. Encounters a spinner
6. Micro Frontend files are downloaded to the page
7. Cached libraries of the same version are used
8. Connected to the main store and router
9. Layout service places this Micro Frontend to his
placeholder
10. Rendered
11. User interaction
Don’t code just for code
1. User enters website
2. Core.js is basically what’s left inside main project and is
called SHELL
3. Router is NOT downloaded, why for?
4. User goes to some page via router
5. Encounters a spinner
6. Micro Frontend files are downloaded to the page
7. Cashing might be in the future, but for now they need
different versions
8. DO NOT Connected to the main store and router, why
for?
9. DO NOT Overengineer we have only one layout,
placeholders are just components
10. Rendered
11. User interaction
POC Fate
micro-frontends-with-vuejs
Usually thrown away
Ideal is not finished!
The milestones road
Make it
release candidate
POC is marinading on PROD
39
We polish our solution
render /destroy / initialize
static file server / CDN
export to window
stores separated / EE
own router / root router / base
Architecture entities
45
Following single responsibility principle
SHELL – core entity, set up using config
ROUTER – main routes and global routes orchestration is placed in SHELL as well (passed as a
prop during each Micro Frontend's rendering phase). Visually it is presented in sidebar. It dictates
at which URL, which Micro Frontend to run.
LOADER – this entity could fetch user's Micro Frontends versions and the Micro Frontend files
themselves.
RENDERER – component which receives a prop of Micro Frontend name, retrieves it from global
microservices storage (currently it is window[namespace] (Webpack)) using LOADER's method.
MANIFEST – a json schema, which contains list of the files created by a single Micro Frontend
and paths for these files, as they must be downloaded.
LOCALIZATION – provides an API for localization of texts within any Micro Frontend (passed as
a prop during each Micro Frontend's rendering phase).
IDENTITY – provides an API to detect user related data and ACL, for instance email (passed as a
prop during each Micro Frontend's rendering phase).
Helper source: https://www.youtube.com/watch?v=2r9KqASOSeM
Mykhailo Churilov "Front-end Microservices Architecture"
MANIFEST
47
Cache breaking
{
"app.css": "/players-search-app.ad2.css",
"app.js": "/players-search-app.ad2.js",
"chunk-vendors.css": "/players-search-chunk-vendors.ad2.css",
"chunk-vendors.js": "/players-search-chunk-vendors.ad2.js"
}
RENDERER
49
Component which receives a prop of Micro Frontend name,
retrieves it from global microservices storage (currently it is
window[namespace] (Webpack)) using LOADER's method.
<template>
<section>
<div class="microfrontend-wrapper">
<div>
<bo-loader />
</div>
</div>
<pre v-if="error" class="error">
Unable to load microfrontend '<strong>{{ name }}</strong>'
<div>
{{error.message}}
{{error.stack}}
</div>
</pre>
</section>
</template>
watch: {
$route() {
this.currentInstance && this.destroyMicrofrontend(this.currentInstance);
this.renderMicrofrontend(this.name, this.base);
}
},
mounted() {
this.renderMicrofrontend(this.name, this.base);
},
destroyed() {
this.destroyMicrofrontend(this.name);
}
async renderMicrofrontend(name, base) {
await this.$mf.ensureMicrofrontendReady(this.name);
this.isReady = false;
this.error = null;
try {
const host = document.createElement('div');
const wrapper = this.$el.querySelector('.microfrontend-wrapper div');
wrapper.innerHTML = '';
wrapper.appendChild(host);
const microfrontend = await this.$mf.getMicrofrontendByName(name);
microfrontend.render(host, { base: base });
this.currentInstance = name;
} catch (e) {
this.error = e;
throw e;
}
async destroyMicrofrontend(name) {
try {
const microfrontend =await this.$mf.getMicrofrontendByName(name);
microfrontend && microfrontend.destroy();
} finally {
this.isReady = false;
this.currentInstance = null;
}
}
LOADER
54
This entity could fetch user's Micro Frontends versions and the
Micro Frontend files themselves.
async function getManifest(uri) {
return fetch(uri).then(response => {
return response.json();
});
}
P.S. `try {} catch {}` is above
async function getFileCollection(name, version) {
const url = `/microfrontends/${name}/${version}`;
const manifest = await getManifest(`${url}/manifest.json`);
return Object.values(manifest).reduce((result, value) => {
if (value.endsWith('.js')) {
result.js.unshift(`${url}${value}`);
}
if (value.endsWith('.css')) {
result.css.unshift(`${url}${value}`);
}
return result;
},
{
css: [],
js: []
}
);
}
async function getFileCollectionWithLocalOverride(name, version) {
const port = window.__MF_DEV[name.toUpperCase()];
if (port) {
console.warn(`Microfrontend '${name}' was loaded from localhost`);
return {
js: [`//localhost:${port}/${name.toLowerCase()}-app.js?v=` + +new Date()]
};
}
return getFileCollection(name, version);
}
async ensureMicrofrontendReady(name) {
if (this.state[name]) return true;
const version = this.props.bomf.versions[name];
try {
const config = window.__MF_DEV
? await getFileCollectionWithLocalOverride(name, version)
: await getFileCollection(name, version);
for (const css of config.css || []) {/**/}
for (const js of config.js || []) {/**/}
const microfrontend = await this.getMicrofrontendByName(name);
const notify = this.props.notify;
microfrontend && microfrontend.initialize({
...this.props,
notify: {
error(e, atts = {}) {
notify.error(e, { ...atts, source: name, version }); } }
});
this.state[name] = microfrontend;
getMicrofrontendByName(name) {
const namespace = '__bo__mf__';
return window[namespace] && window[namespace][name];
}
window['__bo__mf__'] =
window['__bo__mf__'] || {},
window['__bo__mf__']['players-search'] = // ...
ROUTER
61
Main routes and global routes orchestration is placed in SHELL as well (passed as
a prop during each Micro Frontend's rendering phase). Visually it is presented in
sidebar. It dictates at which URL, which Micro Frontend to run.
const router = new Router({
mode: 'history',
routes: [
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/players/search',
components: {
default: PlayerSearch,
leftSideBar: Navigation
}
}
// …
was
const router = new Router({
mode: 'history',
routes: [
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/players/search',
components: {
leftSideBar: Navigation,
default: Microfrontend // RENDERER
},
props: { default: { name: 'players-search', base: '/' } }
},
// …
became
export const createRouter = base => {
return new Router({
mode: 'history',
routes: [
{
path: `${base}players/search`,
name: 'PlayerSearch',
component: PlayerSearch
},
// ...
{
path: `${base}players/:playerId/`,
name: 'header',
component: Player,
children: [
{
path: `trxhistory`,
name: 'trxhistory',
component: TRXHistory
},
{
path: 'auditlog',
name: 'auditlog',
components: { default: Microfrontend },
props: { default: { name: 'auditlog', base: `${base}players` } }
},
// ...
Micro Frontend entry
66
Vue.use(...);
async function initialize(props) {
applyIdentityService(props.identity);
applyLocalizationService(props.localization);
applyRootRouter(props.rootRouter);
applyEventEmitter(props.ee);
Vue.use(UIKit, {});
Vue.use(BoMicrofrontendKit, props);
Vue.config.errorHandler = err => props.notify.error(err);
}
function render(element, { base }) {}
function destroy() {}
export { initialize, render, destroy };
Local development
68
CI&CD
feature versions, deploy
Bootstrapping
69
`vue create`
`-p,--preset <presetName> Skip prompts and use saved or remote preset`
`vue create --preset gitlab:git.betlab.com:CoreFront/vue-cli-bo-microfrontend-
template --clone project-name`
micro-frontends-with-vuejs
commitlint
71
micro-frontends-with-vuejs
micro-frontends-with-vuejs
semantic-release
Backoffice for Backoffice
75
Canary releases
76
micro-frontends-with-vuejs
micro-frontends-with-vuejs
Newrelic
79
As a tool for post-production monitoring
80
81
Final architecture flow
ROUTER
Decisions and achievements
1. 2 months only
2. Did not stop feature dev
3. Last week – release
4. Business operating releases as usual
5. Move to Micro Frontend 1 day
6. Create new Micro Frontend ~5 day
7. Node.js instead of BE devs
8. Flexibility in terms of versioning
Next steps
1. Continuous deployment instead of
continuous delivery
2. Automated rollbacks based on
newrelic data
3. Performance testing of single MFE
Take away list
86
1. Sell independent deploy as key to faster time to market
2. Sell MFEs as less error prone entities due to encapsulation
3. Think about local development
4. Use vue-cli presets for fast bootstrapping
5. Use storybook
6. Use POC as release candidate
7. Groom with the team
8. Don’t build spaceship. Focus on the goal. Ideal is not finished.
THANK YOU
Q&A
Intro
Tech part
Q&A
WE ARE HIRING
http://bit.ly/2Cef3zx

More Related Content

Similar to micro-frontends-with-vuejs (20)

PDF
MicroForntends.pdf
Sagar Bhosale
 
PPTX
Micro-Frontend Architecture
Livares Technologies Pvt Ltd
 
PPTX
Vue micro frontend implementation patterns
Albert Brand
 
PDF
Micro frontends with react and redux dev day
Prasanna Venkatesan
 
PDF
JSFest 2019: Technology agnostic microservices at SPA frontend
Vlad Fedosov
 
PPTX
Building applications in a Micro-frontends way
Prasanna Venkatesan
 
PPTX
Micro Front Ends : Divided We Rule by Parth Ghiya - AhmedabadJS
KNOWARTH - Software Development Company
 
PDF
FEVR - Micro Frontend
Miki Lombardi
 
PDF
Building Micro-Frontends: Scaling Teams and Projects Empowering Developers 1s...
azmeelbronii
 
PPTX
“Micro Frontends”- You Keep Using That Word, I Don’t Think It Means What You ...
Shem Magnezi
 
PPTX
JS Fest 2019/Autumn. Влад Федосов. Technology agnostic microservices at SPA f...
JSFestUA
 
PPTX
Building Microtrends With React
Nisheed Jagadish
 
PDF
Node.js BFFs - our way to the better/micro frontends
Eugene Fidelin
 
PDF
Building Micro-Frontends: Scaling Teams and Projects Empowering Developers 1s...
pyrageisari
 
PPTX
Micro-frontends – is it a new normal?
Lohika_Odessa_TechTalks
 
PDF
The Modern Web with Microfrontends
Nikki Dingding
 
PPTX
Micro Frontends.pptx
ShanAli738907
 
PPTX
Micro Front-End & Microservices - Plansoft
Miki Lombardi
 
PDF
vue-storefront - PWA eCommerce for Magento2 MM17NYC presentation
Divante
 
PPTX
Building assets on the fly with Node.js
Acquisio
 
MicroForntends.pdf
Sagar Bhosale
 
Micro-Frontend Architecture
Livares Technologies Pvt Ltd
 
Vue micro frontend implementation patterns
Albert Brand
 
Micro frontends with react and redux dev day
Prasanna Venkatesan
 
JSFest 2019: Technology agnostic microservices at SPA frontend
Vlad Fedosov
 
Building applications in a Micro-frontends way
Prasanna Venkatesan
 
Micro Front Ends : Divided We Rule by Parth Ghiya - AhmedabadJS
KNOWARTH - Software Development Company
 
FEVR - Micro Frontend
Miki Lombardi
 
Building Micro-Frontends: Scaling Teams and Projects Empowering Developers 1s...
azmeelbronii
 
“Micro Frontends”- You Keep Using That Word, I Don’t Think It Means What You ...
Shem Magnezi
 
JS Fest 2019/Autumn. Влад Федосов. Technology agnostic microservices at SPA f...
JSFestUA
 
Building Microtrends With React
Nisheed Jagadish
 
Node.js BFFs - our way to the better/micro frontends
Eugene Fidelin
 
Building Micro-Frontends: Scaling Teams and Projects Empowering Developers 1s...
pyrageisari
 
Micro-frontends – is it a new normal?
Lohika_Odessa_TechTalks
 
The Modern Web with Microfrontends
Nikki Dingding
 
Micro Frontends.pptx
ShanAli738907
 
Micro Front-End & Microservices - Plansoft
Miki Lombardi
 
vue-storefront - PWA eCommerce for Magento2 MM17NYC presentation
Divante
 
Building assets on the fly with Node.js
Acquisio
 

Recently uploaded (20)

PDF
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
PPTX
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PDF
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
PDF
July Patch Tuesday
Ivanti
 
PDF
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
PDF
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
PDF
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
PPTX
UiPath Academic Alliance Educator Panels: Session 2 - Business Analyst Content
DianaGray10
 
PDF
HCIP-Data Center Facility Deployment V2.0 Training Material (Without Remarks ...
mcastillo49
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PPTX
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
PDF
Complete JavaScript Notes: From Basics to Advanced Concepts.pdf
haydendavispro
 
PDF
Blockchain Transactions Explained For Everyone
CIFDAQ
 
PPTX
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
PDF
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PDF
LLMs.txt: Easily Control How AI Crawls Your Site
Keploy
 
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
July Patch Tuesday
Ivanti
 
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
UiPath Academic Alliance Educator Panels: Session 2 - Business Analyst Content
DianaGray10
 
HCIP-Data Center Facility Deployment V2.0 Training Material (Without Remarks ...
mcastillo49
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
Complete JavaScript Notes: From Basics to Advanced Concepts.pdf
haydendavispro
 
Blockchain Transactions Explained For Everyone
CIFDAQ
 
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
LLMs.txt: Easily Control How AI Crawls Your Site
Keploy
 
Ad

micro-frontends-with-vuejs

  • 3. PMLAB – это украинская продуктовая компания c full-cycle development в сфере Entertainment. Мы являемся частью международного Холдинга, который представлен в шести странах мира с общим числом сотрудников - 1 600 человек.
  • 4. У нас есть стенд, подходите пообщаемся
  • 5. In web dev since 2008 JS Fest program committee member Consultant in tech recruiting and Full Stack JavaScript architecture Author of the top 1 2016-2018 DOU article https://dou.ua/lenta/articles/dont-move-abroad/ Oleksandr Tserkovnyi FE Architect Backoffice & C team
  • 7. Front-end Developer Handbook 2019 http://bit.ly/2GiDP3o Image link http://bit.ly/2UKlxSH
  • 11. Independent deploy When one team wants to deploy without triggering regression or just another team’s part. Clear boundaries Test coverage, monitoring, version control. A&B testing ease Easier to cover with A&B testing individual parts instead of hacking on top of monolith. Use/update any contact/library Micro Frontend team decides what to use in their project.
  • 12. You might NOT need it Is your delivery long? Do you have many product owners in one project? Might you trigger regression of another team? Is your code reusable as much as possible? You have 2-3 devs in the whole team and it is enough. Do you need different setup for various user groups?
  • 13. It is expensive Much time, regression, communication Hard to sell to business Make it incremental Dedicate only a part of resource Sell it as multiplier Sell it as individual products following common standard (ind. deploy)
  • 14. No technologies, no tools No industrial standard Only two runtime options (iframe and lazy load) It is not something, which is inevitably will become all frontends 14
  • 15. Issues are the same 1. Size 2. Scalability 3. Upgrade version of main framework/library 4. Long delivery 5. Long CI&CD
  • 16. One REST API to glue them all?
  • 18. Front-end specificity Different consumers Not only code, but markup No concept of scalability rules for a “container” You cannot enter a “container” by user behalf (2g, device, surr.) Others code might break yours 18
  • 22. Backoffice Internal usage only Latest chrome (CSS Grids, no polyfills) Operating since 2016 Universal for the whole company
  • 23. We want independent deploy Team 1 wants to delivery their small change not affecting Team 2. We don’t want to stop development Please continue delivery of the features. We want standards Please be able to pass experience to other teams, even the outsource without loosing the quality. We want identical look and feel Every section should look the same.
  • 24. Business requirements 1. Business have to continue operating 2. Time to market 24
  • 26. Discuss the request and possible solutions Share the experience POC Set requirements (DO NOT create a spaceship, solve only your issues) Only Vue.js Drawn architecture Tickets, planning and finally sprint Grooming
  • 27. Components reusability Services reusability (data fetching, user identity etc.) Caching of the libraries which are in use by other Micro Frontends Routing Integration testing UX adaptation
  • 28. TECH DEBT Components in the common folder Utils in the utils folder or scattered around Unit tests coverage is something around ~0% Constants in one file
  • 30. https://storybook.js.org/ Industrial standard for reusable components Separate testing (snapshot, unit, screen capturing testing) Force to think components concepts Versatile (разносторонний) to npm and global find&replace Vue.use(BoKit) plugin instead of import BoButton from './BoButton'; Vue.component('BoButton', BoButton);
  • 32. Adapter npm library instead of global find&replace imports left untouched but the inside content was changed: import { httpClient } from ‘bo-utils’; export default httpClient;
  • 33. Unit tests after separation
  • 34. POC schema 1. User enters website 2. Page with core.js and other vital small JavaScript code is loaded 3. Router is downloaded 4. User goes to some page via router 5. Encounters a spinner 6. Micro Frontend files are downloaded to the page 7. Cached libraries of the same version are used 8. Connected to the main store and router 9. Layout service places this Micro Frontend to his placeholder 10. Rendered 11. User interaction
  • 35. Don’t code just for code 1. User enters website 2. Core.js is basically what’s left inside main project and is called SHELL 3. Router is NOT downloaded, why for? 4. User goes to some page via router 5. Encounters a spinner 6. Micro Frontend files are downloaded to the page 7. Cashing might be in the future, but for now they need different versions 8. DO NOT Connected to the main store and router, why for? 9. DO NOT Overengineer we have only one layout, placeholders are just components 10. Rendered 11. User interaction
  • 38. Usually thrown away Ideal is not finished! The milestones road Make it release candidate
  • 39. POC is marinading on PROD 39 We polish our solution
  • 40. render /destroy / initialize
  • 44. own router / root router / base
  • 45. Architecture entities 45 Following single responsibility principle
  • 46. SHELL – core entity, set up using config ROUTER – main routes and global routes orchestration is placed in SHELL as well (passed as a prop during each Micro Frontend's rendering phase). Visually it is presented in sidebar. It dictates at which URL, which Micro Frontend to run. LOADER – this entity could fetch user's Micro Frontends versions and the Micro Frontend files themselves. RENDERER – component which receives a prop of Micro Frontend name, retrieves it from global microservices storage (currently it is window[namespace] (Webpack)) using LOADER's method. MANIFEST – a json schema, which contains list of the files created by a single Micro Frontend and paths for these files, as they must be downloaded. LOCALIZATION – provides an API for localization of texts within any Micro Frontend (passed as a prop during each Micro Frontend's rendering phase). IDENTITY – provides an API to detect user related data and ACL, for instance email (passed as a prop during each Micro Frontend's rendering phase). Helper source: https://www.youtube.com/watch?v=2r9KqASOSeM Mykhailo Churilov "Front-end Microservices Architecture"
  • 48. { "app.css": "/players-search-app.ad2.css", "app.js": "/players-search-app.ad2.js", "chunk-vendors.css": "/players-search-chunk-vendors.ad2.css", "chunk-vendors.js": "/players-search-chunk-vendors.ad2.js" }
  • 49. RENDERER 49 Component which receives a prop of Micro Frontend name, retrieves it from global microservices storage (currently it is window[namespace] (Webpack)) using LOADER's method.
  • 50. <template> <section> <div class="microfrontend-wrapper"> <div> <bo-loader /> </div> </div> <pre v-if="error" class="error"> Unable to load microfrontend '<strong>{{ name }}</strong>' <div> {{error.message}} {{error.stack}} </div> </pre> </section> </template>
  • 51. watch: { $route() { this.currentInstance && this.destroyMicrofrontend(this.currentInstance); this.renderMicrofrontend(this.name, this.base); } }, mounted() { this.renderMicrofrontend(this.name, this.base); }, destroyed() { this.destroyMicrofrontend(this.name); }
  • 52. async renderMicrofrontend(name, base) { await this.$mf.ensureMicrofrontendReady(this.name); this.isReady = false; this.error = null; try { const host = document.createElement('div'); const wrapper = this.$el.querySelector('.microfrontend-wrapper div'); wrapper.innerHTML = ''; wrapper.appendChild(host); const microfrontend = await this.$mf.getMicrofrontendByName(name); microfrontend.render(host, { base: base }); this.currentInstance = name; } catch (e) { this.error = e; throw e; }
  • 53. async destroyMicrofrontend(name) { try { const microfrontend =await this.$mf.getMicrofrontendByName(name); microfrontend && microfrontend.destroy(); } finally { this.isReady = false; this.currentInstance = null; } }
  • 54. LOADER 54 This entity could fetch user's Micro Frontends versions and the Micro Frontend files themselves.
  • 55. async function getManifest(uri) { return fetch(uri).then(response => { return response.json(); }); } P.S. `try {} catch {}` is above
  • 56. async function getFileCollection(name, version) { const url = `/microfrontends/${name}/${version}`; const manifest = await getManifest(`${url}/manifest.json`); return Object.values(manifest).reduce((result, value) => { if (value.endsWith('.js')) { result.js.unshift(`${url}${value}`); } if (value.endsWith('.css')) { result.css.unshift(`${url}${value}`); } return result; }, { css: [], js: [] } ); }
  • 57. async function getFileCollectionWithLocalOverride(name, version) { const port = window.__MF_DEV[name.toUpperCase()]; if (port) { console.warn(`Microfrontend '${name}' was loaded from localhost`); return { js: [`//localhost:${port}/${name.toLowerCase()}-app.js?v=` + +new Date()] }; } return getFileCollection(name, version); }
  • 58. async ensureMicrofrontendReady(name) { if (this.state[name]) return true; const version = this.props.bomf.versions[name]; try { const config = window.__MF_DEV ? await getFileCollectionWithLocalOverride(name, version) : await getFileCollection(name, version); for (const css of config.css || []) {/**/} for (const js of config.js || []) {/**/} const microfrontend = await this.getMicrofrontendByName(name); const notify = this.props.notify; microfrontend && microfrontend.initialize({ ...this.props, notify: { error(e, atts = {}) { notify.error(e, { ...atts, source: name, version }); } } }); this.state[name] = microfrontend;
  • 59. getMicrofrontendByName(name) { const namespace = '__bo__mf__'; return window[namespace] && window[namespace][name]; }
  • 60. window['__bo__mf__'] = window['__bo__mf__'] || {}, window['__bo__mf__']['players-search'] = // ...
  • 61. ROUTER 61 Main routes and global routes orchestration is placed in SHELL as well (passed as a prop during each Micro Frontend's rendering phase). Visually it is presented in sidebar. It dictates at which URL, which Micro Frontend to run.
  • 62. const router = new Router({ mode: 'history', routes: [ { path: '/login', name: 'Login', component: Login }, { path: '/players/search', components: { default: PlayerSearch, leftSideBar: Navigation } } // … was
  • 63. const router = new Router({ mode: 'history', routes: [ { path: '/login', name: 'Login', component: Login }, { path: '/players/search', components: { leftSideBar: Navigation, default: Microfrontend // RENDERER }, props: { default: { name: 'players-search', base: '/' } } }, // … became
  • 64. export const createRouter = base => { return new Router({ mode: 'history', routes: [ { path: `${base}players/search`, name: 'PlayerSearch', component: PlayerSearch }, // ...
  • 65. { path: `${base}players/:playerId/`, name: 'header', component: Player, children: [ { path: `trxhistory`, name: 'trxhistory', component: TRXHistory }, { path: 'auditlog', name: 'auditlog', components: { default: Microfrontend }, props: { default: { name: 'auditlog', base: `${base}players` } } }, // ...
  • 67. Vue.use(...); async function initialize(props) { applyIdentityService(props.identity); applyLocalizationService(props.localization); applyRootRouter(props.rootRouter); applyEventEmitter(props.ee); Vue.use(UIKit, {}); Vue.use(BoMicrofrontendKit, props); Vue.config.errorHandler = err => props.notify.error(err); } function render(element, { base }) {} function destroy() {} export { initialize, render, destroy };
  • 69. Bootstrapping 69 `vue create` `-p,--preset <presetName> Skip prompts and use saved or remote preset` `vue create --preset gitlab:git.betlab.com:CoreFront/vue-cli-bo-microfrontend- template --clone project-name`
  • 76. 76
  • 79. Newrelic 79 As a tool for post-production monitoring
  • 80. 80
  • 81. 81
  • 84. Decisions and achievements 1. 2 months only 2. Did not stop feature dev 3. Last week – release 4. Business operating releases as usual 5. Move to Micro Frontend 1 day 6. Create new Micro Frontend ~5 day 7. Node.js instead of BE devs 8. Flexibility in terms of versioning
  • 85. Next steps 1. Continuous deployment instead of continuous delivery 2. Automated rollbacks based on newrelic data 3. Performance testing of single MFE
  • 86. Take away list 86 1. Sell independent deploy as key to faster time to market 2. Sell MFEs as less error prone entities due to encapsulation 3. Think about local development 4. Use vue-cli presets for fast bootstrapping 5. Use storybook 6. Use POC as release candidate 7. Groom with the team 8. Don’t build spaceship. Focus on the goal. Ideal is not finished.
  • 88. Q&A Intro Tech part Q&A WE ARE HIRING http://bit.ly/2Cef3zx