Polski

Odkryj moc mikro-frontendów dzięki JavaScript Module Federation w Webpack 5. Dowiedz się, jak budować skalowalne, łatwe w utrzymaniu i niezależne aplikacje internetowe.

JavaScript Module Federation z Webpack 5: Kompleksowy przewodnik po mikro-frontendach

W stale ewoluującym świecie tworzenia stron internetowych, budowanie dużych i złożonych aplikacji może być zniechęcającym zadaniem. Tradycyjne architektury monolityczne często prowadzą do wydłużonego czasu tworzenia, wąskich gardeł we wdrożeniach i wyzwań związanych z utrzymaniem jakości kodu. Mikro-frontendy pojawiły się jako potężny wzorzec architektoniczny, aby sprostać tym wyzwaniom, pozwalając zespołom budować i wdrażać niezależne części większej aplikacji internetowej. Jedną z najbardziej obiecujących technologii do implementacji mikro-frontendów jest JavaScript Module Federation, wprowadzona w Webpack 5.

Czym są mikro-frontendy?

Mikro-frontendy to styl architektoniczny, w którym aplikacja frontendowa jest rozłożona na mniejsze, niezależne jednostki, które mogą być rozwijane, testowane i wdrażane autonomicznie przez różne zespoły. Każdy mikro-frontend jest odpowiedzialny za określoną domenę biznesową lub funkcję, a wszystkie są komponowane razem w czasie rzeczywistym, tworząc kompletny interfejs użytkownika.

Pomyśl o tym jak o firmie: zamiast jednego gigantycznego zespołu deweloperskiego, masz wiele mniejszych zespołów skupiających się na konkretnych obszarach. Każdy zespół może pracować niezależnie, co pozwala na szybsze cykle rozwojowe i łatwiejsze utrzymanie. Weźmy za przykład dużą platformę e-commerce, taką jak Amazon; różne zespoły mogą zarządzać katalogiem produktów, koszykiem, procesem płatności i zarządzaniem kontem użytkownika. Wszystko to mogą być niezależne mikro-frontendy.

Zalety mikro-frontendów:

Wyzwania mikro-frontendów:

Czym jest JavaScript Module Federation?

JavaScript Module Federation to funkcja Webpack 5, która pozwala na współdzielenie kodu między oddzielnie kompilowanymi aplikacjami JavaScript w czasie rzeczywistym. Umożliwia ona eksponowanie części aplikacji jako „modułów”, które mogą być konsumowane przez inne aplikacje, bez konieczności publikowania ich w centralnym repozytorium, takim jak npm.

Pomyśl o Module Federation jako o sposobie na stworzenie sfederowanego ekosystemu aplikacji, w którym każda aplikacja może wnosić własną funkcjonalność i konsumować funkcjonalność z innych aplikacji. Eliminuje to potrzebę zależności w czasie budowania i pozwala na prawdziwie niezależne wdrożenia.

Na przykład, zespół odpowiedzialny za system projektowy może eksponować komponenty interfejsu użytkownika jako moduły, a różne zespoły aplikacyjne mogą konsumować te komponenty bezpośrednio z aplikacji systemu projektowego, bez konieczności instalowania ich jako pakiety npm. Gdy zespół systemu projektowego zaktualizuje komponenty, zmiany są automatycznie odzwierciedlane we wszystkich konsumujących aplikacjach.

Kluczowe pojęcia w Module Federation:

Konfiguracja Module Federation z Webpack 5: Praktyczny przewodnik

Przejdźmy przez praktyczny przykład konfiguracji Module Federation z Webpack 5. Stworzymy dwie proste aplikacje: aplikację Host (Gospodarz) i aplikację Remote (Zdalną). Aplikacja Remote będzie eksponować komponent, a aplikacja Host będzie go konsumować.

1. Konfiguracja projektu

Utwórz dwa oddzielne katalogi dla swoich aplikacji: `host` i `remote`.

