Я пытаюсь реализовать простой пример Module Federation с функциями vanilla js.
Структура каталога:
── packages
├── home
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ └── index.js
│ └── webpack.config.js
└── nav
├── index.html
├── package.json
├── src
│ ├── Header.js
│ ├── index.js
└── webpack.config.js
Ожидаемый результат заключается в том, что home
приложение отображает Header
из nav
.
Конфигурация Webpack nav
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const deps = require("./package.json").dependencies;
module.exports = {
mode: 'development',
entry: './src/index.js',
optimization: {
minimize: false
},
resolve: {
extensions: [".js"],
},
output: {
publicPath: "http://localhost:4001/",
},
plugins: [
new ModuleFederationPlugin({
name: "nav",
filename: "remoteEntry.js",
library: {type: 'var', name: 'nav'},
exposes: {
"./Header": "./src/Header"
},
shared: {
...deps
}
}),
new HtmlWebpackPlugin({
title: 'Module Federation Example',
}),
],
}
Конфигурация Webpack home
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')
const deps = require("./package.json").dependencies;
module.exports = {
mode: 'development',
entry: './src/index.js',
optimization: {
minimize: false,
},
resolve: {
extensions: [".js"],
},
output: {
publicPath: "http://localhost:4000/",
},
plugins: [
new ModuleFederationPlugin({
name: "home",
filename: "remoteEntry.js",
remotes: {
nav: "nav@http://localhost:4001/remoteEntry.js"
},
shared: {
...deps
}
}),
new HtmlWebpackPlugin({
title: 'Module Federation Example',
}),
],
}
Это заголовок:
export default () => {
const node = document.createElement('div');
node.innerHTML = 'Header';
node.style = 'padding: 1em; box-sizing: border-box;display: flex;background: aquamarine;font-family:sans-serif;'
return node;
}
В файле index.js
в home
я импортирую Header
:
import Header from 'nav/Header';
const Greetings = () => {
const node = document.createElement('h1');
node.innerHTML = 'App Shell';
return node;
}
document.addEventListener("DOMContentLoaded", () => {
document.body.appendChild(Greetings());
document.body.appendChild(Header());
});
После сборки и использования URL-адреса приложения home
я получаю эту ошибку:
Uncaught TypeError: __webpack_modules__[moduleId] is not a function
at __webpack_require__ (main.js:66:41)
at eval (index.js:2:68)
at ./src/index.js (main.js:19:1)
at __webpack_require__ (main.js:66:41)
at main.js:217:37
at main.js:219:12
Вы можете воспроизвести здесь в StackBlitz.
Я попытался добавить опцию библиотеки library: {type: 'var', name: 'nav'},
в ModuleFederationPlugin, но я не понимаю, почему это не работает.
Я ожидал увидеть nav/Header
в домашнем приложении.
Я нашел решение.
Ошибка возникает из-за того, что я импортировал удаленный модуль непосредственно в файл index.js
.
Удаленный модуль загружается асинхронно, поэтому он еще не был доступен для импорта и, следовательно, ошибка.
Самое быстрое решение — импортировать удаленные модули в файл bootstrap.js
, чтобы убедиться, что они доступны, и импортировать их в index.js
index.js
import("./bootstrap");
bootstrap.js
import Header from 'nav/Header';
// other logics ...