Takip et

Mikro Frontendler Angular’da: Module Federation ile Pratik Rehber

Modern web uygulamaları büyüdükçe, onları geliştirmek ve sürdürmek giderek zorlaşıyor. Monolitik yapıların getirdiği kısıtlamalar, ekiplerin hızını yavaşlatırken, ölçeklenebilirlik ve esneklik gibi kritik ihtiyaçları karşılamakta yetersiz kalabiliyor. Peki, Angular projelerinizde bu zorlukların üstesinden gelmek için daha modüler, bağımsız ve verimli bir yaklaşım benimsemek mümkün mü? Bu rehber, Angular tabanlı uygulamalarınızı Mikro Frontend mimarisine taşırken, Webpack 5’in gücü olan Module Federation’ı nasıl kullanacağınızı adım adım açıklıyor.

Büyük, karmaşık ve çok özellikli web uygulamaları geliştiren ekiplerin en sık karşılaştığı sorunlardan biri, uygulamanın büyüklüğüyle doğru orantılı olarak artan geliştirme ve bakım yüküdür. Geleneksel monolitik bir mimaride, tüm kullanıcı arayüzü tek bir kod tabanında bulunur. Bu durum, başlangıçta hızlı bir geliştirme süreci sunsa da, projenin kapsamı genişledikçe ciddi zorlukları beraberinde getirir. Örneğin, küçük bir özellik değişikliği bile tüm uygulamanın yeniden derlenmesini ve dağıtılmasını gerektirebilir, bu da test süreçlerini uzatır ve hataların yayılma riskini artırır. Ayrıca, farklı ekiplerin aynı kod tabanı üzerinde eş zamanlı çalışması çakışmalara yol açabilir, bağımlılıkları içinden çıkılmaz hale getirebilir ve geliştiricilerin otonomisini sınırlar. Tek bir teknoloji yığınına sıkı sıkıya bağlı kalmak, yeni ve daha verimli teknolojileri denemeyi veya belirli alt sistemler için en uygun aracı seçmeyi imkansız hale getirir. Ölçeklendirme de ayrı bir derttir; uygulamanın tamamını ölçeklendirmek zorunda kalırken, aslında sadece belirli bir bölümünün yoğunluğunu karşılamanız gerekebilir.

İşte tam bu noktada Mikro Frontendler devreye girer. Mikro Frontend mimarisi, monolitik ön uç uygulamasını dikey olarak, işlevsel alanlara göre ayrılmış daha küçük, bağımsız birimlere bölme yaklaşımını benimser. Her bir “mikro frontend”, kendi teknolojisine, geliştirme sürecine ve dağıtım pipeline’ına sahip olabilir. Bu, ekiplerin daha küçük, yönetilebilir parçalar üzerinde odaklanmasını sağlar, bağımsız olarak geliştirme yapmalarına olanak tanır ve böylece daha hızlı yineleme ve dağıtım yapabilirler. Her bir mikro frontend kendi başına bir ürün gibi davranır, bu da takım otonomisini ve mülkiyetini artırır. Monolitik yapının aksine, bir mikro frontenddeki hata veya güncelleme diğerlerini etkilemez. Ayrıca, farklı parçaların farklı teknolojilerle (örneğin, bir bölüm Angular, diğeri React veya Vue ile) geliştirilmesine olanak tanıyarak teknoloji esnekliğini de artırır. Bu esneklik, özellikle büyük ve uzun ömürlü projelerde, zamanla değişen teknoloji trendlerine uyum sağlamak açısından hayati öneme sahiptir. Böylece, uygulamanızın belirli bölümlerini, genel yapıyı bozmadan kademeli olarak modernize edebilirsiniz. Monolitik yapının getirdiği tüm bu operasyonel ve geliştirme zorlukları, modern ve ölçeklenebilir web uygulamaları için Mikro Frontendleri cazip bir alternatif haline getirir.

Mikro Frontend Mimarisi ve Angular Ekosistemi: Neden Bu Kadar Uyumlu?

Mikro Frontend mimarisi, büyük ön uç uygulamalarını yönetilebilir, bağımsız parçalara ayırarak geliştirme sürecini hızlandırmayı, takımlar arası bağımlılıkları azaltmayı ve teknolojik esnekliği artırmayı hedefler. Temel olarak, bir web uygulamasının kullanıcı arayüzünü, mikro servislerin arka uçta yaptığı gibi, dikey olarak böler. Her bir mikro frontend, kendi iş alanına odaklanan, bağımsız olarak geliştirilebilen, test edilebilen ve dağıtılabilen bir mini uygulamadır. Bu yaklaşımın en büyük faydalarından biri, farklı ekiplerin aynı anda farklı özellikler üzerinde çalışırken birbirlerini engellemelerini önlemesidir. Örneğin, bir e-ticaret platformunda “ürün listeleme”, “sepet” ve “ödeme” gibi farklı işlevler, ayrı mikro frontendler olarak ele alınabilir. Her bir mikro frontend, kendi ekibi tarafından, kendi zaman çizelgesine göre geliştirilebilir ve canlıya alınabilir. Bu durum, “takım otonomisi” kavramını ön plana çıkarır ve ekiplerin daha hızlı ve çevik hareket etmesine olanak tanır.