```bash mkdir host remote cd host npm init -y npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev npm install react react-dom cd ../remote npm init -y npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev npm install react react-dom ```

2. Konfiguracja aplikacji zdalnej (Remote)

W katalogu `remote` utwórz następujące pliki:

src/index.js:

```javascript import React from 'react'; import ReactDOM from 'react-dom/client'; import RemoteComponent from './RemoteComponent'; const App = () => (

Remote Application

); const root = ReactDOM.createRoot(document.getElementById('root')); root.render(); ```

src/RemoteComponent.jsx:

```javascript import React from 'react'; const RemoteComponent = () => (

This is a Remote Component!

Rendered from the Remote Application.

); export default RemoteComponent; ```

webpack.config.js:

```javascript const HtmlWebpackPlugin = require('html-webpack-plugin'); const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); const path = require('path'); module.exports = { entry: './src/index', mode: 'development', devServer: { port: 3001, static: { directory: path.join(__dirname, 'dist'), }, }, output: { publicPath: 'auto', }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-react', '@babel/preset-env'], }, }, }, ], }, plugins: [ new ModuleFederationPlugin({ name: 'remote', filename: 'remoteEntry.js', exposes: { './RemoteComponent': './src/RemoteComponent', }, shared: { react: { singleton: true, eager: true }, 'react-dom': { singleton: true, eager: true }, }, }), new HtmlWebpackPlugin({ template: './public/index.html', }), ], resolve: { extensions: ['.js', '.jsx'], }, }; ```

Utwórz plik `public/index.html` z podstawową strukturą HTML. Ważny jest element `

`

3. Konfiguracja aplikacji hosta (Host)

W katalogu `host` utwórz następujące pliki:

  • `src/index.js`: Punkt wejściowy aplikacji.
  • `webpack.config.js`: Plik konfiguracyjny Webpacka.

src/index.js:

```javascript import React, { Suspense } from 'react'; import ReactDOM from 'react-dom/client'; const RemoteComponent = React.lazy(() => import('remote/RemoteComponent')); const App = () => (

Host Application

Loading Remote Component...
}>
); const root = ReactDOM.createRoot(document.getElementById('root')); root.render(); ```

webpack.config.js:

```javascript const HtmlWebpackPlugin = require('html-webpack-plugin'); const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); const path = require('path'); module.exports = { entry: './src/index', mode: 'development', devServer: { port: 3000, static: { directory: path.join(__dirname, 'dist'), }, }, output: { publicPath: 'auto', }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-react', '@babel/preset-env'], }, }, }, ], }, plugins: [ new ModuleFederationPlugin({ name: 'host', remotes: { remote: 'remote@http://localhost:3001/remoteEntry.js', }, shared: { react: { singleton: true, eager: true }, 'react-dom': { singleton: true, eager: true }, }, }), new HtmlWebpackPlugin({ template: './public/index.html', }), ], resolve: { extensions: ['.js', '.jsx'], }, }; ```

Utwórz plik `public/index.html` z podstawową strukturą HTML (podobną do aplikacji zdalnej). Ważny jest element `

`

4. Instalacja Babel

W obu katalogach, `host` i `remote`, zainstaluj zależności Babel:

```bash npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader ```

5. Uruchomienie aplikacji

W obu katalogach, `host` i `remote`, dodaj następujący skrypt do `package.json`:

```json "scripts": { "start": "webpack serve" } ```

Teraz uruchom obie aplikacje:

```bash cd remote npm start cd ../host npm start ```

Otwórz przeglądarkę i przejdź do `http://localhost:3000`. Powinieneś zobaczyć aplikację Hosta z wyrenderowanym wewnątrz niej komponentem zdalnym.

Wyjaśnienie kluczowych opcji konfiguracyjnych:

Zaawansowane techniki Module Federation

Module Federation oferuje wiele zaawansowanych funkcji, które mogą pomóc w budowaniu jeszcze bardziej zaawansowanych architektur mikro-frontendowych.

