#javascript #reactjs #webpack
#javascript #reactjs #webpack
Вопрос:
У меня есть приложение React microfrontend. До сих пор я собрал два вспомогательных приложения, которые отображаются через container/
проект. Изолированно, на localhost: 8083 я могу видеть рендеринг вспомогательного приложения просто отлично, но, в отличие от других вспомогательных приложений, когда мне нужно просмотреть его через localhost: 8080 / dashboard, я не получаю ничего, кроме белого экрана и, что еще хуже, никакой ошибки в терминале, никакой ошибки в консоли, никакой ошибки всетевые запросы.
Это мой webpack.dev.js
файл в container/
:
const { merge } = require("webpack-merge");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const commonConfig = require("./webpack.common");
const packageJson = require("../package.json");
const devConfig = {
mode: "development",
output: {
publicPath: "http://localhost:8080/",
},
devServer: {
port: 8080,
historyApiFallback: true,
},
plugins: [
new ModuleFederationPlugin({
name: "container",
remotes: {
marketing: "marketing@http://localhost:8081/remoteEntry.js",
auth: "auth@http://localhost:8082/remoteEntry.js",
dashboard: "dashboard@http://localhost:8083/remoteEntry.js",
},
shared: packageJson.dependencies,
}),
],
};
module.exports = merge(commonConfig, devConfig);
Я неоднократно смотрел на это, не вижу в этом ничего плохого.
Это webpack.common.js
файл, который у меня есть в этой container/
папке:
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react', '@babel/preset-env'],
plugins: ['@babel/plugin-transform-runtime']
},
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html'
}),
]
}
Я посмотрел на это и не вижу в этом ничего плохого.
Вот мой components/DashboardApp.js
файл внутри container/
:
import { mount } from "dashboard/DashboardApp";
import React, { useRef, useEffect } from "react";
import { useHistory } from "react-router-dom";
export default ({ onSignIn }) => {
const ref = useRef(null);
const history = useHistory();
useEffect(() => {
const { onParentNavigate } = mount(ref.current, {
initialPath: history.location.pathname,
onNavigate: ({ pathname: nextPathname }) => {
const { pathname } = history.location;
if (pathname !== nextPathname) {
history.push(nextPathname);
}
},
onSignIn,
});
history.listen(onParentNavigate);
}, []);
return <div ref={ref} />;
};
Мой container/src/App.js
файл:
import React, { lazy, Suspense, useState } from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import {
StylesProvider,
createGenerateClassName,
} from "@material-ui/core/styles";
import Progress from "./components/Progress";
import Header from "./components/Header";
const MarketingLazy = lazy(() => import("./components/MarketingApp"));
const AuthLazy = lazy(() => import("./components/AuthApp"));
const DashboardLazy = lazy(() => import("./components/DashboardApp"));
const generateClassName = createGenerateClassName({
productionPrefix: "co",
});
export default () => {
const [isSignedIn, setIsSignedIn] = useState(false);
return (
<BrowserRouter>
<StylesProvider generateClassName={generateClassName}>
<div>
<Header
onSignOut={() => setIsSignedIn(false)}
isSignedIn={isSignedIn}
/>
<Suspense fallback={<Progress />}>
<Switch>
<Route path='/auth'>
<AuthLazy onSignIn={() => setIsSignedIn(true)} />
</Route>
<Route path='/dashboard' component={DashboardLazy} />
<Route path='/' component={MarketingLazy} />
</Switch>
</Suspense>
</div>
</StylesProvider>
</BrowserRouter>
);
};
Может ли кто-нибудь увидеть что-нибудь, что я, возможно, пропустил? Почему этот компонент не будет отображаться через container/
, тогда как другие вспомогательные приложения, созданные точно так же, могут.
Комментарии:
1. действителен ли ваш URL-адрес удаленного входа? маркетинг: «marketing@localhost:8081/remoteEntry.js »
2. Взгляните на этот URL blog.bitsrc.io /… , похоже, база контента отсутствует3. @Sam, я только что попробовал contentBase, и это не отображало дополнительное приложение, выглядит так же, как и раньше.
4. @Sam, да, это
marketing: "marketing@http://localhost:8081/remoteEntry.js",
действительно, у меня нет никаких проблем с ним илиauth
с ним.5. Рад, что вы можете заставить его работать, как вы пока находите объединение модулей. у вас есть какие-либо другие проблемы?. Мы планируем использовать в нашем приложении, просто хотим знать, как это пока?
Ответ №1:
Когда приложение начинает усложняться, речь идет о мельчайших деталях. В то время как в моем container/src/App.js
файле был a path="/dashboard"
, в моем dashboard/src/App.js
файле его не было, он выглядел так:
import React from "react";
import { Switch, Route, Router } from "react-router-dom";
import {
StylesProvider,
createGenerateClassName,
} from "@material-ui/core/styles";
import Dashboard from "./components/Dashboard";
const generateClassName = createGenerateClassName({
productionPrefix: "da",
});
export default ({ history }) => {
return (
<div>
<StylesProvider generateClassName={generateClassName}>
<Router history={history}>
<Switch>
<Route exact path='/' component={Dashboard} />
</Switch>
</Router>
</StylesProvider>
</div>
);
};
Однажды я изменил его на этот:
import React from "react";
import { Switch, Route, Router } from "react-router-dom";
import {
StylesProvider,
createGenerateClassName,
} from "@material-ui/core/styles";
import Dashboard from "./components/Dashboard";
const generateClassName = createGenerateClassName({
productionPrefix: "da",
});
export default ({ history }) => {
return (
<div>
<StylesProvider generateClassName={generateClassName}>
<Router history={history}>
<Switch>
<Route exact path='/dashboard' component={Dashboard} />
</Switch>
</Router>
</StylesProvider>
</div>
);
};
Теперь он отображается внутри родительского контейнера.
Ответ №2:
Вам не хватает contentBase.
devServer: {
contentBase: path.join(__dirname, "dist"),
port: 3002,
},
output: {
publicPath: "http://localhost:3002/",
},