Como usar module federation com Nextjs 14 e typescript?
Estou trabalhando em um novo projeto com Nextjs 14 e typescript, e temos que compartilhar entre diferentes projetos, (de times diferentes) o Header e o Footer. Pesquisando um pouco vi que para desafios como esse, é possivel usar Module Federation, porem tudo o que encontrei esta usando versoes anteriores do Nextjs e/ou javascript.
Alguem sabe me dizer como configurar o ModuleFederationPlugin do webpack ou NextFederationPlugin module-federation/nextjs-mf?
Abaixo as alternativas que tentei:
Usando webpack ModuleFederationPlugin
No projeto que exporta os componentes, estou chamando ele de main, temos o seguinte next.config.mjs
import ModuleFederationPlugin from 'webpack/lib/container/ModuleFederationPlugin.js';
import ModuleFederationPlugin from 'webpack/lib/container/ModuleFederationPlugin.js';
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
webpack: (config, options) => {
const { isServer } = options;
config.plugins.push(
new ModuleFederationPlugin({
name: 'main',
remotes: {
shop: `shop@http://localhost:3001/_next/static/${isServer ? 'ssr' : 'chunks'}/remoteEntry.js`,
},
exposes: {
'./footer': './src/components/Footer.tsx',
'./header': './src/components/Header.tsx',
},
filename: 'static/chunks/remoteEntry.js',
shared: {}
}),
);
return config;
}
};
export default nextConfig;
Com esse código a aplicacao main funciona corretamente, porem o projeto que precisa usar o Header e o Footer, retorna erro
ReferenceError: document is not defined while loading "./header" from webpack/container/reference/main while loading "./footer" from webpack/container/reference/main
Tentei usar de duas formas
const Header = dynamic(() => import("main/header"));
const Footer = dynamic(() => import("main/footer").then((mod) => mod.Footer),
{
ssr: true
}
);
E este é o next.config.mjs do projeto que consome o Header e o Footer
import ModuleFederationPlugin from 'webpack/lib/container/ModuleFederationPlugin.js';
const nextConfig = {
reactStrictMode: true,
webpack(config, { isServer }) {
config.plugins.push(
new ModuleFederationPlugin({
name: 'shop',
remotes: {
main: ``main@http://localhost:3000/_next/static/${isServer ? 'ssr' : 'chunks'}/remoteEntry.js``,
},
filename: 'static/chunks/remoteEntry.js',
})
);
return config;
},
}
export default nextConfig;
NextFederationPlugin
No projeto main o meu arquivo next.config.mjs fica assim:
import { NextFederationPlugin } from '@module-federation/nextjs-mf';
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
webpack(config, options) {
const { isServer } = options;
config.plugins.push(
new NextFederationPlugin({
name: 'main',
exposes: {
'./footer': './src/components/Footer.tsx',
},
remotes: {
home: `home@http://localhost:3001/_next/static/${isServer ? 'ssr' : 'chunks'}/remoteEntry.js`,
},
filename: 'static/chunks/remoteEntry.js',
shared: {}
}),
);
return config;
}
};
export default nextConfig;
Com esse código a aplicao main nao funciona, ao tentar rodar recebo este erro:
Error: Compiling RuleSet failed: Expected condition but got falsy value (at ruleSet[1].rules[14].oneOf[5].exclude[0]: undefined)