[英]Micro frontend routing issue with Next.js
I am building a micro frontend framework with three Next.js projects (app1, app2, base).我正在构建一个包含三个 Next.js 项目(app1、app2、base)的微前端框架。
app1
and app2
are the remote application and base
is the host application. app1
和app2
是远程应用程序, base
是主机应用程序。
app1 next.config.js
: app1
next.config.js
:
const { withModuleFederation } = require('@module-federation/nextjs-mf');
module.exports = {
webpack5: true,
images: {
domains: ['static.wikia.nocookie.net'],
},
webpack: (config, options) => {
const { isServer } = options;
const mfConf = {
mergeRuntime: true,
name: 'app1',
library: {
type: config.output.libraryTarget,
name: 'app1',
},
filename: 'static/runtime/app1RemoteEntry.js',
remotes: {},
exposes: {
'./thanatos': './components/thanatos',
},
};
config.cache = false;
withModuleFederation(config, options, mfConf);
if (!isServer) {
config.output.publicPath = 'http://localhost:3001/_next/';
}
return config;
},
webpackDevMiddleware: (config) => {
// Perform customizations to webpack dev middleware config
// Important: return the modified config
return config;
},
};
app2 next.config.js
app2
next.config.js
const { withModuleFederation } = require('@module-federation/nextjs-mf');
module.exports = {
webpack5: true,
images: {
domains: ['static.wikia.nocookie.net'],
},
webpack: (config, options) => {
const { isServer } = options;
const mfConf = {
mergeRuntime: true,
name: 'app2',
library: {
type: config.output.libraryTarget,
name: 'app2',
},
filename: 'static/runtime/app2RemoteEntry.js',
remotes: {},
exposes: {
'./zagreus': './components/zagreus',
},
};
config.cache = false;
withModuleFederation(config, options, mfConf);
if (!isServer) {
config.output.publicPath = 'http://localhost:3002/_next/';
}
return config;
},
webpackDevMiddleware: (config) => {
// Perform customizations to webpack dev middleware config
// Important: return the modified config
return config;
},
};
base next.config.js
基础
next.config.js
const { withModuleFederation } = require('@module-federation/nextjs-mf');
const path = require('path');
// For SSR, resolve to disk path (or you can use code streaming if you have access)
// in production use the chunks
const ssrRemoteEntry = (app) =>
process.env.NODE_ENV === 'production'
? path.join(
`<remotes-path>/${app}/.next/server/chunks/static/runtime/remoteEntry.js`
)
: path.resolve(
__dirname,
`../${app}/.next/server/static/runtime/remoteEntry.js`
);
module.exports = {
webpack5: true,
images: {
domains: ['static.wikia.nocookie.net'],
},
webpack: (config, options) => {
const { isServer } = options;
const mfConf = {
name: 'base',
library: {
type: config.output.libraryTarget,
name: 'base',
},
remotes: {
app1: isServer ? ssrRemoteEntry('app1') : 'app1',
app2: isServer ? ssrRemoteEntry('app2') : 'app2',
},
exposes: {},
};
config.cache = false;
withModuleFederation(config, options, mfConf);
return config;
},
webpackDevMiddleware: (config) => {
// Perform customizations to webpack dev middleware config
// Important: return the modified config
return config;
},
};
base _document.js
基础
_document.js
import Document, { Html, Head, Main, NextScript } from 'next/document';
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps };
}
render() {
return (
<Html>
<script src="http://localhost:3001/_next/static/runtime/app1RemoteEntry.js" />
<script src="http://localhost:3002/_next/static/runtime/app2RemoteEntry.js" />
<Head>
<link rel="icon" href="/favicon.ico" />
<meta
name="description"
content="Demo for Microfrontends using Module Federation"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
When I run the three applications, on base
application I can only see the page for base
but when I click on the other two buttons want to navigate to app1
and app2
, the browser shows the blank page.当我运行这三个应用程序时,在
base
应用程序上我只能看到base
页面,但是当我单击其他两个按钮想要导航到app1
和app2
时,浏览器会显示空白页面。
I may have the solution for you.我可能有你的解决方案。 What you need to do in the next.config.js is add your URLs to your.env file.
在 next.config.js 中您需要做的是将您的 URL 添加到 your.env 文件中。 From there, you tell your base app to navigate to the URL and route.
从那里,您告诉您的基础应用程序导航到 URL 并路由。
Here is a sample of what I have done:这是我所做的一个示例:
const { APP1_URL, APP2_URL } = process.env;
module.exports = {
webpackDevMiddleware: (config) => {
config.watchOptions = {
poll: 1000,
aggregateTimeout: 300,
};
return config;
},
output: "standalone",
async rewrites() {
return [
{
source: "/dashboard",
destination: "/",
},
{
source: "/app1",
destination: `${APP1_URL}/app1`,
},
{
source: "/app1/:path*",
destination: `${APP1_URL}/app1/:path*`,
},
{
source: "/app2",
destination: `${APP2_URL}/app2`,
},
{
source: "/app2/:path*",
destination: `${APP2_URL}/app2/:path*`,
},
];
},
};
The tricky part is getting back to your base.棘手的部分是回到你的基地。 Here is a sample for App1's next.config.js:
这是 App1 的 next.config.js 的示例:
module.exports = {
webpackDevMiddleware: (config) => {
config.watchOptions = {
poll: 1000,
aggregateTimeout: 300,
};
return config;
},
basePath: "/app1",
output: "standalone",
async redirects() {
return [
{
source: "/app1/dashboard",
destination: "/",
basePath: false,
permanent: true,
},
{
source: "/app1/app1",
destination: "/app1",
basePath: false,
permanent: true,
},
];
},
};
Note the webpackDevMiddleware is just for hot refreshing.注意 webpackDevMiddleware 仅用于热刷新。 You don't need it if you don't want.
如果你不想要,你就不需要它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.