JavaScript chunks not loading for Next.js 16 micro frontend app when routed through host app using rewrites #93391
Replies: 3 comments 1 reply
-
|
Is this happening on dev mode only? Could you try with Other things to troubleshoot:
I've ran out of time for now, but please do post back. Try to describe more of things you observe when debugging. |
Beta Was this translation helpful? Give feedback.
-
|
The chunks not loading is almost certainly because the catalog app's JS files are being requested from the host app's domain, but the asset prefix isn't set up to point back to the catalog app's origin. When Next.js builds the catalog app, it generates chunk URLs relative to the base path. But when the host app proxies the HTML via rewrites, those relative URLs resolve against the host domain — so the browser tries to load You need to set // catalog next.config.js
module.exports = {
assetPrefix: 'http://localhost:3001',
}In production this would be whatever domain/CDN serves the catalog app's static assets. The HTML gets proxied through the host, but the JS/CSS assets need to be loaded directly from the catalog app's origin. |
Beta Was this translation helpful? Give feedback.
-
|
The previous comment identified Why this happensWhen the host app at Complete configurationCatalog app /** @type {import('next').NextConfig} */
const nextConfig = {
// Tell Next.js where static assets are served from
assetPrefix: process.env.NODE_ENV === 'production'
? 'https://catalog.yourdomain.com'
: 'http://localhost:3001',
// Required: tells Next.js the path prefix so internal links resolve correctly
// Only set this if catalog is always served under a subpath
// basePath: '/catalog', // uncomment if catalog routes are at /catalog/*
// Allow the host app to frame/rewrite pages from this app
experimental: {
// Required for App Router micro frontends:
// Prevents double-rendering of the shell
optimizePackageImports: [],
},
};
module.exports = nextConfig;Host app const nextConfig = {
async rewrites() {
return [
// Proxy catalog app static assets through host (for same-origin chunk loading)
// This is an ALTERNATIVE to assetPrefix — use one approach, not both
{
source: '/catalog/_next/:path*',
destination: 'http://localhost:3001/_next/:path*',
},
// Proxy catalog app pages
{
source: '/catalog/:path*',
destination: 'http://localhost:3001/:path*',
},
];
},
};
module.exports = nextConfig;Two approaches — pick oneOption A: Catalog app emits absolute URLs in its Option B: Proxy Host app rewrites both For local dev, Option B is simpler. For production, Option A is more performant. CORS setup for Option A (if needed)// catalog next.config.js
async headers() {
return [
{
source: '/_next/static/:path*',
headers: [
{ key: 'Access-Control-Allow-Origin', value: 'http://localhost:3000' },
],
},
];
},Debug: confirm which chunks are loadingOpen Chrome DevTools → Network → filter by JS → look at the request URLs for |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I am working on a Next.js micro frontend architecture using the App Router, next-intl, and Next.js 16.2.4.
The setup has multiple independent Next.js apps:
host app running on http://localhost:3000
catalog app running on http://localhost:3001
checkout app running on http://localhost:3002
The host app is the main shell. It routes some paths to the catalog app using Next.js rewrites. The problem happens when the catalog app is accessed through the host app.
When I open a catalog route from the host app, the HTML/page renders, but the JavaScript does not load correctly. Because of this, client components are not hydrated and client-side actions do not work.
For example, a simple client component like this does not trigger the click event:
The button renders, but console.log('clicked') does not run when clicking it.
Because hydration/client JS is not working, other JavaScript-based providers are also not working, such as:
context providers
cart/wishlist providers
toast provider
analytics provider
shared UI package client behavior
other interactive client components
Architecture
The host app uses Next.js rewrites to forward catalog routes to the catalog app.
Example from host/next.config.ts:
The catalog app has its own assetPrefix:
Both apps use:
{ "next": "^16.2.4", "react": "^19.0.0", "react-dom": "^19.0.0", "next-intl": "^4.11.0" }Both apps use next-intl locale routing:
The catalog app layout wraps pages with several client providers:
The Providers component is a client component and includes providers like SessionProvider, NextIntlClientProvider, CartProvider, WishlistProvider, Toast, etc.
Expected Behavior
When I access a catalog route through the host app, for example:
http://localhost:3000/en/product/8078711455933
I expect:
the catalog page HTML to render
the catalog app JavaScript chunks to load
React hydration to complete
client components to work
onClick handlers to fire
providers and interactive UI behavior to work
Actual Behavior
The page renders, but client-side JavaScript does not work.
Symptoms:
onClick handlers do not fire
client actions do not work
providers depending on client JS do not initialize correctly
interactive UI from shared packages does not work
hydration appears to fail or never complete
In terminal logs, I also sometimes see errors like:
TypeError: Cannot read properties of undefined (reading 'call')
at .next/server/webpack-runtime.js
And when the catalog app is not running, the host shows proxy errors like:
Failed to proxy http://localhost:3001/en/product/8078711455933
ECONNREFUSED 127.0.0.1:3001
Beta Was this translation helpful? Give feedback.
All reactions