Photo by Alexander Grey on Unsplash

Micro Frontends

Container/Layout içerisinde Micro Frontends Birleştirme Yöntemleri

Micro-frontend parçalarının bir sayfanın içerisinde birleştirilip sunulmasının farklı yöntemleri bulunuyor. Bu yazıda bütünleştirmek için hangi yöntemler kullanıldığını analiz edeceğiz.

Frontend Development With JS
6 min readApr 30, 2023

--

Bundan önceki yazımızda(Framework ve Plugin yöntemlerinde) bu konuyu değinmiştik bu yazıda konuya biraz daha detay olarak gireceğiz ve bu bütünleştirme sırasında kullanılan yöntemlerin ne olduğunu analiz edeceğiz.

Öncelikle gelin Micro-frontend ’in tanımının ne olduğunu tekrardan inceleyelim.

An architectural style where independently deliverable frontend applications are composed into a greater whole (https://martinfowler.com/)

Bağımsız olarak teslim edilebilen frontend parçalarının daha büyük bir bütün halinde oluşturulduğu bir mimari stil

Buradaki meselelerden bir tanesi bağımsız olarak geliştirilip teslim edilebilen yapılar nasıl bütünleştirilip kullanılacak ? Bu bazı yerlerde

  • Container App (Shell App)
  • Layout Engine
  • vb isimler ile kullanılabiliyor.

Burada Cam Jackson Micro-frontend yazısında bulunan entegrasyon yaklaşımlarını inceliyor olacağız.

  • Server-side template composition
  • Build-time integration
  • Run-time integration via iframes
  • Run-time integration via JavaScript
  • Run-time integration via Web Component

A. Server-Side Template Composition

Bu yöntem eskiden beri sıkça kullanılan yöntem. İşler genelde sunucu çözülüyor, bir tane index.html ve bunun içerisinde render edebileceği template (layout) yapıları bulunuyor. Buradan gelen isteklere göre fragment dediğimiz yapılar sunucu tarafında sayfanın içerisine birleştirilerek bir bütün yapı oluşturulmaya çalışılıyor.

inspired by the link’s diagram Micro Frontends

Basit olması açısından sunucu tarafından gelen yapıların render edilmiş (Render işlemi tamamlanmış) HTML parçaları(fragment) olduğunu düşünelim.

Aslında bu yapının daha dağıtık yapılması ile çok performanslı işlemler gerçekleştirilebilir. Yani

  • Layout (Birleştirme işlemlerini yapan kısım)
  • Fragment oluşturan kısımları

ayrı ayrı sunucular olarak düşünürsek birbirinden bağımsız ayrı ayrı yönetilebilen frontend parçalarını geleneksek yöntemler ile sağlamış oluruz. Bu kısımdaki Server sunucu bir Docker, Lambda Functions veya Edge Functions vb… container yapıları olabilir.

Microservis parçalarının sunucular üzerinde üretilmesi.

Bu yöntem hem güvenlik (Security), hemde (SEO) açısından avantajlar sağlasada Dinamiklik ve Sunucuda’ki üretim maliyetleri açısından dezavantajlar içerir.

Buradaki performans sorunlarını çözmek için Puzzle.js(Trendyol) ve Voltran.js(Hepsiburada) yapılarında tüm sayfanın tamamıyle oluşması gerçekleşmeden parça parça oluşsa da chunk streamler halinde en kısı zamanda görsel bir UI oluşturmayı hedefler. Aynı zamanda cache yapıları sayesinde benzer sayfa çağrımlarını

  • PuzzleJS Mimarisine Bakalım, bu mimaride StoreFront Fragment üzerinden HTML parçalarını alıp Storefront içerisinde birleştirip tarayıcıya dönüş yapıyor.
PuzzleJS Architecture
  • VoltranJS’de Oğuzhan Aslan’ ın medium blog yazısından anladığım Layout Service gelen bu parçaları birleştirip tarayıcıya tek bir ekran olarak dönen kısmı oluşturuyor. Aşağıdaki örnekte Layout Service nasıl çalıştığı basitçe anlatılmış.
VoltranJS Layout Service

Bu Layout servisinde fragment adreslerindeki micro frontend çalıştırılarak ilgili HTML, JS ve CSS kodlarının Layout içerisindeki birleşişimi görebilirsiniz.

Burada Fragment bir HTTP Servisi olarak nasıl tarayıcıya HTML dönüyor ise aynısı bir ön katman olan StoreFront yapısı içerisindeki Layout Service içerisinde toplanıp bir bütün oluşturulması sağlanıyor.

Not: Yukarıdaki framework’ ler her şeyi sunucuda render edecek diye bir durum yok sadece biz bu bölümde Server-Side Composition incelediğimiz için gelen tüm parçaların sunucu’ da render edildiğini düşünerek anlatıyoruz . Sunucu tarafında Fragment’i nasıl oluşturduğunuz anladığım kadarı ile size ve projenizin ihtiyaçlarına kalmış,

  • JS bundle,
  • veya Render Edilmiş bir HTML sayfasıda dönebilirsiniz.

peki bu gelen parçayı index sayfasına nasıl ekleyeceksiniz ?

  • fragment (iframe farklı olarak o sayfanın parçası haline gelir..)

B. Build Time Integration

Build zamanında bütünleştirme, micro frontend parçalarının build zamanında NPM paketleri halinde oluşturulması ve ana projenin package.json dosyasına eklenmesi sonucunda tüm proje tek bir bundle haline gelir.

{
"name": "@feed-me/container",
"version": "1.0.0",
"description": "A food delivery web app",
"dependencies": {
"@feed-me/browse-restaurants": "^1.2.3",
"@feed-me/order-food": "^4.5.6",
"@feed-me/user-profile": "^7.8.9"
}
}

Fakat bu yöntemde ürünün herhangi bir parçasında bir değişiklik yapmak için her bir micro frontend yeniden derlememiz (build almamız) ve yayınlamamız gerektiği anlamına geliyor. NPM sürüm ve versiyon süreci yönetilmesi oldukça zor olduğu için bu yöntem nihai kullanımda oldukça zorlayıcı olacaktır. Bundan dolayı sıkça tercih edilmez.

Uygulamamızı bağımsız olarak geliştirilebilen ve test edilebilen ayrı kod parçalarına bölmeyi başarabildikten sonra , release(yayınlama) aşamasında tüm bu bağlantıları yeniden ortaya koymayalım. Micro frontend’ leri build-time değil de run-time da birleştirebiliyor olmamız gerekiyor.

C. Run-time Integration via iFrames

iFrame ’ler eski ve basit bir birleştirme yöntemidir. Bu yöntemde iframe ler o sayfanın içerisine ayrı bir window olarak yerleştirilir, bağımsız bir alan oluşturduğu için Global değişkenlerin ve Stil değişkenlerinin çakışma imkanı yoktur. Çok iyi bir izolasyon imkanı sunar.

inspired by the link’s diagram Micro Frontends

Bu yöntemde en problemli konulardan bir tanesi bileşenlenler arası iletişim yönteminin kurulmasıdır. Bu şekilde ciddi bir izolasyon sonucunda

  • Yönlendirmeler , deep-linking ve history üzerindeki işlemler zorlaşır
  • Micro Frontend’ lerin birbirileri ile iletişim kurmaları zorlaşır.
  • Micro Frontend içerisinde ekipler çok farklı teknolojiler kullanabilir.
  • Micro Frontend içerisinde aynı teknolojilerin farklı farklı versiyonları olabilir.
  • Micro Frontend içerisinde ortak kullanım olmayacağı için aynı kütüphanelerin tekrar tekrar tarayıcıya yüklenmesi

sorunları ile karşılaşabilirsiniz.

D. Run-time integration via JavaScript

Bu yöntem diğerlerine göre en esnek olanıdır ve ekiplerin en sık benimsediğini gördüğümüz yaklaşımdır. Her bir mikro frontend <script> etiketi kullanılarak sayfaya dahil edilir ve yüklendikten sonra giriş noktası olarak global bir fonksiyon sunar. Container uygulaması daha sonra hangi micro frontend gösterilmesi gerektiğini belirler.

Bu yöntemde ServerSide yaptığımız birleştirme işlemini run-time JS bundle üzerinden gerçekleştiriyoruz

inspired by the link’s diagram Micro Frontends

Diğer yöntemler ile karşılaştıralım:

  • Build Time NPM paketleri ile statik bağlantılar kurmak yerine bu yapıları daha dinamik bir şekilde birleştirmenize olanak sağlıyor. Sayfa içerisinde Run Time bir injection işlemi gerçekleştirip bunun tamamiyle versiyonlar ile bağımlı olmasından kurtulursunuz
  • iFrame göre ise JS bundle, Server Side Composite olduğu gibi direk uygulamanın DOM yapısı içerisine RunTime enjekte ettiği için veri geçişleri , bileşen kullanımlarıda oldukça rahat bir şekilde gerçekleşir.

Burada bundle statik olarak tanımladığımız gibi aynı zamanda lazy olarak yükletebiliriz.

Aşağıdaki örnekte Container Config üzerinden Routing ile Micro Frontend bileşenlerini nasıl yükletebileceğinizi görebilirisiniz.

Bundan sonra yüklelenenler MicroFrontend bileşenleri bu bileşenlerin yapısıda aslında id üzerinden bir <div> , <main> yapısının içerisine sunucu veya herhangi bir URL indirilmiş js bundle render etmesi ile gerçekleşir.

inspired by the link’s diagram Micro Frontends

Genelde Webpack Module Federation plugin yöntemi ile yukarıdaki yapıyı webpack bundle üzerinden daha rahat oluşturabilmeniz için bir plugin sunar. Benzer yapıları Rollup, Parcel veya Vite gibi bundler bulabilirsiniz. Ama en popüler ve en çok kullanılan yöntem Webpack olduğu için bu Plugin bu dinamik JS bundle birleştirmek için basit ve başarılı bir yöntemdir.

Yukarıdaki yöntem Webpack tarafından yapılıyor olmasının bir takım avantajları vardır;

  • Ortak kütüphane bağımlılıklarını basit bir şekilde yapabilirsiniz.
  • Ayrı bir Framework ve kütüphane bağımlılık ihtiyacınızı ortadan kaldırıyor.
  • Bu nedenle yeni teknoloji veya kütüphaneler öğrenmenize gerek yok.
  • Host → Remote Micro Apps kullanıyor ama sıkı bir bağlanma yöntemi yok gevşek bir bağ ile bağlanıyor.
  • Ekstra bir bakım maliyeti oluşturmuyor.

Module Federation aslında Run-time integration via JavaScript için daha kullanışlı bir altyapı sunuyor biz geliştiricilere.

E. Run-time integration via Web Component

Son olarak da bu birleşimin Web Component’lar üzerinden yapılabileceğini anlatmışlar. JS Module’lere göre aynı yapıları Native Web Component’ları üzerinden yapmak hem tarayıcı desteği, hemde uygulamanın sadece Web Component spesifik bir düzeye çekilmesi açısından biraz kısıtlayıcı oluyor Örneğin React, Vue, Angular gibi yapılar kullanılamıyor bu durumda.

inspired by the link’s diagram Micro Frontends

Ama sadece Web Component üzerinden çalışan bir proje ise bu yöntemde tercih edilebilir.

Referanslar

Okumaya Devam Et 😃

Bu yazının devamı veya yazı grubundaki diğer yazılara erişmek için bu linke tıklayabilirsiniz.

--

--