Angular, güçlü modüler yapısı, bileşen tabanlı mimarisi ve zengin araç ekosistemi sayesinde Mikro Frontendler için son derece uygun bir platformdur. Angular’ın kendi modül sistemi (NgModule’ler), bağımsız işlevsellikleri gruplandırmak için doğal bir yol sunar. Her bir mikro frontend, kendi Angular modülü veya hatta kendi Angular projesi olarak düşünülebilir. Angular CLI, yeni projeler oluşturmayı, bileşenler ve modüller eklemeyi kolaylaştırarak bu parçalı yapının yönetimini basitleştirir. Ayrıca, Angular’ın güçlü tip sistemi (TypeScript) ve kapsamlı test araçları, bağımsız mikro frontendlerin kalitesini ve sürdürülebilirliğini artırmaya yardımcı olur. Router mekanizması ise farklı mikro frontendler arasında sorunsuz geçişler sağlamak için ideal bir temel sunar.

Bu uyum, Webpack 5 ile gelen Module Federation özelliği sayesinde daha da güçlenmiştir. Önceleri, Angular uygulamalarını mikro frontend mimarisine taşımak, karmaşık iframe çözümleri, kütüphane paylaşım zorlukları veya sunucu tarafında birleştirme gibi yöntemlerle biraz sancılı olabiliyordu. Ancak Module Federation, bu zorlukların çoğunu ortadan kaldırıyor. Webpack 5’in bu özelliği, farklı Webpack build’lerinin çalışma zamanında (runtime) kodlarını paylaşmasını ve dinamik olarak yüklemesini mümkün kılar. Bu, host (ana) uygulamanın, uzak (remote) bir mikro frontend tarafından açığa çıkarılan (exposed) bir bileşeni veya modülü sanki kendi projesinin bir parçasıymış gibi kolayca kullanabilmesi anlamına gelir. Angular’ın bileşen ve modül odaklı yapısıyla birleştiğinde, Module Federation, gerçek bir bağımsızlık ve dinamik yükleme kabiliyeti sunarak, Angular projelerini Mikro Frontend mimarisine entegre etmek için en modern ve verimli yollardan birini teşkil eder. Bu sinerji, büyük ölçekli Angular uygulamalarında geliştirme verimliliğini, esnekliği ve sürdürülebilirliği radikal bir şekilde artırma potansiyeline sahiptir.

Module Federation Derinlemesine: Webpack 5 ve Dinamik Modül Yükleme Nasıl Çalışır?

Webpack 5 ile birlikte hayatımıza giren Module Federation, JavaScript uygulamalarında modülerliği ve kod paylaşımını tamamen yeni bir seviyeye taşıyan devrim niteliğinde bir özelliktir. Bu özellik, farklı Webpack derlemelerinin (yani farklı projelerin) çalışma zamanında birbirleriyle kod paylaşmasını ve dinamik olarak modül yüklemesini sağlar. Geleneksel olarak, birden fazla uygulamayı tek bir sayfada çalıştırmak istediğinizde, ya her uygulamanın kendi bağımsız betiklerini yüklemesi ve global değişkenler üzerinden iletişim kurması (ki bu karmaşaya yol açar), ya da uygulamaları iframe’ler içinde izole etmek (ki bu da performans ve iletişim kısıtlamaları getirir) gibi yöntemler kullanılırdı. Module Federation, bu zorlukları aşarak, uygulamalar arası kod paylaşımını ve entegrasyonu çok daha doğal ve verimli hale getirir.

Module Federation’ın temelinde üç anahtar kavram yatar: remotes, exposes ve shared.

  • exposes (Açığa Çıkarma): Bir projenin (ki buna “remote” uygulama denir) diğer projeler tarafından kullanılmasını istediği modülleri veya bileşenleri tanımlar. Örneğin, bir “ürün kartı” bileşenini veya bir “ödeme modülünü” açığa çıkarabilirsiniz. Bu, remote uygulamanın adeta bir kütüphane gibi davranarak belirli parçalarını dış dünyaya sunmasını sağlar.
  • remotes (Uzaklar): Bir projenin (ki buna “host” uygulama denir) hangi uzak uygulamalardan hangi modülleri dinamik olarak yükleyeceğini tanımlar. Host uygulama, burada belirtilen remote uygulamaların açığa çıkardığı modülleri kendi koduna dahil edebilir ve sanki kendi projesinin bir parçasıymış gibi kullanabilir. Bu sayede, host uygulama, remote uygulamanın güncellemelerinden otomatik olarak faydalanabilir.
  • shared (Paylaşılanlar): Birden fazla uygulama arasında paylaşılan bağımlılıkları tanımlar. Bu, özellikle büyük framework’ler (Angular, React, Vue gibi) veya büyük kütüphaneler (RxJS, Lodash gibi) için kritik öneme sahiptir. shared yapılandırması sayesinde, her mikro frontend kendi Angular kopyasını yüklemek yerine, sadece bir kopyanın tüm uygulamalar tarafından paylaşılmasını sağlayabiliriz. Bu, uygulama boyutunu önemli ölçüde küçültür ve yükleme performansını artırır. Ayrıca, singleton: true gibi seçeneklerle, paylaşılan modülün yalnızca bir örneğinin (singleton) yüklendiğinden emin olunabilir, bu da bağımlılık çatışmalarını önler ve tutarlılığı garanti eder.