Dynamiczne aplikacje zdalne (Remotes)

Zamiast sztywno kodować adresy URL aplikacji zdalnych w konfiguracji Webpacka, można je ładować dynamicznie w czasie rzeczywistym. Pozwala to na łatwą aktualizację lokalizacji aplikacji zdalnych bez konieczności ponownego budowania aplikacji hosta.

Na przykład, można przechowywać adresy URL aplikacji zdalnych w pliku konfiguracyjnym lub w bazie danych i ładować je dynamicznie za pomocą JavaScriptu.

```javascript // W pliku webpack.config.js remotes: { remote: `promise new Promise(resolve => { const urlParams = new URLSearchParams(window.location.search); const remoteUrl = urlParams.get('remote'); // Załóżmy, że remoteUrl to coś w stylu 'http://localhost:3001/remoteEntry.js' const script = document.createElement('script'); script.src = remoteUrl; script.onload = () => { // kluczem w module federation jest to, że zdalna aplikacja jest // dostępna pod nazwą zdefiniowaną w jej konfiguracji (remote) resolve(window.remote); }; document.head.appendChild(script); })`, }, ```

Teraz możesz załadować aplikację hosta z parametrem zapytania `?remote=http://localhost:3001/remoteEntry.js`

Wersjonowanie współdzielonych modułów

Module Federation może automatycznie zarządzać wersjonowaniem i deduplikacją współdzielonych modułów, aby zapewnić, że ładowana jest tylko jedna kompatybilna wersja każdego modułu. Jest to szczególnie ważne w przypadku dużych i złożonych aplikacji z wieloma zależnościami.

Możesz określić zakres wersji każdego współdzielonego modułu w konfiguracji Webpacka.

```javascript // W pliku webpack.config.js shared: { react: { singleton: true, eager: true, requiredVersion: '^18.0.0' }, 'react-dom': { singleton: true, eager: true, requiredVersion: '^18.0.0' }, }, ```

Niestandardowe loadery modułów

Module Federation pozwala na definiowanie niestandardowych loaderów modułów, które mogą być używane do ładowania modułów z różnych źródeł lub w różnych formatach. Może to być przydatne do ładowania modułów z CDN lub z niestandardowego rejestru modułów.

Dzielenie stanu między mikro-frontendami

Jednym z wyzwań w architekturach mikro-frontendowych jest dzielenie stanu między różnymi mikro-frontendami. Istnieje kilka podejść, które można zastosować, aby sprostać temu wyzwaniu:

Dobre praktyki wdrażania mikro-frontendów z Module Federation

Oto kilka dobrych praktyk, o których warto pamiętać podczas wdrażania mikro-frontendów z Module Federation:

Przykłady użycia Module Federation w rzeczywistych projektach

Chociaż konkretne studia przypadków są często poufne, oto kilka ogólnych scenariuszy, w których Module Federation może być niezwykle przydatne:

Podsumowanie

JavaScript Module Federation w Webpack 5 zapewnia potężny i elastyczny sposób budowania architektur mikro-frontendowych. Pozwala na współdzielenie kodu między oddzielnie kompilowanymi aplikacjami JavaScript w czasie rzeczywistym, umożliwiając niezależne wdrożenia, różnorodność technologiczną i zwiększoną autonomię zespołów. Postępując zgodnie z najlepszymi praktykami opisanymi w tym przewodniku, możesz wykorzystać Module Federation do budowania skalowalnych, łatwych w utrzymaniu i innowacyjnych aplikacji internetowych.

Przyszłość rozwoju frontendu niewątpliwie zmierza w kierunku architektur modułowych i rozproszonych. Module Federation dostarcza kluczowego narzędzia do budowania tych nowoczesnych systemów, umożliwiając zespołom tworzenie złożonych aplikacji z większą szybkością, elastycznością i odpornością. W miarę dojrzewania technologii możemy spodziewać się pojawienia jeszcze bardziej innowacyjnych zastosowań i najlepszych praktyk.