Ελληνικά

Απελευθερώστε τη δύναμη των micro-frontends με το JavaScript Module Federation στο Webpack 5. Μάθετε πώς να δημιουργείτε επεκτάσιμες, συντηρήσιμες και ανεξάρτητες εφαρμογές web.

JavaScript Module Federation με Webpack 5: Ένας Ολοκληρωμένος Οδηγός για τα Micro-frontends

Στο διαρκώς εξελισσόμενο τοπίο της ανάπτυξης web, η δημιουργία μεγάλων και σύνθετων εφαρμογών μπορεί να είναι ένα δύσκολο εγχείρημα. Οι παραδοσιακές μονολιθικές αρχιτεκτονικές συχνά οδηγούν σε αυξημένο χρόνο ανάπτυξης, σημεία συμφόρησης στην ανάπτυξη (deployment bottlenecks) και προκλήσεις στη διατήρηση της ποιότητας του κώδικα. Τα Micro-frontends έχουν αναδειχθεί ως ένα ισχυρό αρχιτεκτονικό πρότυπο για την αντιμετώπιση αυτών των προκλήσεων, επιτρέποντας στις ομάδες να δημιουργούν και να αναπτύσσουν ανεξάρτητα τμήματα μιας μεγαλύτερης εφαρμογής web. Μία από τις πιο υποσχόμενες τεχνολογίες για την υλοποίηση micro-frontends είναι το JavaScript Module Federation, που εισήχθη στο Webpack 5.

Τι είναι τα Micro-frontends;

Τα Micro-frontends είναι ένα αρχιτεκτονικό στυλ όπου μια εφαρμογή frontend αποσυντίθεται σε μικρότερες, ανεξάρτητες μονάδες, οι οποίες μπορούν να αναπτυχθούν, να δοκιμαστούν και να αναπτυχθούν αυτόνομα από διαφορετικές ομάδες. Κάθε micro-frontend είναι υπεύθυνο για έναν συγκεκριμένο επιχειρηματικό τομέα ή χαρακτηριστικό, και συντίθενται μαζί κατά τον χρόνο εκτέλεσης (runtime) για να σχηματίσουν το πλήρες περιβάλλον χρήστη.

Σκεφτείτε το σαν μια εταιρεία: αντί να έχετε μια τεράστια ομάδα ανάπτυξης, έχετε πολλές μικρότερες ομάδες που εστιάζουν σε συγκεκριμένους τομείς. Κάθε ομάδα μπορεί να εργάζεται ανεξάρτητα, επιτρέποντας ταχύτερους κύκλους ανάπτυξης και ευκολότερη συντήρηση. Σκεφτείτε μια μεγάλη πλατφόρμα ηλεκτρονικού εμπορίου όπως το Amazon: διαφορετικές ομάδες μπορεί να διαχειρίζονται τον κατάλογο προϊόντων, το καλάθι αγορών, τη διαδικασία ολοκλήρωσης αγοράς και τη διαχείριση λογαριασμού χρήστη. Όλα αυτά θα μπορούσαν να είναι ανεξάρτητα micro-frontends.

Οφέλη των Micro-frontends:

Προκλήσεις των Micro-frontends:

Τι είναι το JavaScript Module Federation;

Το JavaScript Module Federation είναι ένα χαρακτηριστικό του Webpack 5 που σας επιτρέπει να μοιράζεστε κώδικα μεταξύ ξεχωριστά μεταγλωττισμένων εφαρμογών JavaScript κατά τον χρόνο εκτέλεσης. Σας δίνει τη δυνατότητα να εκθέτετε τμήματα της εφαρμογής σας ως "modules" που μπορούν να καταναλωθούν από άλλες εφαρμογές, χωρίς να χρειάζεται να τα δημοσιεύσετε σε ένα κεντρικό αποθετήριο όπως το npm.

Σκεφτείτε το Module Federation ως έναν τρόπο δημιουργίας ενός ομοσπονδιακού οικοσυστήματος εφαρμογών, όπου κάθε εφαρμογή μπορεί να συνεισφέρει τη δική της λειτουργικότητα και να καταναλώνει λειτουργικότητα από άλλες εφαρμογές. Αυτό εξαλείφει την ανάγκη για εξαρτήσεις κατά τον χρόνο δημιουργίας (build-time) και επιτρέπει πραγματικά ανεξάρτητες αναπτύξεις.

