Are you over 18 and want to see adult content?
More Annotations
A complete backup of annikoxfiles.tumblr.com
Are you over 18 and want to see adult content?
A complete backup of arrowheadacreswesties.com
Are you over 18 and want to see adult content?
A complete backup of schoolentertainmentreborn.weebly.com
Are you over 18 and want to see adult content?
A complete backup of undermilkwood.net
Are you over 18 and want to see adult content?
A complete backup of conservativesunited.com
Are you over 18 and want to see adult content?
Favourite Annotations
Text
MICRO FRONTENDS
The DOM is the API. Custom Elements, the interoperability aspect from the Web Components Spec, are a good primitive for integration in the browser.Each team builds their component using their web technology of choice and wraps it inside a Custom Element (e.g. ).The DOM specification of this particular element (tag-name, attributes & events) acts as the contract0 PRODUCT PAGE
0 Product Page - Plain JavaScript, One Team, Client Render1 PRODUCT PAGE
1 Product Page - Plain JavaScript, Multiple Teams, ClientMICRO FRONTENDS
The DOM is the API. Custom Elements, the interoperability aspect from the Web Components Spec, are a good primitive for integration in the browser.Each team builds their component using their web technology of choice and wraps it inside a Custom Element (e.g. ).The DOM specification of this particular element (tag-name, attributes & events) acts as the contract0 PRODUCT PAGE
0 Product Page - Plain JavaScript, One Team, Client Render1 PRODUCT PAGE
1 Product Page - Plain JavaScript, Multiple Teams, ClientMICRO FRONTENDS
The DOM is the API. Custom Elements, the interoperability aspect from the Web Components Spec, are a good primitive for integration in the browser.Each team builds their component using their web technology of choice and wraps it inside a Custom Element (e.g. ).The DOM specification of this particular element (tag-name, attributes & events) acts as the contract0 PRODUCT PAGE
0 Product Page - Plain JavaScript, One Team, Client Render1 PRODUCT PAGE
1 Product Page - Plain JavaScript, Multiple Teams, ClientMICRO FRONTENDS
The DOM is the API. Custom Elements, the interoperability aspect from the Web Components Spec, are a good primitive for integration in the browser.Each team builds their component using their web technology of choice and wraps it inside a Custom Element (e.g. ).The DOM specification of this particular element (tag-name, attributes & events) acts as the contract1 PRODUCT PAGE
1 Product Page - Plain JavaScript, Multiple Teams, Client0 PRODUCT PAGE
0 Product Page - Plain JavaScript, One Team, Client RenderMICRO FRONTENDS
The DOM is the API. Custom Elements, the interoperability aspect from the Web Components Spec, are a good primitive for integration in the browser.Each team builds their component using their web technology of choice and wraps it inside a Custom Element (e.g. ).The DOM specification of this particular element (tag-name, attributes & events) acts as the contract1 PRODUCT PAGE
1 Product Page - Plain JavaScript, Multiple Teams, Client0 PRODUCT PAGE
0 Product Page - Plain JavaScript, One Team, Client RenderMICRO FRONTENDS
The DOM is the API. Custom Elements, the interoperability aspect from the Web Components Spec, are a good primitive for integration in the browser.Each team builds their component using their web technology of choice and wraps it inside a Custom Element (e.g. ).The DOM specification of this particular element (tag-name, attributes & events) acts as the contract1 PRODUCT PAGE
1 Product Page - Plain JavaScript, Multiple Teams, Client0 PRODUCT PAGE
0 Product Page - Plain JavaScript, One Team, Client RenderMICRO FRONTENDS
The DOM is the API. Custom Elements, the interoperability aspect from the Web Components Spec, are a good primitive for integration in the browser.Each team builds their component using their web technology of choice and wraps it inside a Custom Element (e.g. ).The DOM specification of this particular element (tag-name, attributes & events) acts as the contract0 PRODUCT PAGE
0 Product Page - Plain JavaScript, One Team, Client Render1 PRODUCT PAGE
1 Product Page - Plain JavaScript, Multiple Teams, ClientMICRO FRONTENDS
The DOM is the API. Custom Elements, the interoperability aspect from the Web Components Spec, are a good primitive for integration in the browser.Each team builds their component using their web technology of choice and wraps it inside a Custom Element (e.g. ).The DOM specification of this particular element (tag-name, attributes & events) acts as the contract0 PRODUCT PAGE
0 Product Page - Plain JavaScript, One Team, Client Render1 PRODUCT PAGE
1 Product Page - Plain JavaScript, Multiple Teams, ClientMICRO FRONTENDS
The DOM is the API. Custom Elements, the interoperability aspect from the Web Components Spec, are a good primitive for integration in the browser.Each team builds their component using their web technology of choice and wraps it inside a Custom Element (e.g. ).The DOM specification of this particular element (tag-name, attributes & events) acts as the contract0 PRODUCT PAGE
0 Product Page - Plain JavaScript, One Team, Client Render1 PRODUCT PAGE
1 Product Page - Plain JavaScript, Multiple Teams, ClientMICRO FRONTENDS
EXTENDING THE MICROSERVICE IDEA TO FRONTEND DEVELOPMENT View project on GitHubEN JP ES
PT
KR
RU
Techniques, strategies and recipes for building a MODERN WEB APP with MULTIPLE TEAMS that can SHIP FEATURES INDEPENDENTLY. WHAT ARE MICRO FRONTENDS? The term MICRO FRONTENDS first came up in ThoughtWorks TechnologyRadar
at the end of 2016. It extends the concepts of micro services to the frontend world. The current trend is to build a feature-rich and powerful browser application, aka single page app, which sits on top of a micro service architecture. Over time the frontend layer, often developed by a separate team, grows and gets more difficult to maintain. That’s what we call a Frontend Monolith.
The idea behind Micro Frontends is to think about a website or web app as A COMPOSITION OF FEATURES which are owned by INDEPENDENT TEAMS. Each team has a DISTINCT AREA OF BUSINESS or MISSION it cares about and specialises in. A team is CROSS FUNCTIONAL and develops its features END-TO-END, from database to user interface. However, this idea is not new. It has a lot in common with the Self-contained Systems concept. In the past approaches like this went by the name of Frontend Integration for Verticalised Systems.
But Micro Frontends is clearly a more friendly and less bulky term. MONOLITHIC FRONTENDS ORGANISATION IN VERTICALS WHAT’S A MODERN WEB APP? In the introduction I’ve used the phrase “building a modern web app”. Let’s define the assumptions that are connected with thisterm.
To put this into a broader perspective, Aral Balkan has written a blog post about what he calls the Documents‐to‐Applications Continuum. He
comes up with the concept of a sliding scale where a site, built out of STATIC DOCUMENTS, connected via links, is ON THE LEFT end and a pure behaviour driven, CONTENTLESS APPLICATION like an online photo editor is ON THE RIGHT. If you would position your project on the LEFT SIDE OF THIS SPECTRUM, an INTEGRATION ON WEBSERVER LEVEL is a good fit. With this model a server collects and CONCATENATES HTML STRINGS from all components that make up the page requested by the user. Updates are done by reloading the page from the server or replacing parts of it via ajax. Gustaf Nilsson Kotte has written a comprehensive articleon this topic.
When your user interface has to provide INSTANT FEEDBACK, even on unreliable connections, a pure server rendered site is not sufficient anymore. To implement techniques like Optimistic UI or Skeleton Screens you need to be able to also UPDATE your UI ON THE DEVICE ITSELF. Google’s term Progressive Web Appsaptly
describes the BALANCING ACT of being a good citizen of the web (progressive enhancement) while also providing app-like performance. This kind of application is located somewhere AROUND THE MIDDLE OF THE SITE-APP-CONTINUUM. Here a solely server based solution is not sufficient anymore. We have to move the INTEGRATION INTO THE BROWSER, and this is the focus of this article. CORE IDEAS BEHIND MICRO FRONTENDS * BE TECHNOLOGY AGNOSTIC Each team should be able to choose and upgrade their stack without having to coordinate with other teams. Custom Elements are a great way to hide implementation details while providing a neutral interface toothers.
* ISOLATE TEAM CODE
Don’t share a runtime, even if all teams use the same framework. Build independent apps that are self contained. Don’t rely on shared state or global variables. * ESTABLISH TEAM PREFIXES Agree on naming conventions where isolation is not possible yet. Namespace CSS, Events, Local Storage and Cookies to avoid collisions and clarify ownership. * FAVOR NATIVE BROWSER FEATURES OVER CUSTOM APIS Use Browser Events for communication instead of building a global PubSub system. If you really have to build a cross team API, try keeping it as simple as possible. * BUILD A RESILIENT SITE Your feature should be useful, even if JavaScript failed or hasn’t executed yet. Use Universal Rendering and Progressive Enhancement to improve perceived performance. -------------------------THE DOM IS THE API
Custom Elements
,
the interoperability aspect from the Web Components Spec, are a good primitive for integration in the browser. Each team builds their component USING THEIR WEB TECHNOLOGY OF CHOICE and WRAPS IT INSIDE A CUSTOM ELEMENT (e.g.PAGE COMPOSITION
Beside the CLIENT- and SERVERSIDE integration of code written in DIFFERENT FRAMEWORKS itself, there are a lot of side topics that should be discussed: mechanisms to ISOLATE JS, AVOID CSS CONFLICTS, LOAD RESOURCES as needed, SHARE COMMON RESOURCES between teams, handle DATA FETCHING and think about good LOADING STATES for the user. We’ll go into these topics one step at a time.THE BASE PROTOTYPE
The product page of this model tractor store will serve as the basis for the following examples. It features a VARIANT SELECTOR to switch between the three different tractor models. On change product image, name, price and recommendations are updated. There is also a BUY BUTTON, which adds the selected variant to the basket and a MINI BASKET at the top that updates accordingly. try in browser & inspect the code All HTML is generated client side using PLAIN JAVASCRIPT and ES6 Template Strings with NO DEPENDENCIES. The code uses a simple state/markup separation and re-renders the entire HTML client side on every change - no fancy DOM diffing and NO UNIVERSAL RENDERING for now. Also NO TEAM SEPARATION - the code is written in one js/css file. CLIENTSIDE INTEGRATION In this example, the page is split into separate components/fragments owned by three teams. TEAM CHECKOUT (blue) is now responsible for everything regarding the purchasing process - namely the BUY BUTTON and MINI BASKET. TEAM INSPIRE (green) manages the PRODUCT RECOMMENDATIONS on this page. The page itself is owned by TEAM PRODUCT(red).
try in browser & inspect the code TEAM PRODUCT decides which functionality is included and where it is positioned in the layout. The page contains information that can be provided by Team Product itself, like the product name, image and the available variants. But it also includes fragments (Custom Elements) from the other teams. HOW TO CREATE A CUSTOM ELEMENT? Lets take the BUY BUTTON as an example. Team Product includes the button simply adding}
disconnectedCallback() { ... }}
window.customElements.define('blue-buy', BlueBuy); Now every time the browser comes across a new blue-buy tag, the connectedCallback is called. this is the reference to the root DOM node of the custom element. All properties and methods of a standard DOM element like innerHTML or getAttribute() can be used. When naming your element the only requirement the spec defines is that the name must INCLUDE A DASH (-) to maintain compatibility with upcoming new HTML tags. In the upcoming examples the naming convention - is used. The team namespace guards against collisions and this way the ownership of a feature becomes obvious, simply by looking at the DOM. PARENT-CHILD COMMUNICATION / DOM MODIFICATION When the user selects another tractor in the VARIANT SELECTOR, the BUY BUTTON HAS TO BE UPDATED accordingly. To achieve this Team Product can simply REMOVE the existing element from the DOM AND INSERT a new one. container.innerHTML; // =>const prices = {
t_porsche: '66,00 €', t_fendt: '54,00 €', t_eicher: '58,00 €',};
class BlueBuy extends HTMLElement { static get observedAttributes() {return ;
}
connectedCallback() {this.render();
}
render() {
const sku = this.getAttribute('sku'); const price = prices; this.innerHTML = ``;}
attributeChangedCallback(attr, oldValue, newValue) {this.render();
}
disconnectedCallback() {...}}
window.customElements.define('blue-buy', BlueBuy); To avoid duplication a render() method is introduced which is called from connectedCallback and attributeChangedCallback. This method collects needed data and innerHTML’s the new markup. When deciding to go with a more sophisticated templating engine or framework inside the Custom Element, this is the place where its initialisation codewould go.
BROWSER SUPPORT
The above example uses the Custom Element V1 Spec which is currently supported in Chrome, Safari and Opera. But with
document-register-elementa
lightweight and battle-tested polyfill is available to make this work in all browsers. Under the hood, it uses the widely supported Mutation Observer API, so there is no hacky DOM tree watching going on in the background. FRAMEWORK COMPATIBILITY Because Custom Elements are a web standard, all major JavaScript frameworks like Angular, React, Preact, Vue or Hyperapp support them. But when you get into the details, there are still a few implementation problems in some frameworks. At Custom Elements Everywhere Rob Dodson has put together a compatibility test suite that highlights unresolved issues. CHILD-PARENT OR SIBLINGS COMMUNICATION / DOM EVENTS But passing down attributes is not sufficient for all interactions. In our example the MINI BASKET SHOULD REFRESH when the user performs a CLICK ON THE BUY BUTTON. Both fragments are owned by Team Checkout (blue), so they could build some kind of internal JavaScript API that lets the mini basket know when the button was pressed. But this would require the component instances to know each other and would also be an isolation violation. A cleaner way is to use a PubSub mechanism, where a component can publish a message and other components can subscribe to specific topics. Luckily browsers have this feature built-in. This is exactly how browser events like click, select or mouseover work. In addition to native events there is also the possibility to create higher level events with new CustomEvent(...). Events are always tied to the DOM node they were created/dispatched on. Most native events also feature bubbling. This makes it possible to listen for all events on a specific sub-tree of the DOM. If you want to listen to all events on the page, attach the event listener to the window element. Here is how the creation of the blue:basket:changed-event looks in the example: class BlueBuy extends HTMLElement { connectedCallback() {this.render();
this.firstChild.addEventListener('click', this.addToCart);}
addToCart() {
// maybe talk to an api this.dispatchEvent(new CustomEvent('blue:basket:changed', {bubbles: true,
}));
}
render() {
this.innerHTML = ``;}
disconnectedCallback() { this.firstChild.removeEventListener('click', this.addToCart);}
}
The mini basket can now subscribe to this event on window and get notified when it should refresh its data. class BlueBasket extends HTMLElement { connectedCallback() { window.addEventListener('blue:basket:changed', this.refresh);}
refresh() {
// fetch new data and render it}
disconnectedCallback() { window.removeEventListener('blue:basket:changed', this.refresh);}
}
With this approach the mini basket fragment adds a listener to a DOM element which is outside its scope (window). This should be ok for many applications, but if you are uncomfortable with this you could also implement an approach where the page itself (Team Product) listens to the event and notifies the mini basket by calling refresh()on the DOM element.
// page.js
const $ = document.getElementsByTagName; $('blue-buy').addEventListener('blue:basket:changed', function() { $('blue-basket').refresh();});
Imperatively calling DOM methods is quite uncommon, but can be found in video element api for example. If possible the use of the declarative approach (attribute change) should be preferred. SERVERSIDE RENDERING / UNIVERSAL RENDERING Custom Elements are great for integrating components inside the browser. But when building a site that is accessible on the web, chances are that initial load performance matters and users will see a white screen until all js frameworks are downloaded and executed. Additionally, it’s good to think about what happens to the site if the JavaScript fails or is blocked. Jeremy Keith explains the importance in his ebook/podcast Resilient Web Design . Therefore the ability to render the core content on the server is key. Sadly the web component spec does not talk about server rendering at all. No JavaScript, no Custom Elements :( CUSTOM ELEMENTS + SERVER SIDE INCLUDES = ❤️ To make server rendering work, the previous example is refactored. Each team has their own express server and the render() method of the Custom Element is also accessible via url. $ curl http://127.0.0.1:3000/blue-buy?sku=t_porsche The Custom Element tag name is used as the path name - attributes become query parameters. Now there is a way to server-render the content of every component. In combination with theachieved:
, which is a
feature that is available in most web servers. Yes, it’s the same technique used back in the days to embed the current date on our web sites. There are also a few alternative techniques like ESI, nodesi
, compoxure
and tailor
, but for our projects SSI has proven itself as a simple and incredibly stable solution. The #include comment is replaced with the response of /blue-buy?sku=t_porsche before the web server sends the complete page to the browser. The configuration in nginx looks like this: upstream team_blue { server team_blue:3001;}
upstream team_green { server team_green:3002;}
upstream team_red { server team_red:3003;}
server {
listen 3000;
ssi on;
location /blue {
proxy_pass http://team_blue;}
location /green {
proxy_pass http://team_green;}
location /red {
proxy_pass http://team_red;}
location / {
proxy_pass http://team_red;}
}
The directive ssi: on; enables the SSI feature and an upstream and location block is added for every team to ensure that all urls which start with /blue will be routed to the correct application (team_blue:3001). In addition the / route is mapped to team red, which is controlling the homepage / product page. This animation shows the tractor store in a browser which has JAVASCRIPT DISABLED.inspect the code
The variant selection buttons now are actual links and every click leads to a reload of the page. The terminal on the right illustrates the process of how a request for a page is routed to team red, which controls the product page and after that the markup is supplemented by the fragments from team blue and green. When switching JavaScript back on, only the server log messages for the first request will be visible. All subsequent tractor changes are handled client side, just like in the first example. In a later example the product data will be extracted from the JavaScript and loaded via a REST api as needed. You can play with this sample code on your local machine. Only Docker Compose needs to beinstalled.
git clone https://github.com/neuland/micro-frontends.git cd micro-frontends/2-composition-universal docker-compose up --build Docker then starts the nginx on port 3000 and builds the node.js image for each team. When you open http://127.0.0.1:3000/ in your browser you should see a red tractor. The combined log of docker-compose makes it easy to see what is going on in the network. Sadly there is no way to control the output color, so you have to endure the fact that team blue might be highlighted in green :) The src files are mapped into the individual containers and the node application will restart when you make a code change. Changing the nginx.conf requires a restart of docker-compose in order to have an effect. So feel free to fiddle around and give feedback. DATA FETCHING & LOADING STATES A downside of the SSI/ESI approach is, that the SLOWEST FRAGMENT DETERMINES THE RESPONSE TIME of the whole page. So it’s good when the response of a fragment can be cached. For fragments that are expensive to produce and hard to cache it’s often a good idea to exclude them from the initial render. They can be loaded asynchronously in the browser. In our example the green-recos fragment, that shows personalized recommendations is a candidate forthis.
One possible solution would be that team red just skips the SSIInclude.
BEFORE
AFTER
,
so writinga broken layout.
A better way is to use a technique called Skeleton Screens.
Team red leaves the green-recos SSI Include in the markup. In addition team green changes the SERVER-SIDE RENDER METHOD of its fragment so that it produces a SCHEMATIC VERSION OF THE CONTENT. The SKELETON MARKUP can reuse parts of the real content’s layout styles. This way it RESERVES THE NEEDED SPACE and the fill-in of the actual content does not lead to a jump. Skeleton screens are also VERY USEFUL FOR CLIENT RENDERING. When your custom element is inserted into the DOM due to a user action it could INSTANTLY RENDER THE SKELETON until the data it needs from the serverhas arrived.
Even on an ATTRIBUTE CHANGE like for the _variant select_ you can decide to switch to skeleton view until the new data arrives. This ways the user gets an indication that something is going on in the fragment. But when your endpoint responds quickly a short SKELETON FLICKER between the old and new data could also be annoying. Preserving the old data or using intelligent timeouts can help. So use this technique wisely and try to get user feedback. NAVIGATING BETWEEN PAGES TO BE CONTINUED SOON … (I PROMISE) watch the Github Repo toget notified
ADDITIONAL RESOURCES * Book: Micro Frontends in ActionWritten by me.
* Talk: Micro Frontends - MicroCPH, Copenhagen 2019(Slides
)
The Nitty Gritty Details or Frontend, Backend, 🌈 Happyend * Talk: Micro Frontends - Web Rebels, Oslo 2018(Slides
)
Think Smaller, Avoid the Monolith, ❤️the Backend * Slides: Micro Frontends - JSUnconf.eu 2017 * Talk: Break Up With Your Frontend Monolith - JS Kongress 2017 Elisabeth Engel talks about implementing Micro Frontends at gutefrage.net * Article: Micro FrontendsArticle by
Cam Jackson on Martin Fowlers Blog * Post: Micro frontends - a microservice approach to front-end webdevelopment
Tom Söderlund explains the core concept and provides links on thistopic
* Post: Microservices to Micro-FrontendsSandeep
Jain summarizes the key principals behind microservices and microfrontends
* Link Collection: Micro Frontends by Elisabeth Engel extensive list of posts, talks, tools and other resources on thistopic
* Awesome Micro Frontendsa curated
list of links by Christian Ulbrich 🕶 * Custom Elements Everywhere Making sure frameworks and custom elements can be BFFs * Tractors are purchasable at manufactum.com:)
_This store is developed by two teams using the here describedtechniques._
RELATED TECHNIQUES
* Posts: Cookie Cutter ScalingDavid
Hammet wrote a series of blog posts on this topic. * Wikipedia: Java Portlet Specification Specification that addresses similar topics for building enterpriseportals.
------------------------- THINGS TO COME … (VERY SOON)* Use Cases
* Navigating between pages * soft vs. hard navigation* universal router
* …
* Side Topics
* Isolated CSS / Coherent User Interface / Style Guides & PatternLibraries
* Performance on initial load * Performance while using the site* Loading CSS
* Loading JS
* Integration Testing* …
CONTRIBUTORS
* Koike Takayuki who translated the site to Japanese . * Jorge Beltrán who translated thesite to Spanish .
* Bruno Carneiro who translated the site to Portuguese . * Soobin Bak who translated the site toKorean .
* Sergei Babin who translated the siteto Russian .
This site is generated by Github Pages. Its source can be found at neuland/micro-frontends .THE AUTHOR
MICHAEL GEERS is a software engineer at neuland Büro für Informatik.
He worked on multiple large e-commerce projects over the last tenyears.
He loves the frontend and is passionate about design systems andweb-performance.
Follow on Twitter or GitHub.
THE BOOK 🚜
MICRO FRONTENDS IN ACTION find the interactive examples at the-tractor.store.
buy it as print or ebook from Manning Publications,
Amazon or your favorite book store.
💚 Support your local bookseller! The ISBN is 1617296872.
Every print book comes with a free code for the kindle, ebook, PDF andonline version.
Details
Copyright © 2024 ArchiveBay.com. All rights reserved. Terms of Use | Privacy Policy | DMCA | 2021 | Feedback | Advertising | RSS 2.0