Peki, bu dinamik modül yükleme süreci nasıl işler? Bir host uygulama, bir remote uygulamanın açığa çıkardığı bir modülü kullanmaya çalıştığında, Module Federation çalışma zamanında remote uygulamanın manifest dosyasını (uzak bir URL üzerinden) yükler. Bu manifest dosyası, remote uygulamanın hangi modülleri açığa çıkardığını ve bu modüllerin nerede bulunduğunu belirtir. Host uygulama daha sonra bu bilgilere dayanarak gerekli modülü dinamik olarak indirir ve kendi uygulama bağlamına enjekte eder. Bu süreç, genellikle bir promise veya async/await yapısı ile yönetilir, bu da modüllerin asenkron olarak yüklenmesini ve uygulamanın kullanıcı deneyimini engellememesini sağlar. Örneğin, bir Angular uygulamasında, host uygulamanın bir rota tanımında veya bir bileşenin içindeki bir dinamik import ifadesinde uzak bir bileşeni veya modülü çağırabilirsiniz. Webpack’in arkaplanda yaptığı tüm bu karmaşık işler sayesinde, geliştiriciler olarak biz, bu dinamik yüklemeyi oldukça basit bir şekilde entegre edebilir ve uygulamanın modülerliğini artırabiliriz. Bu dinamik yükleme yeteneği, özellikle büyük kurumsal uygulamalarda, farklı takımların birbirinden bağımsız olarak geliştirdiği parçaları ana uygulamaya kolayca entegre etme imkanı sunarak geliştirme verimliliğini ve çevikliği maksimize eder.

Pratik Uygulama: Angular ile Module Federation Adım Adım

Şimdi Angular uygulamalarımızda Module Federation’ı nasıl hayata geçireceğimize dair adım adım pratik bir uygulama yapalım. Bu bölümde, bir “host” (ana) uygulama ve bir “remote” (uzak) uygulama oluşturup, remote uygulamanın bir bileşenini host uygulamada nasıl dinamik olarak kullanacağımızı göreceğiz.

Adım 1: Yeni Angular Projeleri Oluşturma

Öncelikle, iki adet Angular projesi oluşturalım. Birisi ana uygulamamız (host), diğeri ise paylaşacağımız bileşeni içeren mikro frontend (remote) olacak.


        ng new host-app --no-standalone --routing --style=scss
        ng new remote-app --no-standalone --routing --style=scss
    

--no-standalone bayrağını kullanıyoruz çünkü şu anki Module Federation entegrasyonu genellikle NgModule tabanlı uygulamalarla daha sorunsuz çalışmaktadır.

Adım 2: Custom Webpack Yapılandırmasını Entegre Etme

Angular CLI, varsayılan olarak Webpack yapılandırmasını gizler. Module Federation'ı kullanabilmek için bu yapılandırmaya erişmemiz ve onu genişletmemiz gerekiyor. Bunun için @angular-architects/module-federation paketini kullanacağız.

Her iki projede de aşağıdaki komutu çalıştırın:


        cd host-app
        npm i @angular-architects/module-federation@latest --save-dev
        ng add @angular-architects/module-federation --project host-app --port 4200 --type host
        cd ../remote-app
        npm i @angular-architects/module-federation@latest --save-dev
        ng add @angular-architects/module-federation --project remote-app --port 4201 --type remote
    

ng add komutu, projenize otomatik olarak bir webpack.config.js dosyası ekleyecek ve angular.json dosyanızdaki build ve serve yapılandırmalarını güncelleyecektir. --type host ve --type remote parametreleri, sırasıyla uygulamanın host mu yoksa remote mu olacağını belirler.

Adım 3: Remote Uygulamayı Yapılandırma (remote-app)

remote-app projesinin kök dizinindeki webpack.config.js dosyasını açın. Bu dosyada ModuleFederationPlugin'in yapılandırmasını bulacaksınız. Bizim Remote uygulamamız bir bileşen açığa çıkaracak.

Öncelikle, açığa çıkaracağımız bir bileşen oluşturalım:


        cd remote-app
        ng g c products/product-list
    

src/app/products/product-list/product-list.component.ts dosyasının içeriği basit olabilir:


        import { Component, OnInit } from '@angular/core';

        @Component({
          selector: 'app-product-list',
          template: 

Remote Ürün Listesi

  • Ürün A
  • Ürün B
  • Ürün C

Bu bileşen remote-app'ten yüklenmiştir.

, styles: [:host { display: block; border: 1px solid blue; padding: 15px; margin: 10px; background-color: #e0e7ff; border-radius: 8px; } h2 { color: #3f51b5; } ul { list-style-type: disc; margin-left: 20px; } li { margin-bottom: 5px; }] }) export class ProductListComponent implements OnInit { constructor() { } ngOnInit(): void { } }

Şimdi bu bileşeni dış dünyaya açığa çıkarmak için webpack.config.js dosyasını güncelleyelim:


        const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');

        module.exports = withModuleFederationPlugin({
          name: 'remoteApp', // Uzak uygulamanın adı
          exposes: {
            // Dışa açtığımız bileşen veya modül
            './ProductListComponent': './src/app/products/product-list/product-list.component.ts',
          },
          shared: {
            ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }),
          },
        });
    

name alanı, bu remote uygulamanın diğer uygulamalar tarafından tanınmasını sağlayacak benzersiz bir kimliktir. exposes altında, key olarak host uygulamanın kullanacağı adı, value olarak ise açığa çıkarılan dosyanın yolunu veriyoruz. shared alanı, Angular ve diğer kütüphanelerin tek bir kopyasının yüklenmesini sağlar.

Adım 4: Host Uygulamayı Yapılandırma (host-app)

host-app projesinin kök dizinindeki webpack.config.js dosyasını açın. Burada remotes kısmını güncelleyeceğiz:


        const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');

        module.exports = withModuleFederationPlugin({
          remotes: {
            // Uzak uygulamayı ve URL'sini belirtiyoruz
            "remoteApp": "http://localhost:4201/remoteEntry.js",
          },
          shared: {
            ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }),
          },
        });
    

