core: Error: NextJS MFE plugin throws error with experimental app directory enabled

NextJS latest with Experimental App directory enabled breaks during build with NextJS Mfe plugin

I tried @module-federation/nextjs-mf": "^6.4.0 plugin with the latest NextJS that has a new way of making pages. For monorepo setup I used turborepo To use the app directory below settings need to be added in next.config.js

  experimental: {
    appDir: true,
  },

And finally to enable the nextjs-mf plugging I modified the next.config.js like below

/** @type {import('next').NextConfig} */
const NextFederationPlugin = require('@module-federation/nextjs-mf');

const remotes = isServer => {
  const location = isServer ? 'ssr' : 'chunks';
  return {
    'mfe-remote': `mfe-remote@http://localhost:3001/_next/static/${location}/remoteEntry.js`,
  };
};

const nextConfig = {
  experimental: {
    appDir: true,
  },
  webpack(config, options) {
    config.plugins.push(
      new NextFederationPlugin({
        name: 'mfe-remote',
        filename: 'static/chunks/remoteEntry.js',
        exposes: {
          './sub-app-page': './src/app/sub-app/page.js'
        },
        remotes: remotes(options.isServer),
        shared: {},
        extraOptions:{
          automaticAsyncBoundary: true
        }
      }),
    );

    return config;
  },
}

module.exports = nextConfig

The project just builds fine I just comment the webpack config but it failed with below error code when tried with above settings.

> Build error occurred
TypeError: Cannot read properties of undefined (reading 'loader')
    at useToEffectRaw (/Users/username/Documents/sample-work/next-turbo-repo/node_modules/next/dist/compiled/webpack/bundle5.js:28:1128287)
    at useToEffect (/Users/username/Documents/sample-work/next-turbo-repo/node_modules/next/dist/compiled/webpack/bundle5.js:28:1128126)
    at /Users/username/Documents/sample-work/next-turbo-repo/node_modules/next/dist/compiled/webpack/bundle5.js:28:1128882
    at Array.map (<anonymous>)
    at useToEffects (/Users/username/Documents/sample-work/next-turbo-repo/node_modules/next/dist/compiled/webpack/bundle5.js:28:1128841)
    at /Users/username/Documents/sample-work/next-turbo-repo/node_modules/next/dist/compiled/webpack/bundle5.js:28:1129041
    at Hook.eval [as call] (eval at create (/Users/username/Documents/sample-work/next-turbo-repo/node_modules/next/dist/compiled/webpack/bundle5.js:13:28549), <anonymous>:49:1)
    at RuleSetCompiler.compileRule (/Users/username/Documents/sample-work/next-turbo-repo/node_modules/next/dist/compiled/webpack/bundle5.js:28:1125129)
    at /Users/username/Documents/sample-work/next-turbo-repo/node_modules/next/dist/compiled/webpack/bundle5.js:28:1124933
    at Array.map (<anonymous>)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Steps to reproduce

  1. Clone repo
  2. Open the terminal and go to the cloned directory
  3. Install dependencies yarn
  4. Change the directory to the mfe-remote cd apps/mfe-remote/
  5. Finally run build command yarn build

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 20 (7 by maintainers)

Most upvoted comments

hey @ScriptedAlchemy Any news about support app dir and server components with MF thanks

Hey @ScriptedAlchemy, do you have an ETA on app directory support, or might be even support it at v6 as fix ?

I get the point about Next.js having a large community, but there are several technical and strategic factors that warrant attention:

  1. npm Stats: The stats you’re likely referring to are npm stats, which are not globally representative. In Asia, Modernjs sees about ~80k installs a week off the npm mirrors, could be better but marketing has not been done, shockingly. Install size is a poor metric, one I can easily manipulate. Technical merit or total market capitalization of the userbase is a better indicator. For instance, federations market capitalization by userbase is about 6 trillion dollars. Yet it has about half a million known domains using it. Value beats popularity

  2. Next.js and Monoliths: Next.js is the de-facto for monoliths. It’s not built for federation or MFE. Modernjs, on the other hand, is designed with these in mind and already powers products like TikTok and Lark, serving around 1/7th of the planet’s population, so far without a single production incident since implementation. Just us alone have over 6,000 frontends, and I believe we expect another 10k to be onboarded.

  3. Historical Context: I heard similar skepticism about federation 4-5 years ago, with DLLPlugin and Externals being cited as the de-facto solutions. Now, as I move onto building meta-frameworks and bigger ecosystems, I’m hearing the same tune. The similarities in the initial sentiments signals I’m on the right track.

  4. Scale: Modernjs serves as the backbone for apps that reach around 1/7th of the planet’s population. It can be distributed at scale, it a highly sophisticated system - straight up the best I’ve ever seen, particularly the “EdenX” iteration.

  5. codename EdenX: We’re using EdenX internally, which is tailored for federation-style architectures. It’s what I wanted Next.js to be but couldn’t make it due to its focus on monoliths, which it is exceptional at. Edenx is the next iteration of ModernJS, I plan to further focus it on meaningfully solving problems of scale. As you’ve shown, this is a saturated market to enter - if entering it it’s got to do something beyond just another rendition of the same things we already have.

  6. Resource Allocation: I haven’t found a meta-framework for MFE that I’m happy with. I’d rather allocate my time to Modernjs, which I know will provide a better user experience and business value.

  7. ByteDance Ecosystem: The ByteDance tech stack offers a rich ecosystem that can be leveraged for unique features. For instance, I could offer a “module engineering” solution where each Next.js page becomes a federated module. This would allow the host to be anything, reducing dependency on Next.js. Additionally, I’m considering moving module federation from the build phase to runtime, leveraging our powerful runtime SDK. The plan is to introduce require.federation.sdk, which would turn Next.js into an empty shell that only provides React, ReactDOM, and next/*, without partaking in dependency sharing.

  8. Next.js Plugin: It will still be maintained and is likely to get more stable as the unification process takes place.

  9. Bundlers and Flexibility: Other bundlers have limited APIs that make it hard to support federation. Next.js is also limited in how it can be customized beyond Vercel’s intended usage.

  10. Change in Approach: Given these limitations, we’re considering exporting our runtime as a library to bypass bundler restrictions/framework restrictions. This would reduce maintenance overhead compared to trying to replicate it in other build APIs, which will never be able to get beyond “tier 1” capabilities.

In summary, ModernJS and its next iteration, are designed to focus on challenges often encountered at scale, such as horizontal scaling, iteration speed, and cloud costs. Like vercel, we own both our meta-framework and an optional Rust compiler, Rspack, which is interoperable with Webpack. This setup allows us to innovate and contribute back to the broader Webpack ecosystem.

I’ll continue to maintain the Next.js plugin, recognizing the complexities of enterprise change management and my moral obligation to a userbase that includes industry giants like Microsoft, AWS, and Netflix. However, my focus is shifting to ModernJS. I plan to make it modular to resolve specific issues in Next.js federation, enabling the export of features like TypeScript syncing, full dynamic remotes, an SDK, fast refresh and HMR, and memory-efficient server-side federation with production (server) HMR.

The efficiency gain with ModernJS is notable: what took three years in Next.js took only three months in ModernJS. The meta-framework offers opt-in features like self-healing runtimes, built-in solutions for documentation, self-discovery, Storybook discovery, npm authoring, state management, and runtime lockfiles. These features are designed to integrate well if combined but are not coupled to a larger stack you have to buy into.

Given the extraordinary measures I’ve gone to for the Next.js federation plugin, where I’ve replaced a significant amount of Webpack’s internal runtime and even implemented my own chunk and dependency management over the module graph, I’ve contemplated more creative solutions. One such idea is to mock the Next.js API and have my plugin resolve to ModernJS internally, effectively replacing Next.js completely. This is not far-fetched considering l replaced large parts of Webpack’s internal runtime already, and drastically alter the build config.

My aim is to un-stall my ecosystem, which feels like it’s been held back due to the time and resources spent on Next.js.

The short term options for next are:

  • send a pr
  • fund the ask

Modernjs is fine and dandy… but I believe NextJS is the de-facto standard, with the biggest English speaking community and should be supported 😃

modernjs-vs-nextjs https://npmtrends.com/@modern-js/create-vs-create-next-app

@matsgm other than a single tweet from @rauchg there has not been anything that I’ve seen. In conversations with @leerob and @elsigh they both let me know that this is still work in progress.

My personal hope is that the Vercel team will work with the community to make what they are working on compatible with federation enhanced since it is bundler agnostic. It already works with webpack and with Rust bundler Rspack and will soon be working with Vite via Rolldown (also Rust) thanks to @yyx990803.

That would leave Turbopack the only major bundler without support of Module Federation which would be great to resolve.

Lastly, with that said 😃 the consulting wing of the federation org does have a request to investigate App Router. Which would push back into universe.

Between the federation org and byte infra. It we will solve RSC, but may require forking some RSC loader/plugins. But next has custom ones and it’s harder to replace

I get the point about Next.js having a large community, but there are several technical and strategic factors that warrant attention: (…)

Great insights. Appreciate it! Disclaimer; you work for ByteDance…?

However, an extensive user base is different from a big community.

My experience is that technology does not trump the community… even though the tech stack is superior.

That being said, I’m looking forward to following ModernJS, EdenX, and Nextjs-MF going forward 😃

Yes I did join recently. Mainly because I really liked the experience and wanted to bring it to a wider audience, as it’s solved hard problems that I’ve been stuck on for a long time. From what users open issues for, it’s addressed many.

Overall I’m positive for the broader ecosystem. Implementing it somewhere easy makes implementing elsewhere less hard

You can branch and try it. I’d suggest trying the async boundary PR branch if you want to pr me with a broken example

App directory is not currently supported. After the v7 rewrite, I’ll look into it. There were a few complications I needed to think about. But it should be solvable in a feature release on v7.1