Error when use remote components with hooks and module federations with nextjs - next.js

I receive this error when use hooks in component from remote app when
enter image description here
i use now nextjs13 with module federations
how to resolve this
enter code here
my component remote app
'use client'
import { useState } from 'react'
export default function Button() {
const [count, setCount] = useState(0)
return (
<div>
<button onClick={() => setCount(count + 1)}>adicionar</button>
<h1>{count}</h1>
</div>
)
}
my component in host
'use client'
import dynamic from 'next/dynamic'
import React, { useState } from 'react'
const RemoteComponent = dynamic({
loader: async () => {
const { default: RemoteComponent } = await import('front_login/Button')
return () => <RemoteComponent />
},
})
export default function Auth() {
return (
<>
<RemoteComponent />
</>
)
}
my next-config.js in host
const { NextFederationPlugin } = require('#module-federation/nextjs-mf')
/** #type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
experimental: {
appDir: true,
},
webpack: (config, options) => {
const { isServer } = options
Object.assign(config.experiments, { topLevelAwait: true })
config.watchOptions = {
poll: 1000,
aggregateTimeout: 300,
}
config.plugins.push(
new NextFederationPlugin({
name: 'front_gateway',
remotes: {
front_login: `front_login#${process.env.FRONT_LOGIN}/_next/static/${
isServer ? 'ssr' : 'chunks'
}/remoteEntry.js`,
},
filename: 'static/chunks/remoteEntry.js',
shared: {
'styled-components': {
requiredVersion: false,
eager: true,
singleton: true,
},
},
}),
)
return config
},
}
module.exports = nextConfig
my next config in remote app
/** #type {import('next').NextConfig} */
const { NextFederationPlugin } = require('#module-federation/nextjs-mf')
const nextConfig = {
output: 'standalone',
experimental: {
appDir: true,
},
webpack: (config, options) => {
const { isServer } = options
config.watchOptions = {
poll: 1000,
aggregateTimeout: 300,
}
config.plugins.push(
new NextFederationPlugin({
name: 'front_login',
remotes: {
front_gateway: `front_gateway#${
process.env.FRONT_GATEWAY
}/_next/static/${isServer ? 'ssr' : 'chunks'}/remoteEntry.js`,
},
filename: 'static/chunks/remoteEntry.js',
exposes: {
'./Button': './src/app/components/Button/button.tsx',
'./Doidao': './src/app/doidao/page.tsx',
},
shared: {
'styled-components': {
singleton: true,
eager: true,
requiredVersion: false,
},
},
}),
)
return config
},
}
module.exports = nextConfig
Please i need help to fix this
When use remote component in remote app, work with success but in host not working

Related

nextjs dynamic() import works in dev mode, but not the production, Nextjs13 pages dir #45582

I have an app with nextjs 13 pages dire.
i am using zoom web sdk for embed the meetings. it works just fine in the dev mode.
the proplem:
when i build the app everything working except that zoom component not showing up after build,
when visiting the /meeting page the component didn't exist.
const ZoomCall = dynamic(() => import("#components/Zoom/ZoomCall"), {
ssr: false,
loading: () => "Loading...",
});
the ZoomCall
import { useEffect } from "react";
import dynamic from "next/dynamic";
import { ZoomMtg } from "#zoomus/websdk";
import ZoomMtgEmbedded from "#zoomus/websdk/embedded";
import ZoomInputs from "./ZoomInputs";
import { useState } from "react";
import useTranslation from "next-translate/useTranslation";
export default function ZoomCall({
user,
meetingNumber,
setMeetingnumber,
passWord,
setMeetingPassword,
}) {
const { t } = useTranslation();
const [isComponentMounted, setIsComponentMounted] = useState(false);
const signatureEndpoint = "/api/zoom/signature";
const role = 0;
useEffect(() => {
ZoomMtg.setZoomJSLib("https://source.zoom.us/1.9.1/lib", "/av");
ZoomMtg.preLoadWasm();
ZoomMtg.prepareJssdk();
}, []);
function getSignature(e) {
e.preventDefault();
fetch(signatureEndpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
meetingNumber: meetingNumber,
role: role,
}),
})
.then((res) => res.json())
.then((response) => {
startMeeting(response.signature);
})
.catch((error) => {
console.error(error);
});
}
function startMeeting(signature) {
let meetingSDKElement = document.getElementById("meetingSDKElement");
const client = ZoomMtgEmbedded.createClient();
// document.getElementById("zmmtg-root").style.display = "block";
client.init({
debug: true,
zoomAppRoot: meetingSDKElement,
language: "en-US",
customize: {
meetingInfo: [
"topic",
"host",
"mn",
"pwd",
"telPwd",
"invite",
"participant",
"dc",
"enctype",
],
toolbar: {
buttons: [
{
text: "Custom Button",
className: "CustomButton",
onClick: () => {
console.log("custom button");
},
},
],
},
},
});
client.join({
sdkKey: process.env.NEXT_PUBLIC_ZOOM_API_KEY,
signature: signature,
meetingNumber: meetingNumber,
password: passWord,
userName: "..",
userEmail: "ah....",
});
}
return (
<div>
<div id="meetingSDKElement"></div>
<button onClick={getSignature}>Join Meeting</button>
</div>
);
}
I have moved the exports to a index file the export
import dynamic from "next/dynamic";
export default dynamic(() => import("./ZoomCall"), { ssr: false });
the issue in still
i have managed to solve this by changing the :
const ZoomCall = dynamic(() => import("#components/Zoom/ZoomCall"), {
ssr: false,
loading: () => "Loading...",
});
into
export default dynamic(() => import("./ZoomCall").then((mod) => mod.ZoomCall), {
ssr: false,
});
and it works just fine

