CINXE.COM
Glimmer: Blazing Fast Rendering for Ember.js, Part 2
<!DOCTYPE html> <html lang="en"> <head> <meta name="pageKey" content="d_lithograph_content"> <!----><!----> <meta name="locale" content="en_US"> <meta id="config" data-app-id="lithograph" data-app-version="0.0.1084" data-call-tree-id="AAYn3dglPbTAxeS4QPYLoQ==" data-multiproduct-name="lithograph-publish-frontend" data-service-name="lithograph-publish-frontend" data-browser-id="004d48a8-ab1e-47fb-8363-eb2b769907b5" data-page-instance="urn:li:page:d_lithograph_content;4U5LdsJZR7emD4MwCDqWUw==" data-disable-jsbeacon-pagekey-suffix="false"> <link rel="canonical" href="https://www.linkedin.com/blog/engineering/optimization/glimmer-blazing-fast-rendering-for-ember-js-part-2"> <!----><!----> <!----> <!----> <!----> <link rel="manifest" href="/homepage-guest/manifest.json" crossorigin="use-credentials"> <link rel="icon" href="https://static.licdn.com/aero-v1/sc/h/al2o9zrvru7aqj8e1x2rzsrca"> <script> function getDfd() {let yFn,nFn;const p=new Promise(function(y, n){yFn=y;nFn=n;});p.resolve=yFn;p.reject=nFn;return p;} window.lazyloader = getDfd(); window.tracking = getDfd(); window.impressionTracking = getDfd(); window.ingraphTracking = getDfd(); window.appDetection = getDfd(); window.pemTracking = getDfd(); </script> <!----> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Glimmer: Blazing Fast Rendering for Ember.js, Part 2</title> <!----> <meta property="og:type" content="website"> <meta property="og:title" content="Glimmer: Blazing Fast Rendering for Ember.js, Part 2"> <!----> <meta property="og:url" content="https://www.linkedin.com/blog/engineering/optimization/glimmer-blazing-fast-rendering-for-ember-js-part-2"> <meta property="og:image" content="https://media.licdn.com/dms/image/v2/D4D08AQHxz9dSnAh_3Q/croft-frontend-shrinkToFit1024/croft-frontend-shrinkToFit1024/0/1700687715262?e=2147483647&v=beta&t=xeLsqm58_tS1wvMEOxtxzYwLZgT3fMSGCktTlcwuINk"> <meta name="twitter:title" content="Glimmer: Blazing Fast Rendering for Ember.js, Part 2"> <meta name="twitter:site" content="@linkedin"> <!----> <!----> <meta name="robots" content="noarchive"> <meta name="linkedin:pageTag" content="/blog/engineering/optimization/glimmer-blazing-fast-rendering-for-ember-js-part-2"> <meta name="litmsProfileName" content="lithograph"> <!----> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="asset-url" id="artdeco/static/images/icons.svg" content="https://static.licdn.com/aero-v1/sc/h/6sz1e821vgereyxaakx87tt4z "> <link rel="stylesheet" href="https://static.licdn.com/aero-v1/sc/h/crjcj3vgj0tgpae2eu4u9y7eb"> <!----> <!----> </head> <body dir="ltr"> <!----> <a href="#lithograph-app" class="skip-link btn-md btn-primary absolute z-11 -top-[100vh] focus:top-0"> Skip to main content </a> <!----> <div class="page-header__wrapper page-header__wrapper--margin" data-custom-nav-wrapper="true"> <div class="page-header__container"> <header id="page-header" class="page-header page-header--hide-dropshadow"> <div class="page-header__content-container"> <div class="header__logo"> <a href="https://www.linkedin.com/blog/engineering" class="custom-nav__logo-link"> <img class="header__linkedin-logo header__full-logo" src="https://static.licdn.com/aero-v1/sc/h/6zm111mce7vohqze950ilreo4" alt="LinkedIn Logo"> <img class="header__linkedin-logo header__in-bug" src="https://static.licdn.com/aero-v1/sc/h/5g0hjlcng3j5pgn50n2et1ca2" alt="LinkedIn Logo"> <span class="t-17 t-black t-bold default-header-title"> Engineering Blog </span> </a> </div> <!----> <!----> <button class="stripped header__expand-nav-button" data-mobile-header-navigation-button data-header-expand-navigation-button aria-expanded="false"> <li-icon class="header__expand-nav-icon" a11y-text="Open navigation" type="hamburger-icon"></li-icon> </button> <button class="stripped header__expand-nav-button hidden" data-mobile-header-navigation-button data-header-collapse-navigation-button aria-expanded="false"> <li-icon class="header__expand-nav-icon" a11y-text="Close navigation" type="cancel-icon"></li-icon> </button> </div> </header> </div> <nav class="header-nav fixed" aria-label="main" data-header-navigation> <ul class="header-nav__list"> <li> <div class="artdeco-dropdown"> <div class="artdeco-dropdown__trigger"> <a href="https://www.linkedin.com/blog/engineering/data" class="t-sans t-black--light t-semibold header-nav__toplink" target="_self"> Data </a> <button class="header-navigation__button" aria-label="Expand to show more links for Data" aria-expanded="false" data-trigger-dropdown-menu type="button"> <li-icon size="small" type="caret-filled-down-icon"></li-icon> </button> <div class="artdeco-dropdown__content header-nav__dropdown-offset"> <ul> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/graph-systems" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Graph System</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/economic-graph" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Economic Graph</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/skills-graph" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Skills Graph</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/knowledge" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Knowledge Graph</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/data-management" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Data Management</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/data-streaming-processing" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Data Streams/Processing</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/data-science" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Data Science</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/research" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Research</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/ab-testing-experimentation" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">A/B Testing/Experimentation</a> </div> </li> </ul> </div> </div> </div> </li> <li> <div class="artdeco-dropdown"> <div class="artdeco-dropdown__trigger"> <a href="https://www.linkedin.com/blog/engineering/artificial-intelligence" class="t-sans t-black--light t-semibold header-nav__toplink" target="_self"> AI </a> <button class="header-navigation__button" aria-label="Expand to show more links for AI" aria-expanded="false" data-trigger-dropdown-menu type="button"> <li-icon size="small" type="caret-filled-down-icon"></li-icon> </button> <div class="artdeco-dropdown__content header-nav__dropdown-offset"> <ul> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/machine-learning" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Machine Learning</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/natural-language-processing" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Natural Language Processing</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/generative-ai" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Generative AI</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/data-modeling" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Data Modeling</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/responsible-ai" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Responsible AI</a> </div> </li> </ul> </div> </div> </div> </li> <li> <div class="artdeco-dropdown"> <div class="artdeco-dropdown__trigger"> <a href="https://www.linkedin.com/blog/engineering/trust-and-safety" class="t-sans t-black--light t-semibold header-nav__toplink" target="_self"> Trust & Safety </a> <button class="header-navigation__button" aria-label="Expand to show more links for Trust &amp; Safety" aria-expanded="false" data-trigger-dropdown-menu type="button"> <li-icon size="small" type="caret-filled-down-icon"></li-icon> </button> <div class="artdeco-dropdown__content header-nav__dropdown-offset"> <ul> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/fairness" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Fairness</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/verification" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Verification </a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/security" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Security</a> </div> </li> </ul> </div> </div> </div> </li> <li> <div class="artdeco-dropdown"> <div class="artdeco-dropdown__trigger"> <a href="https://www.linkedin.com/blog/engineering/product-design" class="t-sans t-black--light t-semibold header-nav__toplink" target="_self"> Product Design </a> <button class="header-navigation__button" aria-label="Expand to show more links for Product Design" aria-expanded="false" data-trigger-dropdown-menu type="button"> <li-icon size="small" type="caret-filled-down-icon"></li-icon> </button> <div class="artdeco-dropdown__content header-nav__dropdown-offset"> <ul> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/marketing" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Marketing </a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/sales" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Sales</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/learning" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Learning</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/hiring" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Hiring</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/profile" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Profile</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/messaging-notifications" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Messaging/Notifications</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/feed" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Feed</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/profile" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Profile</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/groups" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Groups</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/accessibility" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Accessibility</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/member-customer-experience" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Member/Customer Experience</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/search" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Search</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/recommendations" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Recommendations</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/skills" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Skills</a> </div> </li> </ul> </div> </div> </div> </li> <li> <div class="artdeco-dropdown"> <div class="artdeco-dropdown__trigger"> <a href="https://www.linkedin.com/blog/engineering/infrastructure" class="t-sans t-black--light t-semibold header-nav__toplink" target="_self"> Infrastructure </a> <button class="header-navigation__button" aria-label="Expand to show more links for Infrastructure" aria-expanded="false" data-trigger-dropdown-menu type="button"> <li-icon size="small" type="caret-filled-down-icon"></li-icon> </button> <div class="artdeco-dropdown__content header-nav__dropdown-offset"> <ul> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/code" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Code</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/scalability" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Scalability</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/distributed-systems" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Distributed Systems</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/graph-systems" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Graph Systems</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/architecture" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Architecture</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/analytics" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Analytics</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/automation" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Automation</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/platform-platformization" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Platforms/Platformization</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/cloud-computing" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Cloud Computing</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/open-source" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Open Source</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/additional-innovations" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Additional Innovations</a> </div> </li> </ul> </div> </div> </div> </li> <li> <div class="artdeco-dropdown"> <div class="artdeco-dropdown__trigger"> <a href="https://www.linkedin.com/blog/engineering/talent" class="t-sans t-black--light t-semibold header-nav__toplink" target="_self"> Talent </a> <button class="header-navigation__button" aria-label="Expand to show more links for Talent" aria-expanded="false" data-trigger-dropdown-menu type="button"> <li-icon size="small" type="caret-filled-down-icon"></li-icon> </button> <div class="artdeco-dropdown__content header-nav__dropdown-offset"> <ul> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/culture" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Culture</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/developer-experience-productivity" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Developer Experience/Productivity</a> </div> </li> <li> <div class="artdeco-dropdown__item"> <a href="https://www.linkedin.com/blog/engineering/leadership" class="t-14 t-sans t-black t-bold header-nav__link" target="_self">Leadership</a> </div> </li> </ul> </div> </div> </div> </li> </ul> </nav> <nav class="custom-header__nav--mobile invisible" data-mobile-navigation="true" aria-label="main"> <ul class="custom-header__list--mobile"> <li class="custom-header__list-item--mobile" data-mobile-navigation-list-item="true"> <a href="https://www.linkedin.com/blog/engineering/data" class="t-16 t-sans t-black t-semibold header-nav__toplink" target="_self"> Data </a> <button class="header-navigation__button" aria-label="Expand to show more links for Data" aria-expanded="false" data-mobile-dropdown-trigger type="button"> <li-icon size="small" type="chevron-down-icon"></li-icon> </button> <ul class="custom-header__dropdownlink-list--mobile hidden" data-dropdownlinks-list="true"> <li> <a href="https://www.linkedin.com/blog/engineering/graph-systems" class="t-sans t-black t-normal header-nav__link" target="_self">Graph System</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/economic-graph" class="t-sans t-black t-normal header-nav__link" target="_self">Economic Graph</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/skills-graph" class="t-sans t-black t-normal header-nav__link" target="_self">Skills Graph</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/knowledge" class="t-sans t-black t-normal header-nav__link" target="_self">Knowledge Graph</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/data-management" class="t-sans t-black t-normal header-nav__link" target="_self">Data Management</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/data-streaming-processing" class="t-sans t-black t-normal header-nav__link" target="_self">Data Streams/Processing</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/data-science" class="t-sans t-black t-normal header-nav__link" target="_self">Data Science</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/research" class="t-sans t-black t-normal header-nav__link" target="_self">Research</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/ab-testing-experimentation" class="t-sans t-black t-normal header-nav__link" target="_self">A/B Testing/Experimentation</a> </li> </ul> </li> <li class="custom-header__list-item--mobile" data-mobile-navigation-list-item="true"> <a href="https://www.linkedin.com/blog/engineering/artificial-intelligence" class="t-16 t-sans t-black t-semibold header-nav__toplink" target="_self"> AI </a> <button class="header-navigation__button" aria-label="Expand to show more links for AI" aria-expanded="false" data-mobile-dropdown-trigger type="button"> <li-icon size="small" type="chevron-down-icon"></li-icon> </button> <ul class="custom-header__dropdownlink-list--mobile hidden" data-dropdownlinks-list="true"> <li> <a href="https://www.linkedin.com/blog/engineering/machine-learning" class="t-sans t-black t-normal header-nav__link" target="_self">Machine Learning</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/natural-language-processing" class="t-sans t-black t-normal header-nav__link" target="_self">Natural Language Processing</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/generative-ai" class="t-sans t-black t-normal header-nav__link" target="_self">Generative AI</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/data-modeling" class="t-sans t-black t-normal header-nav__link" target="_self">Data Modeling</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/responsible-ai" class="t-sans t-black t-normal header-nav__link" target="_self">Responsible AI</a> </li> </ul> </li> <li class="custom-header__list-item--mobile" data-mobile-navigation-list-item="true"> <a href="https://www.linkedin.com/blog/engineering/trust-and-safety" class="t-16 t-sans t-black t-semibold header-nav__toplink" target="_self"> Trust & Safety </a> <button class="header-navigation__button" aria-label="Expand to show more links for Trust &amp; Safety" aria-expanded="false" data-mobile-dropdown-trigger type="button"> <li-icon size="small" type="chevron-down-icon"></li-icon> </button> <ul class="custom-header__dropdownlink-list--mobile hidden" data-dropdownlinks-list="true"> <li> <a href="https://www.linkedin.com/blog/engineering/fairness" class="t-sans t-black t-normal header-nav__link" target="_self">Fairness</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/verification" class="t-sans t-black t-normal header-nav__link" target="_self">Verification </a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/security" class="t-sans t-black t-normal header-nav__link" target="_self">Security</a> </li> </ul> </li> <li class="custom-header__list-item--mobile" data-mobile-navigation-list-item="true"> <a href="https://www.linkedin.com/blog/engineering/product-design" class="t-16 t-sans t-black t-semibold header-nav__toplink" target="_self"> Product Design </a> <button class="header-navigation__button" aria-label="Expand to show more links for Product Design" aria-expanded="false" data-mobile-dropdown-trigger type="button"> <li-icon size="small" type="chevron-down-icon"></li-icon> </button> <ul class="custom-header__dropdownlink-list--mobile hidden" data-dropdownlinks-list="true"> <li> <a href="https://www.linkedin.com/blog/engineering/marketing" class="t-sans t-black t-normal header-nav__link" target="_self">Marketing </a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/sales" class="t-sans t-black t-normal header-nav__link" target="_self">Sales</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/learning" class="t-sans t-black t-normal header-nav__link" target="_self">Learning</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/hiring" class="t-sans t-black t-normal header-nav__link" target="_self">Hiring</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/profile" class="t-sans t-black t-normal header-nav__link" target="_self">Profile</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/messaging-notifications" class="t-sans t-black t-normal header-nav__link" target="_self">Messaging/Notifications</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/feed" class="t-sans t-black t-normal header-nav__link" target="_self">Feed</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/profile" class="t-sans t-black t-normal header-nav__link" target="_self">Profile</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/groups" class="t-sans t-black t-normal header-nav__link" target="_self">Groups</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/accessibility" class="t-sans t-black t-normal header-nav__link" target="_self">Accessibility</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/member-customer-experience" class="t-sans t-black t-normal header-nav__link" target="_self">Member/Customer Experience</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/search" class="t-sans t-black t-normal header-nav__link" target="_self">Search</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/recommendations" class="t-sans t-black t-normal header-nav__link" target="_self">Recommendations</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/skills" class="t-sans t-black t-normal header-nav__link" target="_self">Skills</a> </li> </ul> </li> <li class="custom-header__list-item--mobile" data-mobile-navigation-list-item="true"> <a href="https://www.linkedin.com/blog/engineering/infrastructure" class="t-16 t-sans t-black t-semibold header-nav__toplink" target="_self"> Infrastructure </a> <button class="header-navigation__button" aria-label="Expand to show more links for Infrastructure" aria-expanded="false" data-mobile-dropdown-trigger type="button"> <li-icon size="small" type="chevron-down-icon"></li-icon> </button> <ul class="custom-header__dropdownlink-list--mobile hidden" data-dropdownlinks-list="true"> <li> <a href="https://www.linkedin.com/blog/engineering/code" class="t-sans t-black t-normal header-nav__link" target="_self">Code</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/scalability" class="t-sans t-black t-normal header-nav__link" target="_self">Scalability</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/distributed-systems" class="t-sans t-black t-normal header-nav__link" target="_self">Distributed Systems</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/graph-systems" class="t-sans t-black t-normal header-nav__link" target="_self">Graph Systems</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/architecture" class="t-sans t-black t-normal header-nav__link" target="_self">Architecture</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/analytics" class="t-sans t-black t-normal header-nav__link" target="_self">Analytics</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/automation" class="t-sans t-black t-normal header-nav__link" target="_self">Automation</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/platform-platformization" class="t-sans t-black t-normal header-nav__link" target="_self">Platforms/Platformization</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/cloud-computing" class="t-sans t-black t-normal header-nav__link" target="_self">Cloud Computing</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/open-source" class="t-sans t-black t-normal header-nav__link" target="_self">Open Source</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/additional-innovations" class="t-sans t-black t-normal header-nav__link" target="_self">Additional Innovations</a> </li> </ul> </li> <li class="custom-header__list-item--mobile" data-mobile-navigation-list-item="true"> <a href="https://www.linkedin.com/blog/engineering/talent" class="t-16 t-sans t-black t-semibold header-nav__toplink" target="_self"> Talent </a> <button class="header-navigation__button" aria-label="Expand to show more links for Talent" aria-expanded="false" data-mobile-dropdown-trigger type="button"> <li-icon size="small" type="chevron-down-icon"></li-icon> </button> <ul class="custom-header__dropdownlink-list--mobile hidden" data-dropdownlinks-list="true"> <li> <a href="https://www.linkedin.com/blog/engineering/culture" class="t-sans t-black t-normal header-nav__link" target="_self">Culture</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/developer-experience-productivity" class="t-sans t-black t-normal header-nav__link" target="_self">Developer Experience/Productivity</a> </li> <li> <a href="https://www.linkedin.com/blog/engineering/leadership" class="t-sans t-black t-normal header-nav__link" target="_self">Leadership</a> </li> </ul> </li> </ul> <div class="custom-header__button-share-container--mobile"> <!----> </div> </nav> </div> <main role="main"> <div id="lithograph-app"> <section id="component-container" data-attach-collapse-behavior="true"> <div id class="component component-articleHeadline" data-component-type="articleHeadline"> <div class="article-headline-container"> <p class="article-headline__topic"> <a class="t-14" href="https://www.linkedin.com/blog/engineering/optimization">Optimization</a> </p> <h1 class="article-headline t-40" data-article-title="Glimmer: Blazing Fast Rendering for Ember.js, Part 2">Glimmer: Blazing Fast Rendering for Ember.js, Part 2</h1> <div class="article-meta t-14 article-meta__hairline"> <div class="article-meta__byline-container"> <div class="author-profile__author-container"> <img class="author-profile__author-image" srcset="https://media.licdn.com/dms/image/v2/C4E03AQELUe74rDgDEw/profile-displayphoto-shrink_100_100/profile-displayphoto-shrink_100_100/0/1652545894980?e=2147483647&v=beta&t=S975DabZUlR0kcuHx1WdYIHSThAmVN0rSWFDIsrZARo 100w,https://media.licdn.com/dms/image/v2/C4E03AQELUe74rDgDEw/profile-displayphoto-shrink_200_200/profile-displayphoto-shrink_200_200/0/1652545894980?e=2147483647&v=beta&t=Xnb3vuoYXBXNpeZ-UJaVEEcIR1tCAjHST-h-FUiI3uE 200w,https://media.licdn.com/dms/image/v2/C4E03AQELUe74rDgDEw/profile-displayphoto-shrink_400_400/profile-displayphoto-shrink_400_400/0/1652545894980?e=2147483647&v=beta&t=J1qyJThY0ftDwISlao3QNza0U2Ag4CgMYvFvMYstM94 400w,https://media.licdn.com/dms/image/v2/C4E03AQELUe74rDgDEw/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1652545894980?e=2147483647&v=beta&t=hDluNYJo3IvUGI5fVSjFKZV1Cf_9EuevlDrytinsqTw 800w," sizes="(max-width: 480px) 480px, (max-width: 767px) 767px, (max-width: 1024px) 1024px, 1920px" src="https://media.licdn.com/dms/image/v2/C4E03AQELUe74rDgDEw/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1652545894980?e=2147483647&v=beta&t=hDluNYJo3IvUGI5fVSjFKZV1Cf_9EuevlDrytinsqTw" alt="Chad Hietala"> <div class="author-profile__author-text-container"> <a href="https://www.linkedin.com/in/chadhietala" target="_blank" class="t-14 t-bold"><span class="screen-reader">Authored by</span>Chad Hietala</a> <p class="t-14">Technical Leader at LinkedIn</p> <p class="t-14 t-black--light" data-published-date="2017-6-28"> June 28, 2017 </p> </div> </div> <!----> </div> <div class="social-share"> <ul class="social-share__list share-list" title="Share via" data-share-list> <li class="share-list__item share-item"> <a href="#" class="share-item__link medium-round-muted-tertiary-button" role="button" data-tracking-control-name="_linkedin_share" data-share-type="linkedin" aria-label="Share on LinkedIn, New window will open"> <li-icon class="share-item__icon" type="linkedin-icon"></li-icon> </a> </li> <li class="share-list__item share-item"> <a href="#" class="share-item__link medium-round-muted-tertiary-button" role="button" data-tracking-control-name="_facebook_share" data-share-type="facebook" aria-label="Share on Facebook, New window will open"> <li-icon class="share-item__icon" type="facebook-icon"></li-icon> </a> </li> <li class="share-list__item share-item"> <a href="#" class="share-item__link medium-round-muted-tertiary-button" role="button" data-tracking-control-name="_twitter_share" data-share-type="twitter" aria-label="Share on Twitter, New window will open"> <li-icon class="share-item__icon" type="twitter-icon"></li-icon> </a> </li> </ul> </div> </div> </div> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p><i>Co-authors: <a href="https://www.linkedin.com/in/chadhietala/" target="_blank" data-tracking-control-name="_anchor_link">Chad Hietala</a> and <a href="https://www.linkedin.com/in/sarahclatterbuck/" target="_blank" data-tracking-control-name="_anchor_link">Sarah Clatterbuck</a></i></p> <p><i> </i></p> <p><i>Editor’s note: This is a continuation of a two-part series about the Glimmer Virtual Machine used in Ember.js for rendering. The <a href="https://engineering.linkedin.com/blog/2017/03/glimmer--blazing-fast-rendering-for-ember-js--part-1" target="_blank" data-tracking-control-name="_anchor_link">previous post</a> looked at how the AoT compiler stack allowed us to drastically reduce the payload size of all Ember applications by moving to a JSON-based wire format instead of an executable JavaScript program. This post will look at how we use the wire format at runtime within the Ember application.</i></p> <p><i>Additionally, since our first blog post, we're happy to announce that Glimmer is now <a href="https://glimmerjs.com/" target="_blank" data-tracking-control-name="_anchor_link">available as a standalone project</a> that serves as a gateway into the Ember ecosystem.</i></p> <p> </p> <p>In the <a href="https://engineering.linkedin.com/blog/2017/03/glimmer--blazing-fast-rendering-for-ember-js--part-1" target="_blank" data-tracking-control-name="_anchor_link">previous blog post</a>, we talked extensively about the advantages of the wire format in terms of template size and load time, but we did not talk about how we convert the wire format into a running application. Unlike <a href="https://facebook.github.io/react/docs/reconciliation.html" target="_blank" data-tracking-control-name="_anchor_link">DOM reconciliation</a> solutions like React, Glimmer VM is <a href="https://thefeedbackloop.xyz/designing-and-implementing-glimmer-like-a-programming-language/" target="_blank" data-tracking-control-name="_anchor_link">designed like a programming language</a> that uses two subsystems, References and Revision Tags, to make fine-grained updates to dynamic values rendered in the UI. While these subsystems differentiate Glimmer from other solutions, they also are more efficient when compared to previous rendering engines in Ember and other JavaScript frameworks.</p> <h2>Runtime stack</h2> <p>The runtime is a virtual machine (VM) architecture, which is responsible taking the wire format and producing a program that can be run to do the initial render and any subsequent renders. At a high level, the runtime looks like the following:</p> </div> </div> <div id class="component component-standaloneImage" data-component-type="standaloneImage"> <div class="standalone-image-component standalone-image-component--article-width"> <figure> <img class="standalone-image-component__image" sizes="(max-width: 480px) 480px, (max-width: 767px) 767px, (max-width: 1024px) 1024px, 1920px" data-delayed-url="https://media.licdn.com/dms/image/v2/D4D08AQHw-I7K63vI0Q/croft-frontend-shrinkToFit1024/croft-frontend-shrinkToFit1024/0/1700687716197?e=2147483647&v=beta&t=Q5HMvQBi8YKlWf_4pjuUPYLvi_gJsjJECooaRicwCSg" alt="Glimmer21"> <!----> </figure> </div> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>While a VM architecture is a novel way of modeling rendering, the initial execution of the VM sets up Reference and Revision Tag subsystems, which allow us to model a pull-based functional reactive program (FRP) used for updating the UI. What this means in practice is that there is no notion of observers or subscriptions to keep values updated in the UI, but rather that we allow the backing values in a template to freely mutate. For now, the simplest way to conceptualize this system is something like the following:</p> </div> </div> <div id class="component component-githubGist" data-component-type="githubGist"> <div class="github-gist" data-github-gist data-gist-src="https://gist.github.com/chadhietala/dc883c3de5a7bbb65f55657fc1a088c0.js" data-gist-title="Github Gist Embed"></div> <!----> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <h2>Runtime compilation and execution</h2> <p>In Ember, when the application routes to a specific URL, there is a template that is associated with that specific URL. Within Ember, we use the container system to look up the correct template object and invoke it. At this point the Glimmer VM is initialized and is now ready to compile the wire format into an executable program.</p> <p>The first thing that happens is that the wire format data is passed through a scanner that iterates over the top level. As the scanner iterates over the wire format data, it maps operations in the wire format to their corresponding compiler functions.</p> </div> </div> <div id class="component component-standaloneImage" data-component-type="standaloneImage"> <div class="standalone-image-component standalone-image-component--article-width"> <figure> <img class="standalone-image-component__image" sizes="(max-width: 480px) 480px, (max-width: 767px) 767px, (max-width: 1024px) 1024px, 1920px" data-delayed-url="https://media.licdn.com/dms/image/v2/D4D08AQH_WI9X4q9HhA/croft-frontend-shrinkToFit1024/croft-frontend-shrinkToFit1024/0/1700687716720?e=2147483647&v=beta&t=xQ2rDBdnkLg2ojK9d0lzjaU2-PO09va7fZXKhuSAsC4" alt="Glimmer23"> <!----> </figure> </div> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>There are compiler functions for every statement and expression that can be expressed in a template. Each compiler function will receive the statement or expression from the wire format along with an OpcodeBuilder (“builder” in the example above). The OpcodeBuilder is what actually creates the executable program and places values into a heap. In the example above, “builder.openPrimitiveElement” would simply do something like the following:</p> </div> </div> <div id class="component component-githubGist" data-component-type="githubGist"> <div class="github-gist" data-github-gist data-gist-src="https://gist.github.com/chadhietala/835045099f12627f89f175ce6258bc13.js" data-gist-title="Github Gist Embed"></div> <!----> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>At the end of runtime compilation, we have a byte array and strings, numbers, objects, and References in a heap. As we saw above, an operation is a 4-byte segment of the array, where the arguments, positions 1-3, are just memory addresses into the heap.</p> </div> </div> <div id class="component component-githubGist" data-component-type="githubGist"> <div class="github-gist" data-github-gist data-gist-src="https://gist.github.com/chadhietala/220b2a4c9e18377113dee3f1ce210b55.js" data-gist-title="Github Gist Embed"></div> <!----> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>Once the template has been compiled, we can then start executing the program.</p> <p><b>VM execution<br> </b>The Glimmer VM is a <a href="https://en.wikipedia.org/wiki/Stack_machine" target="_blank" data-tracking-control-name="_anchor_link">stack machine</a> that uses the <a href="https://en.wikipedia.org/wiki/Calling_convention#MIPS" target="_blank" data-tracking-control-name="_anchor_link">MIPS calling convention</a> to model its computation. Execution of the VM is simply a linear loop over the compiled program, mapping every fourth item into an operation to perform some work:</p> </div> </div> <div id class="component component-standaloneImage" data-component-type="standaloneImage"> <div class="standalone-image-component standalone-image-component--article-width"> <figure> <img class="standalone-image-component__image" sizes="(max-width: 480px) 480px, (max-width: 767px) 767px, (max-width: 1024px) 1024px, 1920px" data-delayed-url="https://media.licdn.com/dms/image/v2/D4D08AQFwmzr5M1JvWA/croft-frontend-shrinkToFit1024/croft-frontend-shrinkToFit1024/0/1700687716370?e=2147483647&v=beta&t=DwK_usuestOifCxK2UBRkfQYsQjBOJM9ZeNjN8yTRfY" alt="Glimmer24"> <!----> </figure> </div> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>In the example above, the VM would look up the 26th item in its instruction set and run that instruction. The operation will also pull the first item out of the heap to perform the operation. In the example above, this ends up looking like the following:</p> </div> </div> <div id class="component component-githubGist" data-component-type="githubGist"> <div class="github-gist" data-github-gist data-gist-src="https://gist.github.com/chadhietala/5ad85ff718bd20fb3bfd7c86f150d586.js" data-gist-title="Github Gist Embed"></div> <!----> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>The compiler structures the data so that the VM invokes a DOM construction helper that is responsible for creating the element. The above is pretty much identical with the typical DOM operations:</p> </div> </div> <div id class="component component-githubGist" data-component-type="githubGist"> <div class="github-gist" data-github-gist data-gist-src="https://gist.github.com/chadhietala/84da8ff62fa309aae7772bfcd9f982a5.js" data-gist-title="Github Gist Embed"></div> <!----> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>In the Glimmer VM, there are two categories of operations: append operations and updating operations. Since the Glimmer VM breaks down the operations to do the initial render into very terse and targeted operations, we can infer exactly how those operations will behave when they are updated. This allows us to build up the exact program to update the UI as we are executing an append program. The updating program has access to References that track and update the dynamic content in the template. Since the updating program only needs to know about the dynamic portions of the UI, it tends to be much smaller.</p> <h2>The Reference and Revision Tag systems</h2> <p>As mentioned earlier, Glimmer VM uses References and Revision Tags to update the dynamic content in a template. A “Reference” is a stable data structure used to track the actual content that is put into a template. The most basic Reference has the following interface:</p> </div> </div> <div id class="component component-githubGist" data-component-type="githubGist"> <div class="github-gist" data-github-gist data-gist-src="https://gist.github.com/chadhietala/c1a9fc1e5f2ca616b8c5a29c690f6404.js" data-gist-title="Github Gist Embed"></div> <!----> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>Unlike previous solutions in Ember, there is no notion of observers and subscriptions. Instead, we use a discrete signal to pull the value from the Reference to capture the current value to update the UI. This can be illustrated as follows:</p> </div> </div> <div id class="component component-githubGist" data-component-type="githubGist"> <div class="github-gist" data-github-gist data-gist-src="https://gist.github.com/chadhietala/dc883c3de5a7bbb65f55657fc1a088c0.js" data-gist-title="Github Gist Embed"></div> <!----> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>References are simple structures that let us model any type of computation or functional combinators. For instance, let’s take a break from our simple “Hello World” example and look at an example that concatenates and then uppercases:</p> </div> </div> <div id class="component component-githubGist" data-component-type="githubGist"> <div class="github-gist" data-github-gist data-gist-src="https://gist.github.com/chadhietala/6dad74a0e402bddd84f61756337a49da.js" data-gist-title="Github Gist Embed"></div> <!----> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>The above can be modeled with References as such:</p> </div> </div> <div id class="component component-githubGist" data-component-type="githubGist"> <div class="github-gist" data-github-gist data-gist-src="https://gist.github.com/chadhietala/c8ae025c3c20219fd26594fd565f6520.js" data-gist-title="Github Gist Embed"></div> <!----> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>As you can see, the Uppercase Reference receives the Concat Reference as an argument in its constructor. When we call “value” on it, this will cause a recursive call to the Concat Reference. Concat maps over the references, pulling their value out and joining them to create a string when we call “value.” This result is then passed back to Uppercase and we uppercase the result and return.</p> <p>Since we can model arbitrarily expensive computation, we must have a system that knows about the freshness of the computation. Otherwise the system will become volatile, performing computation when the result of that computation is idempotent. We will see later how Revision Tags are used to track the freshness of the computation.</p> <p><b>Validating and updating<br> </b>One of the challenges of building UI with JavaScript is making sure it updates instantly in response to user interaction. To do so, the system first needs to detect that a change has happened, and then efficiently determine which underlying data has changed or needs to be recomputed. In Glimmer, References use a sub-system known as “Revision Tags.” One can think of Revision Tags like HTTP E-Tags, where you have a validation “ticket” and a validator that tells you if the resource cache is stale or not. Unlike E-Tags, Revision Tags rely on a monotonically increasing counter to encode the freshness of a computation. A Revision Tag has the following interface:</p> </div> </div> <div id class="component component-githubGist" data-component-type="githubGist"> <div class="github-gist" data-github-gist data-gist-src="https://gist.github.com/chadhietala/7d9c462ae8d2d547d2cf3b90b5b79cc3.js" data-gist-title="Github Gist Embed"></div> <!----> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>The idea is pretty simple: “value” returns a “Revision,” and you pass that back into “validate” to see if it is still valid. In Glimmer, all References have a Revision Tag on them so we can quickly check to see if the computation of the reference is stale or not.</p> </div> </div> <div id class="component component-githubGist" data-component-type="githubGist"> <div class="github-gist" data-github-gist data-gist-src="https://gist.github.com/chadhietala/45e607a1397ad425eab41dedc55e70bf.js" data-gist-title="Github Gist Embed"></div> <!----> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>While this answers some questions about producing unneeded computation, it does not answer how we get new values into the system. One can think of the templating layer as a pure or side-effect-free way of modeling the UI that is backed by JavaScript, which is a highly mutable language. To bridge these two worlds, we use a collaborating object on the JavaScript side that knows how to mutate values and that the templating layer knows about. This is largely done with a “Dirtyable” Tag.</p> </div> </div> <div id class="component component-githubGist" data-component-type="githubGist"> <div class="github-gist" data-github-gist data-gist-src="https://gist.github.com/chadhietala/63a294dac4f4cf80d524430afcc463c5.js" data-gist-title="Github Gist Embed"></div> <!----> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>The Dirtyable Tag is responsible for incrementing the global revision counter, and is placed on an object that is being used to back a template. In Ember, we use “set” as a way to not only update the value dirting the reference, but also to schedule a re-validation of the UI. Below is an example of what that looks like.</p> </div> </div> <div id class="component component-githubGist" data-component-type="githubGist"> <div class="github-gist" data-github-gist data-gist-src="https://gist.github.com/chadhietala/06d6f4f89735e56d88c7a4f2ade3bbef.js" data-gist-title="Github Gist Embed"></div> <!----> </div> <div id class="component component-migratedContent" data-component-type="migratedContent"> <div class="rich-text"> <p>Since every mustache expression in our templates is backed by an object with the Dirtyable Tag on it, we know exactly when the UI needs to update. As we mentioned in the VM execution section, the initial render builds an updating program. Prior to updating the UI, we schedule a re-render, which effectively executes the opcodes in the updating program. During this process each opcode validates the tags that it knows about. If the tag is invalid, we know we need to pull compute the new value by pulling it from the Reference and update the UI with it. At the end of this process we are left with the updated UI.</p> <h2>What’s next for Glimmer VM?</h2> <p>As of today, there are quite a few things that we are thinking about with the Glimmer VM, with our primary focus being on how we can reduce the size of not only the templates of an application, but also of the VM itself. Since we are compiling the wire format into an array of bytes and a constants heap, one could imagine that our wire format could change to be more reflective of what actually gets executed by the VM.</p> <p>Since we have a VM with an evaluation loop, it’s not hard to imagine where we can start, pause, and resume execution of the VM to allow for better alignment of the browser’s rendering pipeline. It also means that there is the potential for doing streaming server-side rendering response for the initial render of the UI.</p> <p><b>Standalone Glimmer.js<br> </b>Finally, we’d like to call out the great work that’s been done by the Ember community to help launch <a href="https://glimmerjs.com/" target="_blank" data-tracking-control-name="_anchor_link">Glimmer.js</a> as a standalone component rendering library. We’re excited that more developers will have the opportunity to experience the speed and productivity of Ember's components first-hand through Glimmer.</p> <p>In the near future, we plan to use Glimmer.js components as part of a lightweight version of <a href="https://engineering.linkedin.com/blog/2016/12/pemberly-at-linkedin" target="_blank" data-tracking-control-name="_anchor_link">our Pemberly framework</a> for mobile-only and other lightweight development use cases. Separately, Ember users will be able to use standalone Glimmer components in existing Ember apps, just by installing an addon. You can read about the plans for Glimmer.js on the <a href="https://emberjs.com/blog/2017/04/05/emberconf-2017-state-of-the-union.html" target="_blank" data-tracking-control-name="_anchor_link">official Ember blog</a>.</p> </div> </div> <div id class="component component-postList" data-component-type="postList"> <section id="postList0FocusPoint" class="component__content-container list-layout" data-post-list> <section class="simple-topic-list"> <p class="t-14 t-bold">Topics: <a class="simple-topic-list__topic" href="https://www.linkedin.com/blog/engineering/culture"> Culture </a> <a class="simple-topic-list__topic" href="https://www.linkedin.com/blog/engineering/open-source"> Open Source </a> <a class="simple-topic-list__topic" href="https://www.linkedin.com/blog/engineering/code"> Code </a> </p> </section> <hr class="artdeco-divider"> <section class="list-layout__headline-container"> <p class="list-layout__headline t-32 t-sans">Related articles</p> <!----> </section> <ul class="list-layout__posts"> <li class="post-list__item list-post"> <div class="list-post__content-container"> <!----> <div class="list-post__content-container__title"> <a class="list-post__link t-20 t-black" href="https://www.linkedin.com/blog/engineering/architecture/navigating-the-transition-adopting-azure-linux-as-linkedins-operatingsystem"> Navigating the transition: adopting Azure Linux as LinkedIn’s ... </a> </div> <div class="list-post__content-container__byline"> <p class="list-post__content-container__author t-14 t-bold t-black"> Ievgen Priadka </p> <!----><!----> <p class="list-post__content-container__date t-14 t-black--light"> Aug 19, 2024 </p> </div> </div> <div class="list-post__image-container"> <figure class="post__image-figure"> <img class="post__image" alt data-delayed-url="https://media.licdn.com/dms/image/v2/D4D08AQHRArCQiAcIaw/croft-frontend-shrinkToFit1024/croft-frontend-shrinkToFit1024/0/1723836472725?e=2147483647&v=beta&t=WHpZhCcLSf-jNUHC--0cMjyAXTdVCe-Y0XX0JTA7rNo" data-ghost-url="https://static.licdn.com/aero-v1/sc/h/8pouyb1ly746xtru0x7p2axm0" sizes="(max-width: 480px) 480px, (max-width: 767px) 767px, (max-width: 1024px) 1024px, 480px"> </figure> </div> </li> <li class="post-list__item list-post"> <div class="list-post__content-container"> <p class="list-post__content-container__topic"> <a class="t-14 t-bold" href="https://www.linkedin.com/blog/engineering/open-source"> Open Source </a> </p> <div class="list-post__content-container__title"> <a class="list-post__link t-20 t-black" href="https://www.linkedin.com/blog/engineering/open-source/open-sourcing-openhouse"> Open Sourcing OpenHouse: A Control Plane for Managing Tables i... </a> </div> <div class="list-post__content-container__byline"> <p class="list-post__content-container__author t-14 t-bold t-black"> Sumedh Sakdeo </p> <p class="list-post__content-container__date t-14 t-black--light"> Mar 4, 2024 </p> </div> </div> <div class="list-post__image-container"> <figure class="post__image-figure"> <img class="post__image" alt data-delayed-url="https://media.licdn.com/dms/image/v2/D4D08AQGnzsyRFkFYCw/croft-frontend-shrinkToFit1024/croft-frontend-shrinkToFit1024/0/1709228965222?e=2147483647&v=beta&t=MJozGWTtAKkQI8RytmaxD3PVFGWKH_qApKjngNHEyIY" data-ghost-url="https://static.licdn.com/aero-v1/sc/h/8pouyb1ly746xtru0x7p2axm0" sizes="(max-width: 480px) 480px, (max-width: 767px) 767px, (max-width: 1024px) 1024px, 480px"> </figure> </div> </li> <li class="post-list__item list-post"> <div class="list-post__content-container"> <p class="list-post__content-container__topic"> <a class="t-14 t-bold" href="https://www.linkedin.com/blog/engineering/leadership"> Leadership </a> </p> <div class="list-post__content-container__title"> <a class="list-post__link t-20 t-black" href="https://www.linkedin.com/blog/engineering/leadership/why-representation-matters-in-shaping-the-future-of-engineering"> Why Representation Matters in Shaping The Future of Engineering </a> </div> <div class="list-post__content-container__byline"> <p class="list-post__content-container__author t-14 t-bold t-black"> Sabry Tozin </p> <p class="list-post__content-container__date t-14 t-black--light"> Feb 23, 2024 </p> </div> </div> <div class="list-post__image-container"> <figure class="post__image-figure"> <img class="post__image" alt data-delayed-url="https://media.licdn.com/dms/image/v2/D4D08AQFq-uxWo61UPQ/croft-frontend-shrinkToFit1024/croft-frontend-shrinkToFit1024/0/1708119705134?e=2147483647&v=beta&t=28QTXbM-BYHuCEfK4EP8Pq9dfgSX3--p8C8R3EU1zAI" data-ghost-url="https://static.licdn.com/aero-v1/sc/h/8pouyb1ly746xtru0x7p2axm0" sizes="(max-width: 480px) 480px, (max-width: 767px) 767px, (max-width: 1024px) 1024px, 480px"> </figure> </div> </li> </ul> <!----> </section> </div> <!----> </section> </div> <script src="https://static.licdn.com/aero-v1/sc/h/8hfbuq1ftcvnnx4dd5067pi0t" async></script> <script src="https://static.licdn.com/aero-v1/sc/h/dev5px9xu71l67oqmrrbimi6b" async></script> <script src="https://static.licdn.com/aero-v1/sc/h/3e9epkft4bs8unu9ky8gss8ya" async></script> </main> <footer class="li-footer bg-transparent w-full "> <ul class="li-footer__list flex flex-wrap flex-row items-start justify-start w-full h-auto min-h-[50px] my-[0px] mx-auto py-3 px-2 papabear:w-[1128px] papabear:p-0"> <li class="li-footer__item font-sans text-xs text-color-text-low-emphasis flex flex-shrink-0 justify-start p-1 relative w-50% papabear:justify-center papabear:w-auto"> <span class="sr-only">LinkedIn</span> <icon class="li-footer__copy-logo text-color-logo-brand-alt inline-block self-center h-[14px] w-[56px] mr-1" data-delayed-url="https://static.licdn.com/aero-v1/sc/h/e12h2cd8ac580qen9qdd0qks8"></icon> <span class="li-footer__copy-text flex items-center">© 2024</span> </li> <li class="li-footer__item font-sans text-xs text-color-text-low-emphasis flex flex-shrink-0 justify-start p-1 relative w-50% papabear:justify-center papabear:w-auto"> <a class="li-footer__item-link flex items-center font-sans text-xs font-bold text-color-text-low-emphasis hover:text-color-link-hover focus:text-color-link-focus" href="https://about.linkedin.com?trk=content_footer-about" data-tracking-control-name="content_footer-about" data-tracking-will-navigate> About </a> </li> <li class="li-footer__item font-sans text-xs text-color-text-low-emphasis flex flex-shrink-0 justify-start p-1 relative w-50% papabear:justify-center papabear:w-auto"> <a class="li-footer__item-link flex items-center font-sans text-xs font-bold text-color-text-low-emphasis hover:text-color-link-hover focus:text-color-link-focus" href="https://www.linkedin.com/accessibility?trk=content_footer-accessibility" data-tracking-control-name="content_footer-accessibility" data-tracking-will-navigate> Accessibility </a> </li> <li class="li-footer__item font-sans text-xs text-color-text-low-emphasis flex flex-shrink-0 justify-start p-1 relative w-50% papabear:justify-center papabear:w-auto"> <a class="li-footer__item-link flex items-center font-sans text-xs font-bold text-color-text-low-emphasis hover:text-color-link-hover focus:text-color-link-focus" href="https://www.linkedin.com/legal/user-agreement?trk=content_footer-user-agreement" data-tracking-control-name="content_footer-user-agreement" data-tracking-will-navigate> User Agreement </a> </li> <li class="li-footer__item font-sans text-xs text-color-text-low-emphasis flex flex-shrink-0 justify-start p-1 relative w-50% papabear:justify-center papabear:w-auto"> <a class="li-footer__item-link flex items-center font-sans text-xs font-bold text-color-text-low-emphasis hover:text-color-link-hover focus:text-color-link-focus" href="https://www.linkedin.com/legal/privacy-policy?trk=content_footer-privacy-policy" data-tracking-control-name="content_footer-privacy-policy" data-tracking-will-navigate> Privacy Policy </a> </li> <!----> <li class="li-footer__item font-sans text-xs text-color-text-low-emphasis flex flex-shrink-0 justify-start p-1 relative w-50% papabear:justify-center papabear:w-auto"> <a class="li-footer__item-link flex items-center font-sans text-xs font-bold text-color-text-low-emphasis hover:text-color-link-hover focus:text-color-link-focus" href="https://www.linkedin.com/legal/cookie-policy?trk=content_footer-cookie-policy" data-tracking-control-name="content_footer-cookie-policy" data-tracking-will-navigate> Cookie Policy </a> </li> <li class="li-footer__item font-sans text-xs text-color-text-low-emphasis flex flex-shrink-0 justify-start p-1 relative w-50% papabear:justify-center papabear:w-auto"> <a class="li-footer__item-link flex items-center font-sans text-xs font-bold text-color-text-low-emphasis hover:text-color-link-hover focus:text-color-link-focus" href="https://www.linkedin.com/legal/copyright-policy?trk=content_footer-copyright-policy" data-tracking-control-name="content_footer-copyright-policy" data-tracking-will-navigate> Copyright Policy </a> </li> <li class="li-footer__item font-sans text-xs text-color-text-low-emphasis flex flex-shrink-0 justify-start p-1 relative w-50% papabear:justify-center papabear:w-auto"> <a class="li-footer__item-link flex items-center font-sans text-xs font-bold text-color-text-low-emphasis hover:text-color-link-hover focus:text-color-link-focus" href="https://brand.linkedin.com/policies?trk=content_footer-brand-policy" data-tracking-control-name="content_footer-brand-policy" data-tracking-will-navigate> Brand Policy </a> </li> <li class="li-footer__item font-sans text-xs text-color-text-low-emphasis flex flex-shrink-0 justify-start p-1 relative w-50% papabear:justify-center papabear:w-auto"> <a class="li-footer__item-link flex items-center font-sans text-xs font-bold text-color-text-low-emphasis hover:text-color-link-hover focus:text-color-link-focus" href="https://www.linkedin.com/psettings/guest-controls?trk=content_footer-guest-controls" data-tracking-control-name="content_footer-guest-controls" data-tracking-will-navigate> Guest Controls </a> </li> <li class="li-footer__item font-sans text-xs text-color-text-low-emphasis flex flex-shrink-0 justify-start p-1 relative w-50% papabear:justify-center papabear:w-auto"> <a class="li-footer__item-link flex items-center font-sans text-xs font-bold text-color-text-low-emphasis hover:text-color-link-hover focus:text-color-link-focus" href="https://www.linkedin.com/help/linkedin/answer/34593?trk=content_footer-community-guide" data-tracking-control-name="content_footer-community-guide" data-tracking-will-navigate> Community Guidelines </a> </li> <!----> <li class="li-footer__item font-sans text-xs text-color-text-low-emphasis flex flex-shrink-0 justify-start p-1 relative w-50% papabear:justify-center papabear:w-auto"> <div class="collapsible-dropdown collapsible-dropdown--footer collapsible-dropdown--up flex items-center relative hyphens-auto language-selector z-2"> <!----> <ul class="collapsible-dropdown__list hidden container-raised absolute w-auto overflow-y-auto flex-col items-stretch z-1 bottom-[100%] top-auto" role="menu" tabindex="-1"> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="العربية (Arabic)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-ar_AE" data-locale="ar_AE" role="menuitem" lang="ar_AE"> العربية (Arabic) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="বাংলা (Bangla)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-bn_IN" data-locale="bn_IN" role="menuitem" lang="bn_IN"> বাংলা (Bangla) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Čeština (Czech)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-cs_CZ" data-locale="cs_CZ" role="menuitem" lang="cs_CZ"> Čeština (Czech) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Dansk (Danish)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-da_DK" data-locale="da_DK" role="menuitem" lang="da_DK"> Dansk (Danish) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Deutsch (German)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-de_DE" data-locale="de_DE" role="menuitem" lang="de_DE"> Deutsch (German) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Ελληνικά (Greek)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-el_GR" data-locale="el_GR" role="menuitem" lang="el_GR"> Ελληνικά (Greek) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="English (English) selected" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link--selected" data-tracking-control-name="language-selector-en_US" data-locale="en_US" role="menuitem" lang="en_US"> <strong>English (English)</strong> </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Español (Spanish)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-es_ES" data-locale="es_ES" role="menuitem" lang="es_ES"> Español (Spanish) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="فارسی (Persian)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-fa_IR" data-locale="fa_IR" role="menuitem" lang="fa_IR"> فارسی (Persian) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Suomi (Finnish)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-fi_FI" data-locale="fi_FI" role="menuitem" lang="fi_FI"> Suomi (Finnish) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Français (French)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-fr_FR" data-locale="fr_FR" role="menuitem" lang="fr_FR"> Français (French) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="हिंदी (Hindi)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-hi_IN" data-locale="hi_IN" role="menuitem" lang="hi_IN"> हिंदी (Hindi) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Magyar (Hungarian)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-hu_HU" data-locale="hu_HU" role="menuitem" lang="hu_HU"> Magyar (Hungarian) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Bahasa Indonesia (Indonesian)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-in_ID" data-locale="in_ID" role="menuitem" lang="in_ID"> Bahasa Indonesia (Indonesian) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Italiano (Italian)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-it_IT" data-locale="it_IT" role="menuitem" lang="it_IT"> Italiano (Italian) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="עברית (Hebrew)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-iw_IL" data-locale="iw_IL" role="menuitem" lang="iw_IL"> עברית (Hebrew) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="日本語 (Japanese)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-ja_JP" data-locale="ja_JP" role="menuitem" lang="ja_JP"> 日本語 (Japanese) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="한국어 (Korean)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-ko_KR" data-locale="ko_KR" role="menuitem" lang="ko_KR"> 한국어 (Korean) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="मराठी (Marathi)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-mr_IN" data-locale="mr_IN" role="menuitem" lang="mr_IN"> मराठी (Marathi) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Bahasa Malaysia (Malay)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-ms_MY" data-locale="ms_MY" role="menuitem" lang="ms_MY"> Bahasa Malaysia (Malay) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Nederlands (Dutch)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-nl_NL" data-locale="nl_NL" role="menuitem" lang="nl_NL"> Nederlands (Dutch) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Norsk (Norwegian)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-no_NO" data-locale="no_NO" role="menuitem" lang="no_NO"> Norsk (Norwegian) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="ਪੰਜਾਬੀ (Punjabi)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-pa_IN" data-locale="pa_IN" role="menuitem" lang="pa_IN"> ਪੰਜਾਬੀ (Punjabi) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Polski (Polish)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-pl_PL" data-locale="pl_PL" role="menuitem" lang="pl_PL"> Polski (Polish) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Português (Portuguese)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-pt_BR" data-locale="pt_BR" role="menuitem" lang="pt_BR"> Português (Portuguese) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Română (Romanian)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-ro_RO" data-locale="ro_RO" role="menuitem" lang="ro_RO"> Română (Romanian) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Русский (Russian)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-ru_RU" data-locale="ru_RU" role="menuitem" lang="ru_RU"> Русский (Russian) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Svenska (Swedish)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-sv_SE" data-locale="sv_SE" role="menuitem" lang="sv_SE"> Svenska (Swedish) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="తెలుగు (Telugu)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-te_IN" data-locale="te_IN" role="menuitem" lang="te_IN"> తెలుగు (Telugu) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="ภาษาไทย (Thai)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-th_TH" data-locale="th_TH" role="menuitem" lang="th_TH"> ภาษาไทย (Thai) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Tagalog (Tagalog)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-tl_PH" data-locale="tl_PH" role="menuitem" lang="tl_PH"> Tagalog (Tagalog) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Türkçe (Turkish)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-tr_TR" data-locale="tr_TR" role="menuitem" lang="tr_TR"> Türkçe (Turkish) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Українська (Ukrainian)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-uk_UA" data-locale="uk_UA" role="menuitem" lang="uk_UA"> Українська (Ukrainian) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="Tiếng Việt (Vietnamese)" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-vi_VN" data-locale="vi_VN" role="menuitem" lang="vi_VN"> Tiếng Việt (Vietnamese) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="简体中文 (Chinese (Simplified))" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-zh_CN" data-locale="zh_CN" role="menuitem" lang="zh_CN"> 简体中文 (Chinese (Simplified)) </button> </li> <li class="language-selector__item" role="presentation"> <!-- Adding aria-label to both the li and the button because screen reader focus goes to button on desktop and li on mobile--> <button aria-label="正體中文 (Chinese (Traditional))" class="font-sans text-xs link block py-[5px] px-2 w-full hover:cursor-pointer hover:bg-color-action hover:text-color-text-on-dark focus:bg-color-action focus:text-color-text-on-dark language-selector__link !font-regular" data-tracking-control-name="language-selector-zh_TW" data-locale="zh_TW" role="menuitem" lang="zh_TW"> 正體中文 (Chinese (Traditional)) </button> </li> <!----> </ul> <button class="language-selector__button select-none relative pr-2 font-sans text-xs font-bold text-color-text-low-emphasis hover:text-color-link-hover hover:cursor-pointer focus:text-color-link-focus focus:outline-dotted focus:outline-1" aria-expanded="false" data-tracking-control-name="footer-lang-dropdown_trigger"> <span class="language-selector__label-text mr-0.5 break-words"> Language </span> <icon class="language-selector__label-chevron w-2 h-2 absolute top-0 right-0" data-delayed-url="https://static.licdn.com/aero-v1/sc/h/cyolgscd0imw2ldqppkrb84vo"></icon> </button> </div> </li> </ul> <!----> </footer> <script src="https://static.licdn.com/aero-v1/sc/h/eh08muqvrde4h3hc6koyij5ti" async></script> <!----> </body> </html>