remotes altında, key olarak remote uygulamanın adını (remoteApp), value olarak ise remote uygulamanın remoteEntry.js dosyasının URL'sini belirtiyoruz. Bu dosya, remote uygulamanın hangi modülleri açığa çıkardığına dair meta bilgileri içerir.

Adım 5: Host Uygulamada Uzak Bileşeni Kullanma

Şimdi host-app içinde remote-app'ten gelen ProductListComponent'i dinamik olarak yükleyelim. Bunun en kolay yolu Angular router ile lazy loading kullanmaktır. Host uygulamanın src/app/app.module.ts dosyasında herhangi bir değişiklik yapmamıza gerek yok. src/app/app-routing.module.ts dosyasını açalım:


        import { NgModule } from '@angular/core';
        import { RouterModule, Routes } from '@angular/router';

        const routes: Routes = [
          {
            path: 'products',
            loadChildren: () =>
              import('remoteApp/ProductListComponent').then(m => m.ProductListComponent)
              // Dynamik olarak remoteApp'ten ProductListComponent'i yüklüyoruz.
              // Dikkat: Burada doğrudan bir bileşeni yüklüyoruz. Genellikle bir modülü yüklemek daha yaygındır.
              // Bir modül yüklemek isterseniz: import('remoteApp/ProductsModule').then(m => m.ProductsModule)
          },
        ];

        @NgModule({
          imports: [RouterModule.forRoot(routes)],
          exports: [RouterModule]
        })
        export class AppRoutingModule { }
    

Bu örnekte, bir bileşeni doğrudan yükledik. Daha gerçekçi senaryolarda, genellikle bir feature modülünü (örneğin, ProductsModule) açığa çıkarıp onu yüklersiniz. Eğer bir modül açığa çıkaracaksanız, remote-app'in webpack.config.js dosyasında './ProductsModule': './src/app/products/products.module.ts' şeklinde bir expose tanımı yapmalı ve host-app'in router'ında import('remoteApp/ProductsModule').then(m => m.ProductsModule) şeklinde kullanmalısınız.

Son olarak, host-app'in src/app/app.component.html dosyasına bir navigasyon linki ekleyelim:


        

Host Uygulaması

Adım 6: Uygulamaları Çalıştırma

Önce remote uygulamayı başlatın:


        cd remote-app
        npm start
        // veya ng serve --port 4201
    

Sonra host uygulamayı başlatın:


        cd host-app
        npm start
        // veya ng serve --port 4200
    

Tarayıcınızda http://localhost:4200 adresine gidin ve "Ürünler (Remote)" linkine tıklayın. remote-app'ten gelen ProductListComponent'in host-app içinde sorunsuz bir şekilde yüklendiğini göreceksiniz. Bu, farklı Angular projelerinin dinamik olarak nasıl birleşebildiğini gösteren güçlü bir örnektir.

Uzman İpucu: Modül Federasyonu ile Angular bileşenlerini paylaşırken, paylaşılan bağımlılıklarınızın (özellikle Angular kendisinin) tekil (singleton) olduğundan emin olun. Bu, gereksiz kod indirmelerini önler ve çalışma zamanı hatalarını minimize eder.

Gerçek Dünya Senaryoları ve Vaka Analizleri

Module Federation ile Angular mikro frontendlerini uygulamak, teoride kulağa hoş gelse de, gerçek dünya senaryolarında nasıl bir dönüşüm yarattığını anlamak kritik öneme sahiptir. Monolitik yapıların getirdiği tıkanıklıkları aşmada Module Federation'ın sunduğu çözümler, özellikle büyük ölçekli ve hızla gelişen projelerde kendini gösterir.

Vaka Analizi 1: E-ticaret Platformu

Büyük bir e-ticaret platformu hayal edelim. Bu platformda "Ürün Listeleme", "Ürün Detayı", "Sepet", "Ödeme", "Hesabım" ve "Müşteri Desteği" gibi birçok farklı işlevsel alan bulunur. Geleneksel monolitik bir yaklaşımda, tüm bu özellikler tek bir Angular projesinde geliştirilip, aynı ekip tarafından veya büyük bir ekibin farklı grupları tarafından yönetilir. Her bir değişiklik, tüm uygulamanın yeniden dağıtılmasını gerektirir, bu da geliştirme hızını ve çevikliği olumsuz etkiler. Module Federation sayesinde bu platformu aşağıdaki gibi mikro frontendlere ayırabiliriz:

  • Host Uygulama (Kabuk): Sadece ana navigasyonu, site genelindeki başlık ve altbilgiyi (header/footer) ve rotaları yönetir. Kendisi çok az iş mantığı içerir.
  • Ürün Mikro Frontend: "Ürün Listeleme" ve "Ürün Detayı" sayfalarını içerir. Kendi ekibi tarafından geliştirilir ve bağımsız olarak dağıtılır. Yeni filtreleme özellikleri veya ürün görselleştirme araçları eklenirken diğer ekipleri etkilemez.
  • Sepet Mikro Frontend: Kullanıcının sepetine ürün ekleme, çıkarma ve miktar güncelleme işlevselliğini sunar. Kendi özel indirim kurallarını veya karmaşık sepet mantığını geliştirebilir.
  • Ödeme Mikro Frontend: Kredi kartı girişi, adres bilgileri ve ödeme sağlayıcı entegrasyonlarını yönetir. PCI DSS uyumluluğu gibi kritik güvenlik gereksinimleri nedeniyle izole edilmesi özellikle önemlidir.
  • Hesabım Mikro Frontend: Kullanıcı profili, sipariş geçmişi, adres defteri gibi kişisel bilgileri yönetir.