next-i18next fail to load locales from public folder

I migrated to next.js and started to use next-i18next. I would like to know, how to make next-i18next load locales from the public folder? It works only when I place the locales folder in the root directory not in public.
i18n.json ;
{
"locales": ["en", "fr", "ar"],
"defaultLocale": "en",
"pages": {
"*": ["common"]
}
}
next.config.js ;
// next.config.js
const nextTranslate = require("next-translate");
module.exports = {
...nextTranslate(),
};
Create i18n.js file root add this code inside:
const path = require('path');
module.exports = {
i18n: {
locales: ['en', 'ru', 'tm'],
defaultLocale: 'en',
localeDetection: false,
localePath: path.resolve('./public/locales'),
},
};
and add config next.config.js file this:
const { i18n } = require('./i18n');
const nextConfig = {
reactStrictMode: true,
i18n,
};
module.exports = nextConfig;
after every page add transalition code. example: index.file
import React, { useContext, useEffect } from 'react';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { useTranslation } from 'next-i18next';
import Router from 'next/router';
import { Title } from '../components';
import i18n from '../i18n';
const Home = () => {
const { t } = useTranslation('');
useEffect(() => {
if (!user) {
Router.push('/login');
}
});
return (
<>
<Title title={`${t('page.home')} | Trillo`} />
<div className="min-h-screen">Home</div>
</>
);
};
export const getServerSideProps = async ({ locale }) => (
{ props: {
...(await serverSideTranslations(
locale,
['common'],
i18n,
)),
} }
);
export default Home;
After you create these files inside public folder like this. see this and see this 2

how to setup antd less support with nextjs 12

im trying to setup nextjs 12 with ant design antd and in next.config.js when i try to setup withAntdLess it gives type error
Type '{}' is missing the following properties from type '{ esModule: boolean; sourceMap: boolean; modules: { mode: string; }; }': esModule, sourceMap, modules
although all props are optional according to next-plugin-antd-less docs
next.config.js file:
// #ts-check
// next.config.js
const withAntdLess = require('next-plugin-antd-less');
/**
* #type {import('next').NextConfig}
**/
module.exports =withAntdLess({
cssLoaderOptions: {},
// Other Config Here...
webpack(config) {
return config;
},
reactStrictMode: true,
});
I solved it using next-with-less https://github.com/elado/next-with-less
next.config.js
const withLess = require('next-with-less');
const lessToJS = require('less-vars-to-js');
const themeVariables = lessToJS(
fs.readFileSync(
path.resolve(__dirname, './public/styles/custom.less'),
'utf8'
)
);
module.exports = withLess({
...
lessLoaderOptions: {
lessOptions: {
javascriptEnabled: true,
modifyVars: themeVariables, // make your antd custom effective
localIdentName: '[path]___[local]___[hash:base64:5]',
},
},
...
})
Import your custom less file on top off the file _app.jsx
import 'public/styles/custom.less';
...
Import the default Antd less file on your custom less file: (in my case public/styles/custom.less)
#import "~antd/dist/antd.less";
....
Extra notes:
If you have an old implementation of Antd, you should remove the integration in your .babelrc
[
"import",
{
"libraryName": "antd",
"libraryDirectory": "lib",
"style": true
}
],
If you have an old implementation of Antd, you should remove the integration in your webpack zone in your next.config.js
if (isServer) {
const antStyles = /antd\/.*?\/style.*?/;
const origExternals = [...config.externals];
config.externals = [
(context, request, callback) => {
if (request.match(antStyles)) return callback();
if (typeof origExternals[0] === 'function') {
origExternals[0](context, request, callback);
} else {
callback();
}
},
...(typeof origExternals[0] === 'function' ? [] : origExternals),
];
config.module.rules.unshift({
test: antStyles,
use: 'null-loader',
});
}