Για παράδειγμα, μια ομάδα συστήματος σχεδιασμού (design system) μπορεί να εκθέσει components του UI ως modules, και διαφορετικές ομάδες εφαρμογών μπορούν να καταναλώσουν αυτά τα components απευθείας από την εφαρμογή του design system, χωρίς να χρειάζεται να τα εγκαταστήσουν ως πακέτα npm. Όταν η ομάδα του design system ενημερώσει τα components, οι αλλαγές αντικατοπτρίζονται αυτόματα σε όλες τις εφαρμογές που τα καταναλώνουν.

Βασικές Έννοιες στο Module Federation:

Ρύθμιση του Module Federation με το Webpack 5: Ένας Πρακτικός Οδηγός

Ας δούμε ένα πρακτικό παράδειγμα ρύθμισης του Module Federation με το Webpack 5. Θα δημιουργήσουμε δύο απλές εφαρμογές: μια εφαρμογή Host και μια εφαρμογή Remote. Η εφαρμογή Remote θα εκθέσει ένα component, και η εφαρμογή Host θα το καταναλώσει.

1. Ρύθμιση του Project

Δημιουργήστε δύο ξεχωριστούς καταλόγους για τις εφαρμογές σας: `host` και `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. Διαμόρφωση της Εφαρμογής Remote

Στον κατάλογο `remote`, δημιουργήστε τα ακόλουθα αρχεία:

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'], }, }; ```

Δημιουργήστε το `public/index.html` με βασική δομή HTML. Σημαντικό είναι το `

`

3. Διαμόρφωση της Εφαρμογής Host

Στον κατάλογο `host`, δημιουργήστε τα ακόλουθα αρχεία:

  • `src/index.js`: Σημείο εισόδου για την εφαρμογή.
  • `webpack.config.js`: Το αρχείο διαμόρφωσης του Webpack.

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'], }, }; ```

Δημιουργήστε το `public/index.html` με βασική δομή HTML (παρόμοια με την εφαρμογή remote). Σημαντικό είναι το `

`

4. Εγκατάσταση του Babel

Και στους δύο καταλόγους, `host` και `remote`, εγκαταστήστε τις εξαρτήσεις του Babel:

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

5. Εκτέλεση των Εφαρμογών

Και στους δύο καταλόγους, `host` και `remote`, προσθέστε το ακόλουθο script στο `package.json`:

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

Τώρα, ξεκινήστε και τις δύο εφαρμογές:

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

Ανοίξτε το πρόγραμμα περιήγησής σας και μεταβείτε στη διεύθυνση `http://localhost:3000`. Θα πρέπει να δείτε την εφαρμογή Host με το Remote Component να αποδίδεται μέσα σε αυτήν.

Επεξήγηση των Βασικών Επιλογών Διαμόρφωσης:

Προηγμένες Τεχνικές Module Federation

Το Module Federation προσφέρει πολλά προηγμένα χαρακτηριστικά που μπορούν να σας βοηθήσουν να δημιουργήσετε ακόμη πιο εξελιγμένες αρχιτεκτονικές micro-frontend.

Δυναμικά Remotes

Αντί να κωδικοποιείτε σταθερά τα URLs των remote εφαρμογών στη διαμόρφωση του Webpack, μπορείτε να τα φορτώνετε δυναμικά κατά τον χρόνο εκτέλεσης. Αυτό σας επιτρέπει να ενημερώνετε εύκολα την τοποθεσία των remote εφαρμογών χωρίς να χρειάζεται να ξαναχτίσετε την εφαρμογή host.

Για παράδειγμα, θα μπορούσατε να αποθηκεύσετε τα URLs των remote εφαρμογών σε ένα αρχείο διαμόρφωσης ή σε μια βάση δεδομένων και να τα φορτώσετε δυναμικά χρησιμοποιώντας JavaScript.