Bu yapıda, her mikro frontend kendi Angular sürümünü, bağımlılıklarını ve hatta farklı bir UI kütüphanesini kullanabilir (her ne kadar Angular ekosisteminde kalmak genellikle tercih edilse de). Webpack'in shared özelliği sayesinde, temel Angular kütüphaneleri ve diğer yaygın bağımlılıklar yalnızca bir kez yüklenir, bu da performans kaybını minimuma indirir. Örneğin, Sepet ekibi yeni bir ödeme geçidi entegrasyonu yaparken, Ürün ekibi bağımsız olarak yeni bir ürün filtreleme özelliği geliştirebilir ve her iki değişiklik de ana uygulamayı etkilemeden kendi dağıtım süreçleriyle canlıya alınabilir.

Vaka Analizi 2: Kurumsal Dashboard ve Yönetim Paneli

Büyük bir şirketin farklı departmanlarının (Satış, Pazarlama, İnsan Kaynakları, IT) kullandığı tek bir kurumsal dashboard uygulaması düşünelim. Her departmanın kendi verilerine ve raporlama ihtiyaçlarına yönelik farklı widget'ları ve panelleri vardır. Monolitik bir dashboardda, her yeni widget veya rapor talebi, merkezi ekibin iş yükünü artırır ve departmanların kendi ihtiyaçlarına hızlıca yanıt vermesini zorlaştırır. Module Federation bu senaryoyu da optimize edebilir:

  • Host Dashboard: Ana navigasyon, genel düzen ve kullanıcı kimlik doğrulama/yetkilendirme mekanizmasını sağlar.
  • Satış Analizleri Mikro Frontend: Satış ekibi tarafından geliştirilir. Gerçek zamanlı satış grafikleri, performans göstergeleri ve müşteri segmentasyonu widget'ları içerir.
  • Pazarlama Kampanyaları Mikro Frontend: Pazarlama ekibi tarafından yönetilir. Kampanya performans raporları, A/B test sonuçları ve sosyal medya entegrasyonları gibi bileşenleri sunar.
  • İK Yönetimi Mikro Frontend: İnsan Kaynakları departmanı için çalışan bilgileri, izin takipleri ve performans değerlendirme modülleri sağlar.