React-responsive-carousel styles not working

I am trying to add react-responsive-carousel to my NextJS project. When i run npm run dev everything seems to be fine, however my carousel is rendered with no styles.
import { Carousel } from 'react-responsive-carousel';
import 'react-responsive-carousel/lib/styles/carousel.min.css'; // requires loader
const MyCarousel = () => {
return (
<Carousel
autoPlay
interval={2500}
showArrows={true}
>
<div>content</div>
<div>content</div>
<div>content</div>
</Carousel>
)
}
Documentation says that styles need a loader so I configures next.config.js as follows
const withLess = require('#zeit/next-less');
const withCss = require('#zeit/next-css');
const withImage = require('next-images');
const theme = require('./app/styles/antdoverrides');
module.exports = withImage(
withCss({
cssModules: true,
optimizeFonts: false,
...withLess({
lessLoaderOptions: {
javascriptEnabled: true,
importLoaders: 0,
modifyVars: {
...theme,
},
},
cssLoaderOptions: {
importLoaders: 3,
localIdentName: '[local]___[hash:base64:5]',
},
webpack5: false,
webpack: (config, { isServer }) => {
if (isServer) {
const antStyles = /antd\/.*?\/style.*?/;
const origExternals = [...config.externals];
config.externals = [
(context, request, callback) => {
if (request.match(antStyles)) return callback();
if (typeof origExternals[0] === 'function') {
origExternals[0](context, request, callback);
} else {
callback();
}
},
...(typeof origExternals[0] === 'function' ? [] : origExternals),
];
config.module.rules.unshift({
test: antStyles,
use: 'null-loader',
});
}
return config;
},
}),
}),
);
still not getting desired result. Any hints appreciated
You need to import your styles in your _app.js file if you don't use the objects. Just in your _app make import of your styles, something like:
import "../styles/globals.css";
Also you need to npm run local or something like this, check your package.json file to run locally your project instead of build

adding export script to an existing next.config.js

I'm following Microsoft's Tutorial:
Deploy static-rendered Next.js websites on Azure Static Web Apps
The problem is, I'm trying to add to my next.config.js file this code:
const data = require('./utils/projectsData');
module.exports = {
trailingSlash: true,
exportPathMap: async function () {
const { projects } = data;
const paths = {
'/': { page: '/' },
};
projects.forEach((project) => {
paths[`/project/${project.slug}`] = {
page: '/project/[path]',
query: { path: project.slug },
};
});
return paths;
},
};
but my next.config.js already has some existing content:
require('dotenv').config()
const withFonts = require('next-fonts')
module.exports = withFonts({
serverRuntimeConfig: {},
trailingSlash: true,
exportPathMap: function() {
return {
'/': { page: '/' }
};
},
publicRuntimeConfig: {
API_URL: process.env.API_URL,
PORT: process.env.PORT || 3000,
PUBLISHABLE_KEY: process.env.PUBLISHABLE_KEY,
},
})
how can I combine them?
Just combine them like that?
require('dotenv').config()
const data = require('./utils/projectsData'); // Add this line
const withFonts = require('next-fonts')
module.exports = withFonts({
serverRuntimeConfig: {},
trailingSlash: true,
// And override this key
exportPathMap: async function () {
const { projects } = data;
const paths = {
'/': { page: '/' },
};
projects.forEach((project) => {
paths[`/project/${project.slug}`] = {
page: '/project/[path]',
query: { path: project.slug },
};
});
return paths;
},
publicRuntimeConfig: {
API_URL: process.env.API_URL,
PORT: process.env.PORT || 3000,
PUBLISHABLE_KEY: process.env.PUBLISHABLE_KEY,
},
})

Resources