@module-federation/nextjs-mf 8.7.3 → 8.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,380 +1,5 @@
1
- <div align="center">
2
- <!-- for version -->
3
- <img src="https://img.shields.io/npm/v/@module-federation/nextjs-mf" alt="version" >
4
- <img src="https://img.shields.io/npm/l/@module-federation/nextjs-mf.svg?" alt="license" >
5
- <!-- for downloads -->
6
- <img src="https://img.shields.io/npm/dt/@module-federation/nextjs-mf" alt="downloads">
7
- </div>
1
+ # Next.js Support is in maintenance mode
8
2
 
9
- # Module Federation For Next.js
3
+ Read about it [here](https://github.com/module-federation/core/issues/3153)
10
4
 
11
- This plugin enables Module Federation on Next.js
12
-
13
- ## Supports
14
-
15
- - next ^14 || ^13 || ^12
16
- - SSR included!
17
-
18
- I highly recommend referencing this application which takes advantage of the best capabilities:
19
- https://github.com/module-federation/module-federation-examples
20
-
21
- ## This project supports federated SSR
22
-
23
- # We are building a micro-frontend ecosystem!
24
-
25
- While NextFederationPlugin "works", Next.js is staunchly opposed to the technology and Next is very difficult to support.
26
-
27
- This plugin attempts to make the experience as seamless as possible, but it is not perfect.
28
-
29
- We are building a micro-frontend ecosystem that is much more powerful than Next.js, built to support micro-frontends from the ground up.
30
-
31
- **If Federation is a big enabler for your teams and projects, please consider using our ecosystem thats designed for it**
32
-
33
- | [Rspack](https://github.com/web-infra-dev/rspack) | <a href="https://github.com/web-infra-dev/rspack" target="blank"><img src="https://lf3-static.bytednsdoc.com/obj/eden-cn/zq-uylkvT/ljhwZthlaukjlkulzlp/Rspack-1850.png" width="400" /></a> |
34
- | :-----------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
35
- | [Modern.js](https://github.com/web-infra-dev/modern.js) | <a href="https://github.com/web-infra-dev/modern.js" target="blank"><img src="https://lf3-static.bytednsdoc.com/obj/eden-cn/zq-uylkvT/ljhwZthlaukjlkulzlp/Modern-0550.png" width="400" /></a> |
36
- | [Garfish](https://github.com/web-infra-dev/garfish) | <a href="https://github.com/web-infra-dev/garfish" target="blank"><img src="https://lf3-static.bytednsdoc.com/obj/eden-cn/zq-uylkvT/ljhwZthlaukjlkulzlp/Garfish-1630.png" width="400" /></a> |
37
- | [Oxc](https://github.com/web-infra-dev/oxc) | <a href="https://github.com/web-infra-dev/oxc" target="blank"><img src="https://lf3-static.bytednsdoc.com/obj/eden-cn/zq-uylkvT/ljhwZthlaukjlkulzlp/Oxc-0724.png" width="400" /></a> |
38
-
39
- ## Whats shared by default?
40
-
41
- Under the hood we share some next internals automatically
42
- You do not need to share these packages, sharing next internals yourself will cause errors.
43
-
44
- <details>
45
- <summary> See DEFAULT_SHARE_SCOPE:</summary>
46
-
47
- ```ts
48
- export const DEFAULT_SHARE_SCOPE: SharedObject = {
49
- 'next/dynamic': {
50
- requiredVersion: undefined,
51
- singleton: true,
52
- import: undefined,
53
- },
54
- 'next/head': {
55
- requiredVersion: undefined,
56
- singleton: true,
57
- import: undefined,
58
- },
59
- 'next/link': {
60
- requiredVersion: undefined,
61
- singleton: true,
62
- import: undefined,
63
- },
64
- 'next/router': {
65
- requiredVersion: false,
66
- singleton: true,
67
- import: undefined,
68
- },
69
- 'next/image': {
70
- requiredVersion: undefined,
71
- singleton: true,
72
- import: undefined,
73
- },
74
- 'next/script': {
75
- requiredVersion: undefined,
76
- singleton: true,
77
- import: undefined,
78
- },
79
- react: {
80
- singleton: true,
81
- requiredVersion: false,
82
- import: false,
83
- },
84
- 'react/': {
85
- singleton: true,
86
- requiredVersion: false,
87
- import: false,
88
- },
89
- 'react-dom/': {
90
- singleton: true,
91
- requiredVersion: false,
92
- import: false,
93
- },
94
- 'react-dom': {
95
- singleton: true,
96
- requiredVersion: false,
97
- import: false,
98
- },
99
- 'react/jsx-dev-runtime': {
100
- singleton: true,
101
- requiredVersion: false,
102
- },
103
- 'react/jsx-runtime': {
104
- singleton: true,
105
- requiredVersion: false,
106
- },
107
- 'styled-jsx': {
108
- singleton: true,
109
- import: undefined,
110
- version: require('styled-jsx/package.json').version,
111
- requiredVersion: '^' + require('styled-jsx/package.json').version,
112
- },
113
- 'styled-jsx/style': {
114
- singleton: true,
115
- import: false,
116
- version: require('styled-jsx/package.json').version,
117
- requiredVersion: '^' + require('styled-jsx/package.json').version,
118
- },
119
- 'styled-jsx/css': {
120
- singleton: true,
121
- import: undefined,
122
- version: require('styled-jsx/package.json').version,
123
- requiredVersion: '^' + require('styled-jsx/package.json').version,
124
- },
125
- };
126
- ```
127
-
128
- </details>
129
-
130
- ## Requirement
131
-
132
- I set `process.env.NEXT_PRIVATE_LOCAL_WEBPACK = 'true'` inside this plugin, but its best if its set in env or command line export.
133
-
134
- "Local Webpack" means you must have webpack installed as a dependency, and next will not use its bundled copy of webpack which cannot be used as i need access to all of webpack internals
135
-
136
- - `cross-env NEXT_PRIVATE_LOCAL_WEBPACK=true next dev` or `next build`
137
- - `npm install webpack`
138
-
139
- ## Usage
140
-
141
- ```js
142
- import React, { lazy } from 'react';
143
- const SampleComponent = lazy(() => import('next2/sampleComponent'));
144
- ```
145
-
146
- To avoid hydration errors, use `React.lazy` instead of `next/dynamic` for lazy loading federated components.
147
-
148
- #### See the implementation here: https://github.com/module-federation/module-federation-examples/tree/master/nextjs-v13/home/pages
149
-
150
- With async boundary installed at the page level. You can then do the following
151
-
152
- ```js
153
- const SomeHook = require('next2/someHook');
154
- import SomeComponent from 'next2/someComponent';
155
- ```
156
-
157
- ## Demo
158
-
159
- You can see it in action here: https://github.com/module-federation/module-federation-examples/tree/master/nextjs-ssr
160
-
161
- ## Options
162
-
163
- This plugin works exactly like ModuleFederationPlugin, use it as you'd normally.
164
- Note that we already share react and next stuff for you automatically.
165
-
166
- Also NextFederationPlugin has own optional argument `extraOptions` where you can unlock additional features of this plugin:
167
-
168
- ```js
169
- new NextFederationPlugin({
170
- name: '',
171
- filename: '',
172
- remotes: {},
173
- exposes: {},
174
- shared: {},
175
- extraOptions: {
176
- debug: boolean, // `false` by default
177
- exposePages: boolean, // `false` by default
178
- },
179
- });
180
- ```
181
-
182
- - `debug` – enables debug mode. It will print additional information about what is going on under the hood.
183
- - `exposePages` – exposes automatically all nextjs pages for you and theirs `./pages-map`.
184
-
185
- ## Demo
186
-
187
- You can see it in action here: https://github.com/module-federation/module-federation-examples/pull/2147
188
-
189
- ## Implementing the Plugin
190
-
191
- 1. Use `NextFederationPlugin` in your `next.config.js` of the app that you wish to expose modules from. We'll call this "next2".
192
-
193
- ```js
194
- // next.config.js
195
- // either from default
196
- const NextFederationPlugin = require('@module-federation/nextjs-mf');
197
-
198
- module.exports = {
199
- webpack(config, options) {
200
- const { isServer } = options;
201
- config.plugins.push(
202
- new NextFederationPlugin({
203
- name: 'next2',
204
- remotes: {
205
- next1: `next1@http://localhost:3001/_next/static/${isServer ? 'ssr' : 'chunks'}/remoteEntry.js`,
206
- },
207
- filename: 'static/chunks/remoteEntry.js',
208
- exposes: {
209
- './title': './components/exposedTitle.js',
210
- './checkout': './pages/checkout',
211
- },
212
- shared: {
213
- // whatever else
214
- },
215
- }),
216
- );
217
-
218
- return config;
219
- },
220
- };
221
- ```
222
-
223
- ```js
224
- // next.config.js
225
-
226
- const NextFederationPlugin = require('@module-federation/nextjs-mf');
227
-
228
- module.exports = {
229
- webpack(config, options) {
230
- const { isServer } = options;
231
- config.plugins.push(
232
- new NextFederationPlugin({
233
- name: 'next1',
234
- remotes: {
235
- next2: `next2@http://localhost:3000/_next/static/${isServer ? 'ssr' : 'chunks'}/remoteEntry.js`,
236
- },
237
- }),
238
- );
239
-
240
- return config;
241
- },
242
- };
243
- ```
244
-
245
- 4. Use react.lazy, low level api, or require/import from to import remotes.
246
-
247
- ```js
248
- import React, { lazy } from 'react';
249
-
250
- const SampleComponent = lazy(() =>
251
- window.next2.get('./sampleComponent').then((factory) => {
252
- return { default: factory() };
253
- }),
254
- );
255
-
256
- // or
257
-
258
- const SampleComponent = lazy(() => import('next2/sampleComponent'));
259
-
260
- //or
261
-
262
- import Sample from 'next2/sampleComponent';
263
- ```
264
-
265
- ## RuntimePlugins
266
-
267
- To provide extensibility and "middleware" for federation, you can refer to `@module-federation/runtime`
268
-
269
- ```js
270
- // next.config.js
271
- new NextFederationPlugin({
272
- runtimePlugins: [require.resolve('./path/to/myRuntimePlugin.js')],
273
- });
274
- ```
275
-
276
- ## Utilities
277
-
278
- Ive added a util for dynamic chunk loading, in the event you need to load remote containers dynamically.
279
-
280
- ```js
281
- import { loadRemote, init } from '@module-federation/runtime';
282
- // if i have remotes in my federation plugin, i can pass the name of the remote
283
- loadRemote('home/exposedModule');
284
- // if i want to load a custom remote not known at build time.
285
- init({
286
- name: 'hostname',
287
- remotes: [
288
- {
289
- name: 'home',
290
- entry: 'http://somthing.com/remoteEntry.js',
291
- },
292
- ],
293
- force: true, // may be needed to sideload remotes after the fact.
294
- });
295
- loadRemote('home/exposedModule');
296
- ```
297
-
298
- **revalidate**
299
-
300
- ### Hot Reloading with `revalidate` in Production Environments
301
-
302
- In production environments, ensuring that your server can dynamically reload and update without requiring a full restart is crucial for maintaining uptime and providing the latest features to your users without disruption. The `revalidate` utility from `@module-federation/nextjs-mf/utils` facilitates this by enabling hot reloading of the node server (not the client). This section outlines two implementations for integrating `revalidate` into your Next.js application to leverage hot reloading capabilities.
303
-
304
- #### Preferred Implementation: Blocking Updates Before Rendering
305
-
306
- This implementation is recommended for most use cases as it helps avoid hydration errors by ensuring that the server and client are always in sync. By blocking and checking for updates before rendering, you can guarantee that your application is always up-to-date without negatively impacting the user experience.
307
-
308
- **How it Works:**
309
-
310
- - **Before rendering the page**, the server checks if there are any updates available.
311
- - **If updates are available**, it proceeds with Hot Module Replacement (HMR) before responding to the client request.
312
- - **This method ensures** that all users receive the latest version of the application without encountering inconsistencies between the server-rendered and client-rendered content.
313
-
314
- **Implementation Example:**
315
-
316
- ```js
317
- // __document.js
318
-
319
- import { revalidate } from '@module-federation/nextjs-mf/utils';
320
- import Document, { Html, Head, Main, NextScript } from 'next/document';
321
-
322
- class MyDocument extends Document {
323
- static async getInitialProps(ctx) {
324
- if (ctx?.pathname && !ctx?.pathname?.endsWith('_error')) {
325
- await revalidate().then((shouldUpdate) => {
326
- if (shouldUpdate) {
327
- console.log('Hot Module Replacement (HMR) activated', shouldUpdate);
328
- }
329
- });
330
- }
331
-
332
- const initialProps = await Document.getInitialProps(ctx);
333
- return initialProps;
334
- }
335
-
336
- render() {
337
- return (
338
- <Html>
339
- <Head />
340
- <body>
341
- <Main />
342
- <NextScript />
343
- </body>
344
- </Html>
345
- );
346
- }
347
- }
348
- ```
349
-
350
- #### Stale Method: Post-Response Update Checks
351
-
352
- While not recommended due to the potential for hydration errors, this method involves listening for the 'finish' event on the response object and then checking for updates. This could be useful in specific scenarios where updates can be applied less frequently or where immediate consistency between server and client is not as critical.
353
-
354
- **How it Works:**
355
-
356
- - **After responding to the client**, the server listens for the 'finish' event on the response object.
357
- - **Once the response has been sent**, it checks for updates.
358
- - **If updates are found**, it logs or acts upon these updates, although the updates will only apply to subsequent requests.
359
-
360
- **Implementation Example:**
361
-
362
- ```js
363
- // Included in the `getInitialProps` method as shown in the preferred implementation
364
- ctx?.res?.on('finish', () => {
365
- revalidate().then((shouldUpdate) => {
366
- console.log('Response sent, checking for updates:', shouldUpdate);
367
- });
368
- });
369
- ```
370
-
371
- ## For Express.js
372
-
373
- Hot reloading Express.js required additional steps: https://github.com/module-federation/core/blob/main/packages/node/README.md
374
-
375
- ## Contact
376
-
377
- If you have any questions or need to report a bug
378
- <a href="https://twitter.com/ScriptedAlchemy"> Reach me on Twitter @ScriptedAlchemy</a>
379
-
380
- Or join this discussion thread: https://github.com/module-federation/module-federation-examples/discussions/978
5
+ Plugin Documentation: [here](https://module-federation.io/practice/frameworks/next/index.html)
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/nextjs-mf",
3
- "version": "8.7.3",
3
+ "version": "8.7.5",
4
4
  "license": "MIT",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -15,6 +15,9 @@
15
15
  "dist/",
16
16
  "README.md"
17
17
  ],
18
+ "scripts": {
19
+ "postinstall": "echo \"Deprecation Notice: We intend to deprecate 'nextjs-mf'. Please see https://github.com/module-federation/core/issues/3153 for more details.\""
20
+ },
18
21
  "exports": {
19
22
  ".": "./dist/src/index.js",
20
23
  "./utils": "./dist/utils/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/nextjs-mf",
3
- "version": "8.7.3",
3
+ "version": "8.7.5",
4
4
  "license": "MIT",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -35,11 +35,11 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "fast-glob": "^3.2.11",
38
- "@module-federation/runtime": "0.6.15",
39
- "@module-federation/sdk": "0.6.15",
40
- "@module-federation/enhanced": "0.6.15",
41
- "@module-federation/node": "2.6.3",
42
- "@module-federation/webpack-bundler-runtime": "0.6.15"
38
+ "@module-federation/runtime": "0.7.0",
39
+ "@module-federation/sdk": "0.7.0",
40
+ "@module-federation/enhanced": "0.7.0",
41
+ "@module-federation/node": "2.6.5",
42
+ "@module-federation/webpack-bundler-runtime": "0.7.0"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "webpack": "^5.40.0",
@@ -52,5 +52,8 @@
52
52
  "styled-jsx": {
53
53
  "optional": true
54
54
  }
55
+ },
56
+ "scripts": {
57
+ "postinstall": "echo \"Deprecation Notice: We intend to deprecate 'nextjs-mf'. Please see https://github.com/module-federation/core/issues/3153 for more details.\""
55
58
  }
56
59
  }