Bu modelde, her departman kendi mini uygulamasının geliştirilmesinden ve sürdürülmesinden sorumlu olur. Onlar için en uygun teknolojileri veya kütüphaneleri seçebilirler (yine de uyumluluk için Angular'da kalmak mantıklıdır). Dashboard'un ana ekibi sadece entegrasyon ve genel çerçeveye odaklanırken, departmanlar kendi iş akışlarına özel ve özelleştirilmiş widget'ları hızlıca geliştirebilir ve dağıtabilirler. Bu, geliştirici verimliliğini artırmanın yanı sıra, departmanların kendi iş ihtiyaçlarına daha hızlı yanıt vermesini sağlayarak iş süreçlerini de hızlandırır. Bağımlılık çatışmalarını minimuma indirmek ve farklı mikro frontendlerin aynı Angular bağımlılık setini kullanmasını sağlamak için shared yapılandırmasını singleton: true ile kullanmak esastır. Bu sayede, uygulamanın farklı bölümleri aynı anda yüklendiğinde, aynı Angular instance'ını paylaşarak hem performans optimizasyonu sağlanır hem de olası hataların önüne geçilir. Bu vaka analizleri, Module Federation'ın sadece teorik bir konsept olmadığını, aksine büyük ve karmaşık sistemlerde gerçek değer yaratan pratik bir çözüm olduğunu açıkça ortaya koymaktadır.

Uzman İpucu: Karmaşık paylaşımlı modül yapılandırmalarında (özellikle farklı versiyonlardaki kütüphaneler), strictVersion: true ve requiredVersion: 'auto' gibi seçenekleri dikkatlice kullanın. Bu, beklenmedik versiyon çatışmalarını engellemeye yardımcı olur.

Gelişmiş Konular ve Optimizasyon İpuçları

Mikro Frontend mimarisini Module Federation ile Angular projelerinize uyguladıktan sonra, uygulamanın performansını, sürdürülebilirliğini ve kullanıcı deneyimini daha da artırmak için ileri düzey konulara ve optimizasyon ipuçlarına odaklanmak önemlidir.

Performans İyileştirmeleri

  1. Lazy Loading ve Dinamik Import: Module Federation'ın temel faydalarından biri dinamik yüklemedir. Mikro frontendlerinizi ve hatta içindeki bileşenleri sadece ihtiyaç duyulduğunda yükleyerek başlangıç ​​yükleme süresini önemli ölçüde azaltabilirsiniz. Angular Router ile bu zaten doğal olarak desteklenir.
  2. Shared Modül Optimizasyonu: shared yapılandırmasında Angular, RxJS gibi büyük kütüphanelerin tekil (singleton) kopyalarını paylaşmak esastır. Ayrıca, tüm projelerinizde aynı versiyonları kullanmaya özen gösterin. Eğer farklı versiyonlar kaçınılmazsa, Webpack'in bu durumu nasıl ele alacağını shared seçeneklerinde (örneğin, eager, strictVersion) detaylıca belirtin.
  3. Caching Stratejileri: Tarayıcı önbellekleme ve Service Worker'lar (Angular PWA) kullanarak statik varlıkları ve mikro frontend bundle'larını önbelleğe alın. Bu, tekrar eden ziyaretlerde uygulamanın çok daha hızlı yüklenmesini sağlar.
  4. Küçük ve Odaklı Mikro Frontendler: Her mikro frontend'i mümkün olduğunca küçük ve tek bir işlevsel alana odaklanmış tutun. Bu, hem bundle boyutlarını küçültür hem de bağımsız dağıtımı kolaylaştırır.

Hata Yönetimi ve Kullanıcı Deneyimi

Dinamik yükleme ve dağıtık bir yapı, hata durumlarını yönetmeyi biraz daha karmaşık hale getirebilir.

  • Yükleme Hatalarını Yakalama: Bir mikro frontend yüklenemediğinde (örneğin ağ hatası veya remote sunucusu kapalıysa), kullanıcıya anlamlı bir geri bildirim sunmak önemlidir. Router'da loadChildren kullanan durumlarda, catch blokları ile bu hataları yakalayabilir ve alternatif bir "yükleme başarısız oldu" bileşeni gösterebilirsiniz.
  • Loading Göstergeleri: Mikro frontendler asenkron olarak yüklendiği için, kullanıcıya bir şeylerin yüklendiğini gösteren görsel bir geri bildirim (spinner, iskelet ekran) sağlamak kullanıcı deneyimini artırır.
  • Sağlık Kontrolleri: Mikro frontendlerin sağlıklı çalışıp çalışmadığını izlemek için sağlık kontrolü (health check) endpointleri ekleyin. Bu, sorunları proaktif olarak tespit etmenize yardımcı olur.

CSS ve Styling Stratejileri

Farklı mikro frontendler arasında stil çatışmalarını önlemek kritik bir konudur.

  • Scoped CSS (Shadow DOM): Angular bileşenleri varsayılan olarak ViewEncapsulation.Emulated ile kapsüllenmiş stiller kullanır. Bu, çoğu durumda yeterli olsa da, bazı durumlarda Shadow DOM (ViewEncapsulation.ShadowDom) kullanarak stillerin tamamen izole edilmesini sağlayabilirsiniz.
  • CSS Ön İşlemcileri ve Adlandırma Kuralları: Sass/Less gibi ön işlemcilerle modüler stil dosyaları oluşturun. BEM (Block Element Modifier) gibi adlandırma kuralları kullanarak sınıflar arasında çatışma riskini azaltın.
  • CSS Değişkenleri: Ortak tema ve stil kılavuzlarını global CSS değişkenleri (CSS Custom Properties) aracılığıyla paylaşın. Bu, her mikro frontend'in kendi stillerini korurken, ana tema ile uyumlu kalmasını sağlar.
  • Utility-First CSS (Tailwind CSS): Tailwind CSS gibi utility-first framework'ler, bileşen düzeyinde stillendirme konusunda büyük esneklik sağlar ve global stil çatışmalarını en aza indirir.

        /* Mobil uyumlu tasarım için örnek bir medya sorgusu */
        @media (max-width: 768px) {
          .micro-frontend-container {
            flex-direction: column;
            padding: 10px;
          }
          .remote-widget {
            margin-bottom: 15px;
          }
        }
    

Bu medya sorgusu örneği, farklı mikro frontendlerin bulunduğu bir düzenin mobil cihazlarda nasıl daha iyi görüneceğini gösterir. Her bir mikro frontend kendi içinde responsive olabilir veya ana uygulama genel bir responsive iskelet sunabilir.

CI/CD Süreçleri ve Dağıtım Stratejileri

Her mikro frontend'in bağımsız olarak dağıtılabilir olması, CI/CD süreçlerini modernize etmeyi gerektirir.

  • Bağımsız Pipeline'lar: Her mikro frontend için kendi derleme, test ve dağıtım pipeline'ını oluşturun. Bu, ekiplerin birbirini beklemeden kendi kodlarını canlıya almasını sağlar.
  • Versiyonlama Stratejileri: Mikro frontendlerinizi semantik versiyonlama (SemVer) ile versiyonlayın. Host uygulamanın belirli bir remote uygulamanın hangi versiyonunu tüketeceğini açıkça belirtin. Gerekirse, webpack.config.js içinde remote URL'sini versiyona özel hale getirebilirsiniz (örn. http://localhost:4201/v1/remoteEntry.js).
  • Ortak Build Ortamı: Ortak bağımlılıklar ve build araçları için bir "base image" veya "starter kit" oluşturmak, tutarlılığı ve kolaylığı artırır.

Bu gelişmiş konuları ve optimizasyon ipuçlarını uygulayarak, Angular ile Module Federation tabanlı mikro frontend mimarisinin sunduğu tüm potansiyeli ortaya çıkarabilir, daha performanslı, esnek ve sürdürülebilir uygulamalar geliştirebilirsiniz.

Güvenlik ve Sürdürülebilirlik

Her dağıtık mimaride olduğu gibi, Mikro Frontendler de beraberinde bazı güvenlik ve sürdürülebilirlik zorluklarını getirir. Ancak doğru stratejilerle bu zorlukların üstesinden gelmek mümkündür.

Güvenlik Endişeleri

1. Çapraz Kaynak Güvenliği (CORS): Module Federation, farklı kökenlerden (domain, port) modül yüklemeyi içerdiğinden, CORS politikalarının doğru yapılandırılması hayati öneme sahiptir. Remote uygulamaların sunucuları, host uygulamanın kökeninden gelen isteklere izin verecek şekilde ayarlanmalıdır. Yanlış yapılandırılmış CORS, güvenlik açıklarına yol açabilir veya uygulamalar arası iletişimi engelleyebilir. Her mikro frontend'in dağıtıldığı sunucuda veya CDN'de bu ayarların doğru yapıldığından emin olunmalıdır.


        // Örnek bir Node.js (Express) sunucusunda CORS yapılandırması
        const express = require('express');
        const cors = require('cors');
        const app = express();

        app.use(cors({
          origin: 'http://localhost:4200', // Host uygulamasının URL'si
          methods: ['GET', 'POST'],
          credentials: true // Çerezler ve kimlik doğrulama bilgileri için
        }));

        // Diğer route'lar
        app.listen(4201, () => {
          console.log('Remote app server running on port 4201');
        });
    

2. Bağımlılık Güvenliği: Her mikro frontend'in kendi bağımlılık setine sahip olması, güvenlik açığı taramalarının her proje için ayrı ayrı yapılmasını gerektirir. npm audit veya Snyk gibi araçlarla düzenli olarak bağımlılıkların güvenlik açıklarını kontrol etmek, potansiyel riskleri minimize eder.

3. İstemci Tarafı Güvenliği: XSS (Cross-Site Scripting) ve CSRF (Cross-Site Request Forgery) gibi yaygın web saldırılarına karşı her mikro frontend'in ayrı ayrı güvence altına alındığından emin olun. Angular'ın yerleşik güvenlik mekanizmaları (sanitizasyon) bu konuda büyük destek sağlar, ancak geliştiricilerin de dikkatli olması gerekir.

Sürdürülebilirlik Stratejileri

1. Bağımlılık Çatışmaları ve Versiyonlama: Module Federation'ın shared özelliği bağımlılık çatışmalarını büyük ölçüde azaltır. Ancak, farklı mikro frontendler aynı kütüphanenin uyumsuz versiyonlarını kullanmaya kalktığında sorunlar ortaya çıkabilir. Bu durumu yönetmek için:

  • Semantik Versiyonlama (SemVer): Tüm paylaşılan kütüphaneler ve mikro frontendler için tutarlı bir SemVer stratejisi benimseyin.
  • singleton ve strictVersion: Webpack yapılandırmasında shared modülleri için singleton: true ve strictVersion: true kullanmak, tek bir kopyanın yüklenmesini ve versiyon uyumsuzluklarının katı bir şekilde denetlenmesini sağlar.
  • Versiyon Politikası: Ekipler arasında ortak bağımlılıkların hangi versiyonlarının kullanılacağına dair bir politika belirleyin ve bunu dökümante edin.

2. Ekip Organizasyonu ve İletişim: Mikro Frontendler, ürün odaklı, çapraz fonksiyonel ekipleri teşvik eder. Her ekip, kendi mikro frontend'inin tüm yaşam döngüsünden (geliştirme, test, dağıtım, bakım) sorumlu olmalıdır. Bu, takım otonomisini artırır, ancak ekipler arasında açık ve düzenli iletişim olmadan başarılı olamaz. Ortak bileşenler, API sözleşmeleri ve genel tasarım ilkeleri hakkında düzenli senkronizasyon toplantıları yapılmalıdır.

3. Test Stratejileri: Dağıtık bir sistemde testler daha kapsamlı olmalıdır.

  • Birim ve Entegrasyon Testleri: Her mikro frontend kendi içinde kapsamlı birim ve entegrasyon testlerine sahip olmalıdır.
  • Uçtan Uca (E2E) Testleri: Host uygulama ile entegre olan tüm mikro frontendlerin bir arada çalıştığını doğrulayan E2E testleri vazgeçilmezdir. Cypress veya Playwright gibi araçlar bu tür testler için idealdir.
  • Sözleşme Testleri (Contract Testing): Mikro frontendler arasında veya mikro frontend ile backend arasında API sözleşmelerini doğrulayan testler (Pact gibi araçlarla) entegrasyon hatalarını önler.

4. İzleme ve Gözlemlenebilirlik: Dağıtık bir mimaride sorun gidermek karmaşık olabilir. Merkezi bir loglama sistemi (ELK Stack, Grafana Loki), performans izleme araçları (Datadog, New Relic) ve hata izleme sistemleri (Sentry) kurmak, sorunları hızlıca tespit etmek ve çözmek için kritik öneme sahiptir. Her mikro frontend'in kendi telemetri verilerini bu merkezi sistemlere göndermesi sağlanmalıdır.

Bu güvenlik ve sürdürülebilirlik stratejilerini uygulayarak, Module Federation ile kurduğunuz Angular mikro frontend mimarisinin uzun vadede hem güvenli hem de yönetilebilir kalmasını sağlayabilirsiniz. Unutmayın, teknik mükemmeliyet kadar, ekipler arası iletişim ve ortak standartlar da bu mimarinin başarısı için kilit rol oynar.

Sonuç: Mikro Frontendler ile Geleceğe Yönelik Mimari

Angular ekosisteminde Mikro Frontend mimarisi, özellikle Webpack 5'in Module Federation özelliği ile birleştiğinde, büyük ölçekli ve karmaşık web uygulamalarının geliştirme ve sürdürülebilirlik sorunlarına güçlü bir çözüm sunmaktadır. Monolitik yapıların getirdiği kısıtlamaları aşarak, takımların bağımsız bir şekilde çalışmasına, teknolojileri daha esnek bir şekilde seçmesine ve uygulamalarını kademeli olarak ölçeklendirmesine olanak tanır. Bu rehberde, Module Federation'ın temel prensiplerinden Angular projelerinde adım adım nasıl uygulanacağına, gerçek dünya senaryolarından performans optimizasyonuna ve güvenlik stratejilerine kadar birçok konuyu ele aldık.

Module Federation, dinamik kod paylaşımını ve asenkron modül yüklemesini basitleştirerek, Angular'ın güçlü bileşen tabanlı yapısıyla mükemmel bir uyum sergiler. Bu sayede, "ürün kartı" gibi küçük bir bileşenden, "ödeme" gibi karmaşık bir işlevsel modüle kadar her şeyi bağımsız olarak geliştirip host uygulamanıza sorunsuz bir şekilde entegre edebilirsiniz. Bu yaklaşım, geliştirme ekiplerinin verimliliğini artırmanın yanı sıra, uygulamanın esnekliğini ve geleceğe yönelik sürdürülebilirliğini de garanti eder. Mikro Frontendler ve Module Federation ile artık Angular projeleriniz, değişen iş ihtiyaçlarına çok daha hızlı adapte olabilen, çevik ve ölçeklenebilir bir yapıya kavuşacaktır.

Bu teknolojilerin potansiyelini tam olarak keşfetmek için kendi projelerinizde denemeler yapmaktan çekinmeyin. Küçük adımlarla başlayarak, mevcut monolitik uygulamanızın belirli bir bölümünü mikro frontend'e dönüştürerek veya yeni bir özellik geliştirirken bu mimariyi deneyerek adaptasyon sürecinizi kolaylaştırabilirsiniz. Geleceğin web uygulamaları, şüphesiz daha modüler, dağıtık ve esnek yapılar üzerine inşa edilecek; Mikro Frontendler ve Module Federation da bu dönüşümün en önemli araçlarından biridir.

Sıkça Sorulan Sorular

1. Mikro Frontendler her proje için uygun mudur?

Hayır, her proje için uygun değildir. Küçük veya orta ölçekli projelerde, monolitik bir mimari genellikle daha hızlı ve daha az karmaşık bir geliştirme süreci sunar. Mikro Frontendler, özellikle büyük ekiplerin çalıştığı, farklı iş alanlarına sahip, bağımsız dağıtım ve teknoloji esnekliği gerektiren çok büyük ve karmaşık uygulamalar için en büyük faydayı sağlar. Yanlış uygulandığında, gereksiz karmaşıklık ve yönetim yükü getirebilir.

2. Module Federation'ın alternatifi var mı?

Evet, Module Federation, mikro frontendler için en modern ve verimli çözümlerden biri olsa da alternatifleri mevcuttur. Bunlar arasında iframe'ler (izolasyon sağlar ancak iletişim ve SEO sorunları yaratır), Web Components (framework bağımsız bileşenler oluşturma), tek sayfa uygulamalarının manuel olarak birleştirilmesi (build zamanı entegrasyonu) veya Nginx gibi bir reverse proxy aracılığıyla farklı uygulamaların birleştirilmesi (sunucu tarafı kompozisyon) sayılabilir. Ancak Module Federation, çalışma zamanında dinamik kod paylaşımı ve bağımlılık yönetimindeki üstünlüğüyle öne çıkar.

3. Mikro Frontendler uygulamanın performansını nasıl etkiler?

Doğru yapılandırıldığında, Mikro Frontendler performansı artırabilir. Dinamik yükleme (lazy loading) sayesinde kullanıcılar yalnızca ihtiyaç duydukları kodu indirir. shared modüllerin akıllıca kullanılmasıyla ortak bağımlılıklar yalnızca bir kez yüklenir. Ancak yanlış yapılandırılırsa (örneğin, bağımlılıkların birden fazla kopyasının yüklenmesi, gereksiz mikro frontend yüklemeleri), performansı olumsuz etkileyebilir. Dikkatli planlama ve optimizasyon kritik öneme sahiptir.

4. Bağımlılık yönetimi nasıl yapılır?

Module Federation'ın shared özelliği bağımlılık yönetiminin anahtarıdır. Bu özellik sayesinde, Angular ve diğer büyük kütüphanelerin tekil (singleton) kopyalarını tüm mikro frontendler arasında paylaşabilirsiniz. strictVersion: true ve requiredVersion: 'auto' gibi seçenekler, versiyon uyumsuzluklarından kaynaklanan hataları önlemeye yardımcı olur. Ekipler arasında ortak bağımlılıkların versiyonları konusunda tutarlı bir politika benimsemek de önemlidir.

5. Angular dışındaki framework'lerle çalışır mı?

Evet, Module Federation, Webpack'in bir özelliği olduğu için Angular ile sınırlı değildir. Farklı JavaScript framework'lerini (React, Vue, Svelte vb.) kullanan uygulamalar arasında kod ve modül paylaşımını destekler. Hatta bir Angular mikro frontend'ini bir React host uygulamasına veya tam tersine entegre etmek bile mümkündür. Bu, teknoloji esnekliğinin en büyük göstergelerinden biridir.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Gönder

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.
Exit mobile version