Я слежу за парой статей о том, как реализовать простой подход к микро-интерфейсу с помощью React (здесь и здесь, см. образцы репозиториев внизу вопроса).
Он отлично работает, когда два приложения (корневое приложение и вспомогательное приложение) работают на своих соответствующих серверах разработки. Однако когда я развертываю артефакты сборки на реальном веб-сервере, это не работает. Это важный код в корневом приложении:
function MicroFrontend({name, host, history}) {
useEffect(() => {
const scriptId = `micro-frontend-script-${name}`;
const renderMicroFrontend = () => {
window["render" + name](name + "-container", history);
};
if (document.getElementById(scriptId)) {
renderMicroFrontend();
return;
}
fetch(`${host}/asset-manifest.json`)
.then((res) => res.json())
.then((manifest) => {
const script = document.createElement("script");
script.id = scriptId;
script.crossOrigin = "";
script.src = `${host}${manifest.files["main.js"]}`;
script.onload = () => {
renderMicroFrontend();
};
document.head.appendChild(script);
});
return () => {
window[`unmount${name}`] && window[`unmount${name}`](`${name}-container`);
};
});
return <main id={`${name}-container`}/>;
}
MicroFrontend.defaultProps = {
document,
window,
};
Когда я нажимаю кнопку, которая загружает main.js для микроприложения, оно отлично работает до момента, когда вызывает renderMicroFrontend
выше. Затем я получаю в своем браузере такую ошибку: Uncaught TypeError: window[("render" + t)] is not a function
Это потому, что он не может найти функцию, которая загружает микрофронтенд, который должен быть на window
. Когда я запускаю два приложения на сервере разработки, у меня есть правильная функция на window
, и она работает. Когда я выполняю те же шаги с двумя приложениями, развернутыми на реальном сервере (после запуска npm run build
), вместо функции renderMicroApp
на моем window
у меня есть другая переменная с именем: webpackJsonpmicro-app
.
Я понял, что это связано с параметром output.library (и / или связанными с ним параметрами) в веб-пакете из документации веб-пакета:
output.jsonpFunction. string = 'webpackJsonp' Используется только в том случае, если для цели задано значение «web», при котором для загрузки фрагментов по запросу используется JSONP. При использовании параметра output.library имя библиотеки автоматически объединяется со значением output.jsonpFunction.
Я в основном хочу, чтобы пакет / скрипт был загружен и оценен, чтобы функция renderMicroApp
была доступна в окне, но я не понимаю, какие настройки веб-пакета мне нужны, чтобы это работало, поскольку существует множество различных вариантов перестановок.
Для справки я использую следующие переопределения конфигурации в микроприложении (поверх react-app-rewired
):
module.exports = {
webpack: (config, env) => {
config.optimization.runtimeChunk = false;
config.optimization.splitChunks = {
cacheGroups: {
default: false,
},
};
config.output.filename = "static/js/[name].js";
config.plugins[5].options.filename = "static/css/[name].css";
config.plugins[5].options.moduleFilename = () => "static/css/main.css";
return config;
},
};
И в моем index.tsx (в микроприложении) я выставляю функцию в окне:
window.renderMicroApp = (containerId, history) => {
ReactDOM.render(<AppRoot />, document.getElementById(containerId));
serviceWorker.unregister();
};
Некоторые образцы репозиториев: