@vercel/microfrontends 2.1.2 → 2.2.0

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +4 -0
  3. package/dist/bin/cli.cjs +125 -89
  4. package/dist/config.d.ts +2 -2
  5. package/dist/experimental/sveltekit.cjs +97 -62
  6. package/dist/experimental/sveltekit.cjs.map +1 -1
  7. package/dist/experimental/sveltekit.d.ts +6 -0
  8. package/dist/experimental/sveltekit.js +97 -62
  9. package/dist/experimental/sveltekit.js.map +1 -1
  10. package/dist/experimental/vite.cjs +96 -65
  11. package/dist/experimental/vite.cjs.map +1 -1
  12. package/dist/experimental/vite.js +96 -65
  13. package/dist/experimental/vite.js.map +1 -1
  14. package/dist/microfrontends/server.cjs +92 -59
  15. package/dist/microfrontends/server.cjs.map +1 -1
  16. package/dist/microfrontends/server.d.ts +2 -2
  17. package/dist/microfrontends/server.js +92 -59
  18. package/dist/microfrontends/server.js.map +1 -1
  19. package/dist/microfrontends/utils.cjs +3 -3
  20. package/dist/microfrontends/utils.cjs.map +1 -1
  21. package/dist/microfrontends/utils.d.ts +1 -1
  22. package/dist/microfrontends/utils.js +3 -3
  23. package/dist/microfrontends/utils.js.map +1 -1
  24. package/dist/next/config.cjs +133 -115
  25. package/dist/next/config.cjs.map +1 -1
  26. package/dist/next/config.d.ts +11 -1
  27. package/dist/next/config.js +133 -115
  28. package/dist/next/config.js.map +1 -1
  29. package/dist/next/middleware.cjs +35 -17
  30. package/dist/next/middleware.cjs.map +1 -1
  31. package/dist/next/middleware.js +35 -17
  32. package/dist/next/middleware.js.map +1 -1
  33. package/dist/next/testing.d.ts +2 -2
  34. package/dist/overrides.d.ts +3 -3
  35. package/dist/schema.d.ts +2 -2
  36. package/dist/{types-88602303.d.ts → types-b9ea41b2.d.ts} +1 -1
  37. package/dist/{types-e7523e61.d.ts → types-dcd8b17a.d.ts} +71 -24
  38. package/dist/utils/mfe-port.cjs +92 -59
  39. package/dist/utils/mfe-port.cjs.map +1 -1
  40. package/dist/utils/mfe-port.js +92 -59
  41. package/dist/utils/mfe-port.js.map +1 -1
  42. package/dist/validation.cjs +47 -38
  43. package/dist/validation.cjs.map +1 -1
  44. package/dist/validation.d.ts +1 -1
  45. package/dist/validation.js +47 -38
  46. package/dist/validation.js.map +1 -1
  47. package/package.json +1 -1
  48. package/schema/schema.json +47 -38
@@ -12,7 +12,11 @@ interface WithMicrofrontendsOptions {
12
12
  * if it differs from the project name.
13
13
  */
14
14
  appName?: string;
15
- isProduction?: () => boolean;
15
+ /**
16
+ * @deprecated this is a no-op, and will be removed in a future version.
17
+ * It is not necessary to specify this option.
18
+ */
19
+ isProduction?: boolean;
16
20
  debug?: boolean;
17
21
  skipTransforms?: TransformKeys[];
18
22
  /**
@@ -21,6 +25,12 @@ interface WithMicrofrontendsOptions {
21
25
  * enabled when necessary.
22
26
  */
23
27
  supportPagesRouter?: boolean;
28
+ /**
29
+ * @deprecated Use VC_MICROFRONTENDS_CONFIG_FILE_NAME instead. This option is
30
+ * deprecated and will be removed in a future release. The env var enables the
31
+ * vercel build to also read the custom config file / path.
32
+ * @see https://vercel.com/docs/microfrontends/configuration#file-naming
33
+ */
24
34
  configPath?: string;
25
35
  }
26
36
 
@@ -6,12 +6,38 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
6
6
  throw new Error('Dynamic require of "' + x + '" is not supported');
7
7
  });
8
8
 
9
+ // src/bin/local-proxy-is-running.ts
10
+ function localProxyIsRunning() {
11
+ return process.env.TURBO_TASK_HAS_MFE_PROXY === "true";
12
+ }
13
+
14
+ // src/bin/logger.ts
15
+ function debug(...args) {
16
+ if (process.env.MFE_DEBUG) {
17
+ console.log(...args);
18
+ }
19
+ }
20
+ function info(...args) {
21
+ console.log(...args);
22
+ }
23
+ function warn(...args) {
24
+ console.warn(...args);
25
+ }
26
+ function error(...args) {
27
+ console.error(...args);
28
+ }
29
+ var logger = {
30
+ debug,
31
+ info,
32
+ warn,
33
+ error
34
+ };
35
+
9
36
  // src/bin/check-proxy.ts
10
37
  function displayLocalProxyInfo(port) {
11
- const { MFE_PROXY_MESSAGE_PRINTED, TURBO_TASK_HAS_MFE_PROXY } = process.env;
12
- if (TURBO_TASK_HAS_MFE_PROXY === "true" && MFE_PROXY_MESSAGE_PRINTED !== "true") {
38
+ if (localProxyIsRunning() && process.env.MFE_PROXY_MESSAGE_PRINTED !== "true") {
13
39
  process.env.MFE_PROXY_MESSAGE_PRINTED = "true";
14
- console.log(`Microfrontends Proxy running on http://localhost:${port}`);
40
+ logger.info(`Microfrontends Proxy running on http://localhost:${port}`);
15
41
  }
16
42
  }
17
43
 
@@ -206,8 +232,8 @@ import fg from "fast-glob";
206
232
 
207
233
  // src/config/microfrontends/utils/get-config-file-name.ts
208
234
  var DEFAULT_CONFIGURATION_FILENAMES = [
209
- "microfrontends.jsonc",
210
- "microfrontends.json"
235
+ "microfrontends.json",
236
+ "microfrontends.jsonc"
211
237
  ];
212
238
  function getPossibleConfigurationFilenames({
213
239
  customConfigFilename
@@ -215,7 +241,7 @@ function getPossibleConfigurationFilenames({
215
241
  if (customConfigFilename) {
216
242
  if (!customConfigFilename.endsWith(".json") && !customConfigFilename.endsWith(".jsonc")) {
217
243
  throw new Error(
218
- `The VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable must end with '.json' or '.jsonc'. Received: ${customConfigFilename}`
244
+ `Found VC_MICROFRONTENDS_CONFIG_FILE_NAME but the name is invalid. Received: ${customConfigFilename}. The file name must end with '.json' or '.jsonc'. It's also possible for the env var to include the path, eg microfrontends-dev.json or /path/to/microfrontends-dev.json.`
219
245
  );
220
246
  }
221
247
  return Array.from(
@@ -263,7 +289,7 @@ function findPackageWithMicrofrontendsConfig({
263
289
  }
264
290
  }
265
291
  }
266
- } catch (error) {
292
+ } catch (error2) {
267
293
  }
268
294
  }
269
295
  if (matchingPaths.length > 1) {
@@ -299,9 +325,9 @@ If you suspect this is thrown in error, please reach out to the Vercel team.`,
299
325
  }
300
326
  const [packageJsonPath] = matchingPaths;
301
327
  return dirname(packageJsonPath);
302
- } catch (error) {
303
- if (error instanceof MicrofrontendError) {
304
- throw error;
328
+ } catch (error2) {
329
+ if (error2 instanceof MicrofrontendError) {
330
+ throw error2;
305
331
  }
306
332
  return null;
307
333
  }
@@ -346,8 +372,8 @@ function isMonorepo({
346
372
  fs2.readFileSync(packageJsonPath, "utf-8")
347
373
  );
348
374
  return packageJson.workspaces !== void 0;
349
- } catch (error) {
350
- console.error("Error determining if repository is a monorepo", error);
375
+ } catch (error2) {
376
+ logger.error("Error determining if repository is a monorepo", error2);
351
377
  return false;
352
378
  }
353
379
  }
@@ -1141,38 +1167,28 @@ var schema_default = {
1141
1167
  type: "object",
1142
1168
  properties: {
1143
1169
  $schema: {
1144
- type: "string"
1170
+ type: "string",
1171
+ description: "See https://openapi.vercel.sh/microfrontends.json."
1145
1172
  },
1146
1173
  version: {
1147
1174
  type: "string",
1148
- const: "1"
1149
- },
1150
- options: {
1151
- $ref: "#/definitions/Options"
1175
+ const: "1",
1176
+ description: "The version of the microfrontends config schema."
1152
1177
  },
1153
1178
  applications: {
1154
1179
  $ref: "#/definitions/ApplicationRouting",
1155
- description: "Mapping of application names to the routes that they host. Only needs to be defined in the application that owns the primary microfrontend domain"
1180
+ description: "Mapping of Vercel project names to their microfrontend configurations."
1181
+ },
1182
+ options: {
1183
+ $ref: "#/definitions/Options",
1184
+ description: "Optional configuration options for the microfrontend."
1156
1185
  }
1157
1186
  },
1158
1187
  required: [
1159
1188
  "applications"
1160
1189
  ],
1161
- additionalProperties: false
1162
- },
1163
- Options: {
1164
- type: "object",
1165
- properties: {
1166
- disableOverrides: {
1167
- type: "boolean",
1168
- description: "If you want to disable the overrides for the site. For example, if you are managing rewrites between applications externally, you may wish to disable the overrides on the toolbar as they will have no effect."
1169
- },
1170
- localProxyPort: {
1171
- type: "number",
1172
- description: "The port number used by the local proxy server.\n\nThe default is `3024`."
1173
- }
1174
- },
1175
- additionalProperties: false
1190
+ additionalProperties: false,
1191
+ description: "The microfrontends configuration schema. See https://vercel.com/docs/microfrontends/configuration."
1176
1192
  },
1177
1193
  ApplicationRouting: {
1178
1194
  type: "object",
@@ -1180,8 +1196,9 @@ var schema_default = {
1180
1196
  $ref: "#/definitions/Application"
1181
1197
  },
1182
1198
  propertyNames: {
1183
- description: "The unique identifier for a Microfrontend Application.\n\nMust match the Vercel project name.\n\nNote: If this name does not also match the name used to run the application, (e.g. the `name` from the `package.json`), then the `packageName` field should be set."
1184
- }
1199
+ description: "The Vercel project name of the microfrontend application.\n\nNote: If this name does not also match the name `name` from the `package.json`, set `packageName` with the name used in `package.json`.\n\nSee https://vercel.com/docs/microfrontends/configuration#application-naming."
1200
+ },
1201
+ description: "Mapping of Vercel project names to their microfrontend configurations."
1185
1202
  },
1186
1203
  Application: {
1187
1204
  anyOf: [
@@ -1191,14 +1208,15 @@ var schema_default = {
1191
1208
  {
1192
1209
  $ref: "#/definitions/ChildApplication"
1193
1210
  }
1194
- ]
1211
+ ],
1212
+ description: "The configuration for a microfrontend application. There must always be one default application."
1195
1213
  },
1196
1214
  DefaultApplication: {
1197
1215
  type: "object",
1198
1216
  properties: {
1199
1217
  packageName: {
1200
1218
  type: "string",
1201
- description: "The name used to run the application, e.g. the `name` field in the `package.json`.\n\nThis is used by the local proxy to map the application config to the locally running app.\n\nThis is only necessary when the application name does not match the `name` used in `package.json`."
1219
+ description: "The name used to run the application, e.g. the `name` field in the `package.json`.\n\nThis is used by the local proxy to map the application config to the locally running app.\n\nThis is only necessary when the application name does not match the `name` used in `package.json`.\n\nSee https://vercel.com/docs/microfrontends/configuration#application-naming."
1202
1220
  },
1203
1221
  development: {
1204
1222
  $ref: "#/definitions/DefaultDevelopment",
@@ -1218,15 +1236,15 @@ var schema_default = {
1218
1236
  "number",
1219
1237
  "string"
1220
1238
  ],
1221
- description: "A local port number or host string that this application runs on when it is running locally. If passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTP. If omitted, the port defaults to a unique, but stable (based on the application name) number.\n\nExamples of valid values:\n- 8080\n- my.localhost.me\n- my.localhost.me:8080\n- https://my.localhost.me\n- https://my.localhost.me:8080"
1239
+ description: "A local port number or host that this application runs on when it is running locally. If passing a string, include the protocol (optional), host (required) and port (optional).\n\nExamples of valid values: 8080, my.localhost.me, my.localhost.me:8080, https://my.localhost.me, https://my.localhost.me:8080.\n\nThe default value is http://localhost:<port> where port is a stable, unique port number (based on the application name).\n\nSee https://vercel.com/docs/microfrontends/local-development."
1222
1240
  },
1223
1241
  task: {
1224
1242
  type: "string",
1225
- description: "Optional task to run when starting the development server. Should reference a script in the package.json of the application."
1243
+ description: 'The task to run when starting the development server. Should reference a script in the package.json of the application.\n\nThe default value is "dev".\n\nSee https://vercel.com/docs/microfrontends/local-development.'
1226
1244
  },
1227
1245
  fallback: {
1228
1246
  type: "string",
1229
- description: "Fallback for local development, could point to any environment. This is required for the default app. This value is used as the fallback for child apps as well if they do not have a fallback.\n\nIf passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTPS. If omitted, the port defaults to `80` for HTTP and `443` for HTTPS."
1247
+ description: "Fallback for local development, could point to any environment. This is required for the default app. This value is used as the fallback for child apps as well if they do not have a fallback.\n\nIf passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTPS. If omitted, the port defaults to `80` for HTTP and `443` for HTTPS.\n\nSee https://vercel.com/docs/microfrontends/local-development."
1230
1248
  }
1231
1249
  },
1232
1250
  required: [
@@ -1239,7 +1257,7 @@ var schema_default = {
1239
1257
  properties: {
1240
1258
  packageName: {
1241
1259
  type: "string",
1242
- description: "The name used to run the application, e.g. the `name` field in the `package.json`.\n\nThis is used by the local proxy to map the application config to the locally running app.\n\nThis is only necessary when the application name does not match the `name` used in `package.json`."
1260
+ description: "The name used to run the application, e.g. the `name` field in the `package.json`.\n\nThis is used by the local proxy to map the application config to the locally running app.\n\nThis is only necessary when the application name does not match the `name` used in `package.json`.\n\nSee https://vercel.com/docs/microfrontends/configuration#application-naming."
1243
1261
  },
1244
1262
  development: {
1245
1263
  $ref: "#/definitions/ChildDevelopment",
@@ -1247,11 +1265,11 @@ var schema_default = {
1247
1265
  },
1248
1266
  routing: {
1249
1267
  $ref: "#/definitions/Routing",
1250
- description: "Groups of path expressions that are routed to this application."
1268
+ description: "Groups of path expressions that are routed to this application.\n\nSee https://vercel.com/docs/microfrontends/path-routing."
1251
1269
  },
1252
1270
  assetPrefix: {
1253
1271
  type: "string",
1254
- description: "The name of the asset prefix to use instead of the auto-generated name.\n\nThe asset prefix is used to prefix all paths to static assets, such as JS, CSS, or images that are served by a specific application. It is necessary to ensure there are no conflicts with other applications on the same domain.\n\nAn auto-generated asset prefix of the form `vc-ap-<hash>` is used when this field is not provided.\n\nWhen this field is provided, `/${assetPrefix}/:path*` must also be added to the list of paths in the `routing` field. Changing the asset prefix after a microfrontend application has already been deployed is not a forwards and backwards compatible change, and the asset prefix should be added to the `routing` field and deployed before setting the `assetPrefix` field."
1272
+ description: "The name of the asset prefix to use instead of the auto-generated name.\n\nThe asset prefix is used to prefix all paths to static assets, such as JS, CSS, or images that are served by a specific application. It is necessary to ensure there are no conflicts with other applications on the same domain.\n\nAn auto-generated asset prefix of the form `vc-ap-<hash>` is used when this field is not provided.\n\nWhen this field is provided, `/${assetPrefix}/:path*` must also be added to the list of paths in the `routing` field. Changing the asset prefix after a microfrontend application has already been deployed is not a forwards and backwards compatible change, and the asset prefix should be added to the `routing` field and deployed before setting the `assetPrefix` field.\n\nThe default value is the auto-generated asset prefix of the form `vc-ap-<hash>`.\n\nSee https://vercel.com/docs/microfrontends/path-routing#asset-prefix."
1255
1273
  }
1256
1274
  },
1257
1275
  required: [
@@ -1267,15 +1285,15 @@ var schema_default = {
1267
1285
  "number",
1268
1286
  "string"
1269
1287
  ],
1270
- description: "A local port number or host string that this application runs on when it is running locally. If passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTP. If omitted, the port defaults to a unique, but stable (based on the application name) number.\n\nExamples of valid values:\n- 8080\n- my.localhost.me\n- my.localhost.me:8080\n- https://my.localhost.me\n- https://my.localhost.me:8080"
1288
+ description: "A local port number or host that this application runs on when it is running locally. If passing a string, include the protocol (optional), host (required) and port (optional).\n\nExamples of valid values: 8080, my.localhost.me, my.localhost.me:8080, https://my.localhost.me, https://my.localhost.me:8080.\n\nThe default value is http://localhost:<port> where port is a stable, unique port number (based on the application name).\n\nSee https://vercel.com/docs/microfrontends/local-development."
1271
1289
  },
1272
1290
  task: {
1273
1291
  type: "string",
1274
- description: "Optional task to run when starting the development server. Should reference a script in the package.json of the application."
1292
+ description: 'The task to run when starting the development server. Should reference a script in the package.json of the application.\n\nThe default value is "dev".\n\nSee https://vercel.com/docs/microfrontends/local-development.'
1275
1293
  },
1276
1294
  fallback: {
1277
1295
  type: "string",
1278
- description: "Fallback for local development, could point to any environment. This is optional for child apps. If not provided, the fallback of the default app will be used.\n\nIf passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTPS. If omitted, the port defaults to `80` for HTTP and `443` for HTTPS."
1296
+ description: "Fallback for local development, could point to any environment. If not provided for child apps, the fallback of the default app will be used.\n\nIf passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTPS. If omitted, the port defaults to `80` for HTTP and `443` for HTTPS.\n\nSee https://vercel.com/docs/microfrontends/local-development."
1279
1297
  }
1280
1298
  },
1281
1299
  additionalProperties: false
@@ -1284,29 +1302,46 @@ var schema_default = {
1284
1302
  type: "array",
1285
1303
  items: {
1286
1304
  $ref: "#/definitions/PathGroup"
1287
- }
1305
+ },
1306
+ description: "A list of path groups that are routed to this application."
1288
1307
  },
1289
1308
  PathGroup: {
1290
1309
  type: "object",
1291
1310
  properties: {
1292
1311
  group: {
1293
1312
  type: "string",
1294
- description: "Optional group name for the paths"
1313
+ description: "Group name for the paths."
1295
1314
  },
1296
1315
  flag: {
1297
1316
  type: "string",
1298
- description: "flag name that can be used to enable/disable all paths in the group"
1317
+ description: "The name of the feature flag that controls routing for this group of paths. See https://vercel.com/docs/microfrontends/path-routing#routing-changes-safely-with-flags."
1299
1318
  },
1300
1319
  paths: {
1301
1320
  type: "array",
1302
1321
  items: {
1303
1322
  type: "string"
1304
- }
1323
+ },
1324
+ description: "A list of path expressions that are routed to this application. See https://vercel.com/docs/microfrontends/path-routing#supported-path-expressions."
1305
1325
  }
1306
1326
  },
1307
1327
  required: [
1308
1328
  "paths"
1309
1329
  ],
1330
+ additionalProperties: false,
1331
+ description: "A group of paths that is routed to this application."
1332
+ },
1333
+ Options: {
1334
+ type: "object",
1335
+ properties: {
1336
+ disableOverrides: {
1337
+ type: "boolean",
1338
+ description: "If you want to disable the overrides for the site. For example, if you are managing rewrites between applications externally, you may wish to disable the overrides on the toolbar as they will have no effect.\n\nSee https://vercel.com/docs/microfrontends/managing-microfrontends/vercel-toolbar#routing-overrides."
1339
+ },
1340
+ localProxyPort: {
1341
+ type: "number",
1342
+ description: "The port number used by the local proxy server.\n\nThe default value is 3024.\n\nSee https://vercel.com/docs/microfrontends/local-development."
1343
+ }
1344
+ },
1310
1345
  additionalProperties: false
1311
1346
  }
1312
1347
  }
@@ -1325,19 +1360,19 @@ function formatAjvErrors(errors) {
1325
1360
  return [];
1326
1361
  }
1327
1362
  const errorMessages = [];
1328
- for (const error of errors) {
1329
- if (error.instancePath === "" && (error.keyword === "anyOf" || error.keyword === "required" && error.params.missingProperty === "partOf")) {
1363
+ for (const error2 of errors) {
1364
+ if (error2.instancePath === "" && (error2.keyword === "anyOf" || error2.keyword === "required" && error2.params.missingProperty === "partOf")) {
1330
1365
  continue;
1331
1366
  }
1332
- const instancePath = error.instancePath.slice(1);
1367
+ const instancePath = error2.instancePath.slice(1);
1333
1368
  const formattedInstancePath = instancePath === "" ? "at the root" : `in field ${instancePath}`;
1334
- if (error.keyword === "required" && error.params.missingProperty === "routing" && instancePath.split("/").length === 2) {
1369
+ if (error2.keyword === "required" && error2.params.missingProperty === "routing" && instancePath.split("/").length === 2) {
1335
1370
  errorMessages.push(
1336
1371
  `Unable to infer if ${instancePath} is the default app or a child app. This usually means that there is another error in the configuration.`
1337
1372
  );
1338
- } else if (error.keyword === "anyOf" && instancePath.split("/").length > 2) {
1373
+ } else if (error2.keyword === "anyOf" && instancePath.split("/").length > 2) {
1339
1374
  const anyOfErrors = errors.filter(
1340
- (e) => e.instancePath === error.instancePath && e.keyword !== "anyOf"
1375
+ (e) => e.instancePath === error2.instancePath && e.keyword !== "anyOf"
1341
1376
  );
1342
1377
  if (anyOfErrors.every((e) => e.keyword === "type")) {
1343
1378
  const allowedTypes = LIST_FORMATTER2.format(
@@ -1353,13 +1388,13 @@ function formatAjvErrors(errors) {
1353
1388
  `Invalid field for ${instancePath}. Possible error messages are ${LIST_FORMATTER2.format(anyOfErrors.map((e) => e.message ?? ""))}`
1354
1389
  );
1355
1390
  }
1356
- } else if (error.keyword === "additionalProperties" && !(error.params.additionalProperty === "routing" && instancePath.split("/").length === 2)) {
1391
+ } else if (error2.keyword === "additionalProperties" && !(error2.params.additionalProperty === "routing" && instancePath.split("/").length === 2)) {
1357
1392
  errorMessages.push(
1358
- `Property '${error.params.additionalProperty}' is not allowed ${formattedInstancePath}`
1393
+ `Property '${error2.params.additionalProperty}' is not allowed ${formattedInstancePath}`
1359
1394
  );
1360
- } else if (error.keyword === "required") {
1395
+ } else if (error2.keyword === "required") {
1361
1396
  errorMessages.push(
1362
- `Property '${error.params.missingProperty}' is required ${formattedInstancePath}`
1397
+ `Property '${error2.params.missingProperty}' is required ${formattedInstancePath}`
1363
1398
  );
1364
1399
  }
1365
1400
  }
@@ -1372,8 +1407,8 @@ function validateSchema(configString) {
1372
1407
  const isValid = validate(parsedConfig);
1373
1408
  if (!isValid) {
1374
1409
  throw new MicrofrontendError(
1375
- `Invalid microfrontends config:${formatAjvErrors(validate.errors).map((error) => `
1376
- - ${error}`).join(
1410
+ `Invalid microfrontends config:${formatAjvErrors(validate.errors).map((error2) => `
1411
+ - ${error2}`).join(
1377
1412
  ""
1378
1413
  )}
1379
1414
 
@@ -1658,27 +1693,25 @@ function transform3(args) {
1658
1693
  };
1659
1694
  }
1660
1695
 
1661
- // src/next/utils/route-to-local-proxy.ts
1662
- function routeToLocalProxy() {
1663
- const isDevEnv = (process.env.VERCEL_ENV ?? "development") === "development";
1664
- return isDevEnv && Boolean(process.env.TURBO_TASK_HAS_MFE_PROXY);
1665
- }
1666
-
1667
1696
  // src/next/config/transforms/redirects.ts
1668
1697
  function transform4(args) {
1669
- const { next, microfrontend, opts, app } = args;
1670
- const isProduction2 = opts?.isProduction ?? false;
1671
- const requireLocalProxyHeader = routeToLocalProxy() && !isProduction2 && !process.env.MFE_DISABLE_LOCAL_PROXY_REWRITE;
1698
+ const { next, microfrontend } = args;
1699
+ const requireLocalProxyHeader = localProxyIsRunning() && !process.env.MFE_DISABLE_LOCAL_PROXY_REWRITE;
1672
1700
  if (requireLocalProxyHeader) {
1673
- const assetPrefix = app.getAssetPrefix();
1674
1701
  const proxyRedirects = [
1675
1702
  {
1676
- source: `/((?!${assetPrefix ? `${assetPrefix}/` : ""}_next/static).*)`,
1703
+ source: `/:path*`,
1677
1704
  destination: `http://localhost:${microfrontend.getLocalProxyPort()}/:path*`,
1678
1705
  permanent: false,
1679
1706
  missing: [
1680
1707
  { type: "header", key: "x-vercel-mfe-local-proxy-origin" }
1681
- ]
1708
+ ],
1709
+ // this fixes relative path Next.js images locally. A security fix removed the headers from the image request,
1710
+ // https://github.com/vercel/next.js/pull/82114, and locally the image fetch does not follow redirects. This
1711
+ // means the header x-vercel-mfe-local-proxy-origin is stripped, and the redirect to then add the header back
1712
+ // in is not followed. As all headers are stripped, there is also no host header, so this check will ensure
1713
+ // relative path Next.js images are not redirected to the local proxy.
1714
+ has: [{ type: "header", key: "host" }]
1682
1715
  }
1683
1716
  ];
1684
1717
  if (next.redirects && typeof next.redirects === "function") {
@@ -1690,17 +1723,15 @@ function transform4(args) {
1690
1723
  } else {
1691
1724
  next.redirects = async () => proxyRedirects;
1692
1725
  }
1693
- if (process.env.MFE_DEBUG) {
1694
- const indent = " ".repeat(4);
1695
- const header = "redirects";
1696
- const separator = "\u23AF".repeat(header.length);
1697
- console.log(
1698
- `${indent}${header}
1726
+ const indent = " ".repeat(4);
1727
+ const header = "redirects";
1728
+ const separator = "\u23AF".repeat(header.length);
1729
+ logger.debug(
1730
+ `${indent}${header}
1699
1731
  ${indent}${separator}
1700
1732
  ${indent} - Automatically redirecting all requests to local microfrontends proxy
1701
1733
  `
1702
- );
1703
- }
1734
+ );
1704
1735
  }
1705
1736
  return { next };
1706
1737
  }
@@ -1721,22 +1752,18 @@ function transform5(args) {
1721
1752
 
1722
1753
  // src/next/config/transforms/rewrites.ts
1723
1754
  function debugRewrites(rewrites) {
1724
- if (process.env.MFE_DEBUG) {
1725
- const indent = " ".repeat(4);
1726
- const header = "rewrites (source \u2192 destination)";
1727
- const separator = "\u23AF".repeat(header.length);
1728
- const maxSourceLength = Math.max(
1729
- ...rewrites.map((key) => key.source.length)
1730
- );
1731
- const table = rewrites.map((route, idx) => {
1732
- const paddedSource = route.source.padEnd(maxSourceLength);
1733
- return `${indent} ${idx + 1}. ${paddedSource} \u2192 ${route.destination}`;
1734
- }).join("\n");
1735
- console.log(`${indent}${header}
1755
+ const indent = " ".repeat(4);
1756
+ const header = "rewrites (source \u2192 destination)";
1757
+ const separator = "\u23AF".repeat(header.length);
1758
+ const maxSourceLength = Math.max(...rewrites.map((key) => key.source.length));
1759
+ const table = rewrites.map((route, idx) => {
1760
+ const paddedSource = route.source.padEnd(maxSourceLength);
1761
+ return `${indent} ${idx + 1}. ${paddedSource} \u2192 ${route.destination}`;
1762
+ }).join("\n");
1763
+ logger.debug(`${indent}${header}
1736
1764
  ${indent}${separator}
1737
1765
  ${table}
1738
1766
  `);
1739
- }
1740
1767
  }
1741
1768
  function rewritesMapToArr(rewrites) {
1742
1769
  return Array.from(rewrites.entries()).flatMap(([source, rewrite]) => {
@@ -1934,20 +1961,18 @@ var transforms = {
1934
1961
 
1935
1962
  // src/next/config/env.ts
1936
1963
  function debugEnv(env) {
1937
- if (process.env.MFE_DEBUG) {
1938
- const indent = " ".repeat(4);
1939
- const header = "env (key \u2192 val)";
1940
- const separator = "\u23AF".repeat(header.length);
1941
- const maxKeyLength = Math.max(...Object.keys(env).map((key) => key.length));
1942
- const table = Object.keys(env).map((key, idx) => {
1943
- const paddedKey = key.padEnd(maxKeyLength);
1944
- return `${indent} ${idx + 1}. ${paddedKey} = ${env[key]}`;
1945
- }).join("\n");
1946
- console.log(`${indent}${header}
1964
+ const indent = " ".repeat(4);
1965
+ const header = "env (key \u2192 val)";
1966
+ const separator = "\u23AF".repeat(header.length);
1967
+ const maxKeyLength = Math.max(...Object.keys(env).map((key) => key.length));
1968
+ const table = Object.keys(env).map((key, idx) => {
1969
+ const paddedKey = key.padEnd(maxKeyLength);
1970
+ return `${indent} ${idx + 1}. ${paddedKey} = ${env[key]}`;
1971
+ }).join("\n");
1972
+ logger.debug(`${indent}${header}
1947
1973
  ${indent}${separator}
1948
1974
  ${table}
1949
1975
  `);
1950
- }
1951
1976
  }
1952
1977
  function setEnvironment({
1953
1978
  app,
@@ -1983,12 +2008,6 @@ function setEnvironment({
1983
2008
  function typedEntries(obj) {
1984
2009
  return Object.entries(obj);
1985
2010
  }
1986
- function isProduction(opts) {
1987
- if (opts?.isProduction) {
1988
- return opts.isProduction();
1989
- }
1990
- return process.env.VERCEL_ENV === "production";
1991
- }
1992
2011
  function withMicrofrontends(nextConfig, opts) {
1993
2012
  if (opts?.debug) {
1994
2013
  process.env.MFE_DEBUG = "true";
@@ -2003,7 +2022,7 @@ function withMicrofrontends(nextConfig, opts) {
2003
2022
  let next = { ...nextConfig };
2004
2023
  for (const [key, transform8] of typedEntries(transforms)) {
2005
2024
  if (opts?.skipTransforms?.includes(key)) {
2006
- console.log(`Skipping ${key} transform`);
2025
+ logger.info(`Skipping ${key} transform`);
2007
2026
  continue;
2008
2027
  }
2009
2028
  try {
@@ -2012,13 +2031,12 @@ function withMicrofrontends(nextConfig, opts) {
2012
2031
  next,
2013
2032
  microfrontend: microfrontends.config,
2014
2033
  opts: {
2015
- isProduction: isProduction(opts),
2016
2034
  supportPagesRouter: opts?.supportPagesRouter
2017
2035
  }
2018
2036
  });
2019
2037
  next = transformedConfig.next;
2020
2038
  } catch (e) {
2021
- console.error("Error transforming next config", e);
2039
+ logger.error("Error transforming next config", e);
2022
2040
  throw e;
2023
2041
  }
2024
2042
  }