Micro-frontend Mimarisi : Vue 3 ve Module Federation
Merhabalar :) Öncelikle micro-frontend mimarisi nedir, bizim ne işimize yarar, nerelerde kullanmalıyız, bu mimari yaklaşımı ile neleri daha iyi bir hale getirebiliriz bunları inceleyerek başlayalım.
Micro-frontend, temel olarak büyük ve karmaşık projelerin daha küçük parçalara ayrılarak kolay ve esnek bir şekilde projenin yönetilebilmesini hedefler. Her parçanın sorumluluğu farklı bir takımda gibi düşünebiliriz. Her takım sadece kendi sorumlu olduğu alanda geliştirme yapabilir. Fakat günün sonunda bu parçalar bir container üzerinde toplanarak kullanıcı ile buluşur.
Bu mimari yaklaşımının amacı büyük ekiplerin daha kolay bir şekilde projeleri yönetebilmesi ve projelerin birbirinden bağımsız olmasıdır.
Avantajları 🎉
- Bu kullanım sonucunda daha küçük bir codebase oluşacağı için kodun daha kolay anlaşılabilmesi için imkan tanır ve projenin daha basit şekilde sürdürülebilmesine olanak tanır.
- Diğer projenin yaşadığı bir problem sadece o projeyi etkiler. Diğer projeler çalışmaya devam eder.
- Herhangi bir proje için yapılan değişiklik direkt deploy edilebilir. Yapılan güncelleme ana container’a hemen yansır.
- Farklı teknolojiler üzerine çalışan farklı ekipleri bir araya getirebilirsiniz.
- Kolay test edilebilir.
Pekii Micro-frontend’i Nasıl Uygulayabiliriz? 🤔
Bir çok araştırma sonucunda Webpack Module Federation yönteminin bizim projelerimize daha çok uyduğunu düşündük.
Module Fedaration, Webpack 5'te tanıtıldı. Bunun temel amacı, uygulamalar arasında kod paylaşımı yapmaktır. Geliştiricilere tek bir uygulama oluşturan birden çok ayrı yapı oluşturma yolu sunar. Herhangi bir Javascript projesi ile çalışma zamanında dinamik olarak kod ve bağımlılıkları yükleyebilir veya paylaşabilir.
Hadi uygulamaya geçelim! ✌️😇
Öncelikle CMD ile projemizi oluşturmak istediğimiz dizine gelip
npx create-mf-app
komutunu çalıştırıyoruz.
Ben ilk olarak container olarak kullanacağım projeyi oluşturuyorum. Daha sonra gelen seçeneklerden “Application” seçerek devam ediyorum. Test projelerime ise vue3 üzerinden devam edeceğim.
Şimdi ise uzaktan erişeceğim remote1 ve remote2 projelerini aynı şekilde sadece farklı portlar vererek oluşturuyorum. Ben sırasıyla 8081 ve 8082 portlarını tercih ettim.
Projelerimizi çalıştırdığımız da üçünün de ayrı ayrı başarılı bir şekilde çalıştığını görebiliriz. 🙂
Peki Container üzerinden Remote1 ve Remote2 projelerine nasıl erişebiliriz ? 👀
Hep birlikte bu soruyu cevaplayalım. 🙂
Öncelikle Remote1 projesinde Remote1.vue adında bir sayfa oluşturuyorum.
<template>
<div class="container">
<div>Remote1</div>
</div>
</template>
Not: Webpack, bir projede çalıştırıldığında, projenin ihtiyaç duyabileceği her modül tipini alan bir dependency graph (bağımlılık grafiği) oluşturur ve bu grafiğin işlenmesi sonucu çıktı olarak bir uygulama paketi üretir.
Remote1 projemizin webpack.config.js dosyasına gelip “plugins” kısmını inceleyelim. “exposes” kısmı proje içerisinde sunulan modül veya dosyalara giden yoldur; bir nesne veya bir dizi olabilir.
Ben Remote1 sayfasına Container projesi erişebilsin istiyorum. Bu yüzden bu sayfayı expose kısmına ekliyorum.
plugins: [
new VueLoaderPlugin(),
new ModuleFederationPlugin({
name: "remote1",
filename: "remoteEntry.js",
remotes: {},
exposes: {
"./Remote1": "./src/Remote1.vue",
},
shared: require("./package.json").dependencies,
}),
new HtmlWebPackPlugin({
template: "./src/index.html",
}),
],
Aynı işlemleri Remote2 projem içinde uyguluyorum.
Şimdi sıra Container da Remote1 ve Remote2 projelerine erişmekte.
Öncelikle Container projemizin webpack.config.js dosyasına gelip “plugins” kısmını inceliyorum. “remote” kısmı ise diğer projelerden erişilebilen statik uzak modüllerin bir listesidir. Uzak bir dizi veya bir nesne olabilir.
plugins: [
new VueLoaderPlugin(),
new ModuleFederationPlugin({
name: "container",
filename: "remoteEntry.js",
remotes: {
remote1: "remote1@http://localhost:8081/remoteEntry.js",
remote2: "remote2@http://localhost:8082/remoteEntry.js",
},
exposes: {},
shared: require("./package.json").dependencies,
}),
new HtmlWebPackPlugin({
template: "./src/index.html",
}),
],
Burada dikkat etmeniz kısım projelerin yollarını verirken package.json dosyasında projenizi nasıl isimlendirdiğiniz ile ilgili.
App.vue sayfasına gelip uzaktan eriştiğimiz Remote1 ve Remote2 sayfalarını projemize tanıtmamız gerekiyor.
App.vue :
<template>
<div class="container">
<div>Name: container</div>
<Remote1></Remote1>
<Remote2></Remote2>
</div>
</template>
<script>
import { defineAsyncComponent } from "vue";
const Remote1 = defineAsyncComponent(() => import("remote1/Remote1"));
const Remote2 = defineAsyncComponent(() => import("remote2/Remote2"));
export default {
name: 'App',
components: {
Remote1,
Remote2
},
}
</script>
Son olarak projelerimizi çalıştırıyoruz. 🙂
Container üzerinden 2 farklı projede ki 2 farklı sayfayı görüntülemiş olduk.🥳 Eğer test ederseniz yaptığınız bir güncellemenin herhangi bir sorun olmadan Container sayfasına da yansıdığını fark edeceksiniz. 🙂
Sizler için projeyi github adresimde paylaştım. Dilerseniz indirip deneyebilirsiniz.
Bir sonra ki yazımda Micro-frontend mimarisi üzerinden ortak Mixins nasıl kullanılır sizlere açıklamaya çalışacağım. 🙂
Bir sonra ki yazımda görüşmek üzere. Bol kodlamalar!👋
Kaynaklar: