From 6ab8e3f5611249f3463d48950919db59f6765cb0 Mon Sep 17 00:00:00 2001 From: Zack Jackson Date: Mon, 25 Jan 2021 17:50:39 -0800 Subject: [PATCH] update plugin --- README.md | 150 ++++++++++++++++++++++++++++++++------ bin/nextjs-mf.js | 102 ++++++++++++++++++++++++++ example/README.md | 12 --- example/package.json | 25 ------- example/public/index.html | 5 -- example/src/App.js | 12 --- example/src/Button.js | 5 -- example/src/bootstrap.js | 5 -- example/src/index.js | 1 - example/webpack.config.js | 49 ------------- index.js | 8 +- package.json | 20 +++-- patchSharing.js | 17 +++++ react-dom.js | 11 +++ react.js | 11 +++ withModuleFederation.js | 62 ++++++++++++++++ 16 files changed, 351 insertions(+), 144 deletions(-) create mode 100755 bin/nextjs-mf.js delete mode 100644 example/README.md delete mode 100644 example/package.json delete mode 100644 example/public/index.html delete mode 100644 example/src/App.js delete mode 100644 example/src/Button.js delete mode 100644 example/src/bootstrap.js delete mode 100644 example/src/index.js delete mode 100644 example/webpack.config.js create mode 100644 patchSharing.js create mode 100644 react-dom.js create mode 100644 react.js create mode 100644 withModuleFederation.js diff --git a/README.md b/README.md index 5e5d2f7..836278c 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,141 @@ -# Module Federation Runtime Chunk Merging +# Module Federation For Next.js -This plugin makes module federation work as expected when using -`runtimeChunk:"single"` as an optimization tactic. +This plugin enables Module Federation on Next.js -## Usage +This is a workaround to hard limitations caused by Next.js being synchronous. + +I am working on an update to Webpack Core which will circumvent projects with older architecture (like Next.js). + +This is a stable and viable workaround to leverage Module Federation [until this issue is resolved](https://github.com/webpack/webpack/issues/11811). + +### Supports + +- next ^9.5.6 +- SSG +- SSR + +**Once I PR webpack, this workaround will no longer be required.** + +# Check out our book + +| Practical Module Federation Book | We will be actively updating this book over the next year as we learn more about best practices and what issues people are running into with Module Federation, as well as with every release of Webpack as it moves towards a release candidate and release. So with your one purchase you are buying a whole year of updates. | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | + +#### Demo + +You can see it in action here: https://github.com/module-federation/module-federation-examples/tree/master/nextjs + +## How to use on a fresh nextjs app + +```sh +yarn global add @module-federation/nextjs-mf +``` + +Run this inside of a fresh nextjs install. + +```sh +nextjs-mf upgrade -p 3001 +``` + +## How to use on an existing app + +1. Use `withModuleFederation` in your `next.config.js` ```js -plugins: [ - new ModuleFedSingleRuntimePlugin(), - new ModuleFederationPlugin({ - name: "app2", - filename: "remoteEntry.js", +// next.config.js +const { withModuleFederation } = require("@module-federation/nextjs-mf"); +const path = require("path"); + +module.exports = { + webpack: (config, options) => { + const { buildId, dev, isServer, defaultLoaders, webpack } = options; + const mfConf = { + mergeRuntime: true, //this is experimental, read below + name: "next2", + library: { type: config.output.libraryTarget, name: "next2" }, + filename: "static/runtime/remoteEntry.js", + remotes: { + // For SSR, resolve to disk path (or you can use code streaming if you have access) + next1: isServer + ? path.resolve( + __dirname, + "../next1/.next/server/static/runtime/remoteEntry.js" + ) + : "next1", // for client, treat it as a global + }, exposes: { - "./Button": "./src/Button", + "./nav": "./components/nav", }, - shared: { react: { singleton: true }, "react-dom": { singleton: true } }, - }), - new HtmlWebpackPlugin({ - template: "./public/index.html", - }), - ] + shared: ["lodash"], + }; + // Configures ModuleFederation and other Webpack properties + withModuleFederation(config, options, mfConf); + + return config; + }, +}; ``` -# Example +2. Add the `patchSharing` to `_document.js`. This will solve the react sharing issue. -Can be found in the `/example` directory +```jsx +import Document, { Html, Head, Main, NextScript } from "next/document"; +import { patchSharing } from "@module-federation/nextjs-mf"; +class MyDocument extends Document { + static async getInitialProps(ctx) { + const initialProps = await Document.getInitialProps(ctx); + return { ...initialProps }; + } + render() { + return ( + + {patchSharing()} +