```javascript // Στο webpack.config.js remotes: { remote: `promise new Promise(resolve => { const urlParams = new URLSearchParams(window.location.search); const remoteUrl = urlParams.get('remote'); // Assume remoteUrl is something like 'http://localhost:3001/remoteEntry.js' const script = document.createElement('script'); script.src = remoteUrl; script.onload = () => { // the key of module federation is that the remote app is // available using the name in the remote resolve(window.remote); }; document.head.appendChild(script); })`, }, ```

Τώρα μπορείτε να φορτώσετε την εφαρμογή host με μια παράμετρο query `?remote=http://localhost:3001/remoteEntry.js`

Κοινόχρηστα Modules με Έκδοση

Το Module Federation μπορεί να χειριστεί αυτόματα την έκδοση και την αποδιπλοποίηση των κοινόχρηστων modules για να διασφαλίσει ότι φορτώνεται μόνο μία συμβατή έκδοση κάθε module. Αυτό είναι ιδιαίτερα σημαντικό όταν αντιμετωπίζετε μεγάλες και σύνθετες εφαρμογές που έχουν πολλές εξαρτήσεις.

Μπορείτε να καθορίσετε το εύρος έκδοσης κάθε κοινόχρηστου module στη διαμόρφωση του Webpack.

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

Προσαρμοσμένοι Φορτωτές Module (Custom Module Loaders)

Το Module Federation σας επιτρέπει να ορίσετε προσαρμοσμένους φορτωτές module που μπορούν να χρησιμοποιηθούν για τη φόρτωση modules από διαφορετικές πηγές ή σε διαφορετικές μορφές. Αυτό μπορεί να είναι χρήσιμο για τη φόρτωση modules από ένα CDN ή από ένα προσαρμοσμένο μητρώο module.

Κοινή Χρήση Κατάστασης (State) μεταξύ Micro-frontends

Μία από τις προκλήσεις των αρχιτεκτονικών micro-frontend είναι η κοινή χρήση της κατάστασης μεταξύ διαφορετικών micro-frontends. Υπάρχουν διάφορες προσεγγίσεις που μπορείτε να ακολουθήσετε για να αντιμετωπίσετε αυτή την πρόκληση:

Βέλτιστες Πρακτικές για την Υλοποίηση Micro-frontends με το Module Federation

Ακολουθούν ορισμένες βέλτιστες πρακτικές που πρέπει να έχετε υπόψη κατά την υλοποίηση micro-frontends με το Module Federation:

Παραδείγματα από τον Πραγματικό Κόσμο της Χρήσης του Module Federation

Ενώ οι συγκεκριμένες μελέτες περιπτώσεων είναι συχνά εμπιστευτικές, εδώ είναι ορισμένα γενικευμένα σενάρια όπου το Module Federation μπορεί να είναι απίστευτα χρήσιμο:

Συμπέρασμα

Το JavaScript Module Federation στο Webpack 5 παρέχει έναν ισχυρό και ευέλικτο τρόπο για τη δημιουργία αρχιτεκτονικών micro-frontend. Σας επιτρέπει να μοιράζεστε κώδικα μεταξύ ξεχωριστά μεταγλωττισμένων εφαρμογών JavaScript κατά τον χρόνο εκτέλεσης, επιτρέποντας ανεξάρτητες αναπτύξεις, ποικιλομορφία τεχνολογίας και βελτιωμένη αυτονομία της ομάδας. Ακολουθώντας τις βέλτιστες πρακτικές που περιγράφονται σε αυτόν τον οδηγό, μπορείτε να αξιοποιήσετε το Module Federation για να δημιουργήσετε επεκτάσιμες, συντηρήσιμες και καινοτόμες εφαρμογές web.

Το μέλλον της ανάπτυξης frontend κλίνει αναμφίβολα προς τις αρθρωτές και κατανεμημένες αρχιτεκτονικές. Το Module Federation παρέχει ένα κρίσιμο εργαλείο για την κατασκευή αυτών των σύγχρονων συστημάτων, επιτρέποντας στις ομάδες να δημιουργούν σύνθετες εφαρμογές με μεγαλύτερη ταχύτητα, ευελιξία και ανθεκτικότητα. Καθώς η τεχνολογία ωριμάζει, μπορούμε να περιμένουμε να δούμε ακόμη πιο καινοτόμες περιπτώσεις χρήσης και βέλτιστες πρακτικές να αναδύονται.