@vercel/microfrontends 1.5.0 → 2.0.0-canary.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 (58) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/bin/cli.cjs +103 -117
  3. package/dist/config.cjs +48 -101
  4. package/dist/config.cjs.map +1 -1
  5. package/dist/config.d.ts +2 -29
  6. package/dist/config.js +37 -100
  7. package/dist/config.js.map +1 -1
  8. package/dist/experimental/sveltekit.cjs +93 -109
  9. package/dist/experimental/sveltekit.cjs.map +1 -1
  10. package/dist/experimental/sveltekit.js +92 -108
  11. package/dist/experimental/sveltekit.js.map +1 -1
  12. package/dist/experimental/vite.cjs +93 -109
  13. package/dist/experimental/vite.cjs.map +1 -1
  14. package/dist/experimental/vite.js +92 -108
  15. package/dist/experimental/vite.js.map +1 -1
  16. package/dist/get-application-context-e8a5a0e2.d.ts +14 -0
  17. package/dist/microfrontends/server.cjs +93 -109
  18. package/dist/microfrontends/server.cjs.map +1 -1
  19. package/dist/microfrontends/server.d.ts +4 -13
  20. package/dist/microfrontends/server.js +92 -108
  21. package/dist/microfrontends/server.js.map +1 -1
  22. package/dist/microfrontends/utils.cjs +24 -4
  23. package/dist/microfrontends/utils.cjs.map +1 -1
  24. package/dist/microfrontends/utils.d.ts +3 -1
  25. package/dist/microfrontends/utils.js +24 -4
  26. package/dist/microfrontends/utils.js.map +1 -1
  27. package/dist/next/client.cjs +1 -1
  28. package/dist/next/client.cjs.map +1 -1
  29. package/dist/next/client.js +1 -1
  30. package/dist/next/client.js.map +1 -1
  31. package/dist/next/config.cjs +223 -111
  32. package/dist/next/config.cjs.map +1 -1
  33. package/dist/next/config.js +222 -110
  34. package/dist/next/config.js.map +1 -1
  35. package/dist/next/middleware.cjs +88 -44
  36. package/dist/next/middleware.cjs.map +1 -1
  37. package/dist/next/middleware.js +78 -44
  38. package/dist/next/middleware.js.map +1 -1
  39. package/dist/next/testing.cjs +51 -104
  40. package/dist/next/testing.cjs.map +1 -1
  41. package/dist/next/testing.d.ts +2 -2
  42. package/dist/next/testing.js +39 -102
  43. package/dist/next/testing.js.map +1 -1
  44. package/dist/overrides.d.ts +3 -3
  45. package/dist/schema.d.ts +2 -2
  46. package/dist/{types-1cec43e6.d.ts → types-0deb756b.d.ts} +16 -1
  47. package/dist/{types-1fb60496.d.ts → types-4299bff1.d.ts} +1 -1
  48. package/dist/utils/mfe-port.cjs +93 -109
  49. package/dist/utils/mfe-port.cjs.map +1 -1
  50. package/dist/utils/mfe-port.js +92 -108
  51. package/dist/utils/mfe-port.js.map +1 -1
  52. package/dist/validation.cjs +4 -0
  53. package/dist/validation.cjs.map +1 -1
  54. package/dist/validation.d.ts +1 -1
  55. package/dist/validation.js +4 -0
  56. package/dist/validation.js.map +1 -1
  57. package/package.json +3 -1
  58. package/schema/schema.json +4 -0
@@ -242,8 +242,9 @@ var CONFIGURATION_FILENAMES = [
242
242
  var configCache = {};
243
243
  function findPackageWithMicrofrontendsConfig({
244
244
  repositoryRoot,
245
- applicationName
245
+ applicationContext
246
246
  }) {
247
+ const applicationName = applicationContext.name;
247
248
  try {
248
249
  const microfrontendsJsonPaths = import_fast_glob.default.globSync(
249
250
  `**/{${CONFIGURATION_FILENAMES.join(",")}}`,
@@ -285,26 +286,45 @@ ${matchingPaths.join("\n \u2022 ")}`,
285
286
  );
286
287
  }
287
288
  if (matchingPaths.length === 0) {
289
+ let additionalErrorMessage = "";
290
+ if (microfrontendsJsonPaths.length > 0) {
291
+ if (!applicationContext.projectName) {
292
+ additionalErrorMessage = `
293
+
294
+ If the name in package.json (${applicationContext.packageJsonName}) differs from your Vercel Project name, set the \`packageName\` field for the application in \`microfrontends.json\` to ensure that the configuration can be found locally.`;
295
+ } else {
296
+ additionalErrorMessage = `
297
+
298
+ Names of applications in \`microfrontends.json\` must match the Vercel Project name (${applicationContext.projectName}).`;
299
+ }
300
+ }
288
301
  throw new MicrofrontendError(
289
- `Could not find a \`microfrontends.json\` file in the repository that contains "applications.${applicationName}". If your Vercel Microfrontends configuration is not in this repository, you can use the Vercel CLI to pull the Vercel Microfrontends configuration using the "vercel microfrontends pull" command, or you can specify the path manually using the VC_MICROFRONTENDS_CONFIG environment variable. If you suspect this is thrown in error, please reach out to the Vercel team.`,
302
+ `Could not find a \`microfrontends.json\` file in the repository that contains the "${applicationName}" application.${additionalErrorMessage}
303
+
304
+ If your Vercel Microfrontends configuration is not in this repository, you can use the Vercel CLI to pull the Vercel Microfrontends configuration using the "vercel microfrontends pull" command, or you can specify the path manually using the VC_MICROFRONTENDS_CONFIG environment variable.
305
+
306
+ If you suspect this is thrown in error, please reach out to the Vercel team.`,
290
307
  { type: "config", subtype: "inference_failed" }
291
308
  );
292
309
  }
293
310
  const [packageJsonPath] = matchingPaths;
294
311
  return (0, import_node_path2.dirname)(packageJsonPath);
295
312
  } catch (error) {
313
+ if (error instanceof MicrofrontendError) {
314
+ throw error;
315
+ }
296
316
  return null;
297
317
  }
298
318
  }
299
319
  function inferMicrofrontendsLocation(opts) {
300
- const cacheKey = `${opts.repositoryRoot}-${opts.applicationName}`;
320
+ const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}`;
301
321
  if (configCache[cacheKey]) {
302
322
  return configCache[cacheKey];
303
323
  }
304
324
  const result = findPackageWithMicrofrontendsConfig(opts);
305
325
  if (!result) {
306
326
  throw new MicrofrontendError(
307
- `Could not infer the location of the \`microfrontends.json\` file for application "${opts.applicationName}" starting in directory "${opts.repositoryRoot}".`,
327
+ `Could not infer the location of the \`microfrontends.json\` file for application "${opts.applicationContext.name}" starting in directory "${opts.repositoryRoot}".`,
308
328
  { type: "config", subtype: "inference_failed" }
309
329
  );
310
330
  }
@@ -376,90 +396,13 @@ function findConfig({ dir }) {
376
396
  // src/config/microfrontends-config/isomorphic/index.ts
377
397
  var import_jsonc_parser2 = require("jsonc-parser");
378
398
 
379
- // src/config/microfrontends-config/client/index.ts
380
- var import_path_to_regexp = require("path-to-regexp");
381
- var regexpCache = /* @__PURE__ */ new Map();
382
- var getRegexp = (path6) => {
383
- const existing = regexpCache.get(path6);
384
- if (existing) {
385
- return existing;
386
- }
387
- const regexp = (0, import_path_to_regexp.pathToRegexp)(path6);
388
- regexpCache.set(path6, regexp);
389
- return regexp;
390
- };
391
- var MicrofrontendConfigClient = class {
392
- constructor(config, opts) {
393
- this.pathCache = {};
394
- this.serialized = config;
395
- if (opts?.removeFlaggedPaths) {
396
- for (const app of Object.values(config.applications)) {
397
- if (app.routing) {
398
- app.routing = app.routing.filter((match) => !match.flag);
399
- }
400
- }
401
- }
402
- this.applications = config.applications;
403
- }
404
- /**
405
- * Create a new `MicrofrontendConfigClient` from a JSON string.
406
- * Config must be passed in to remain framework agnostic
407
- */
408
- static fromEnv(config, opts) {
409
- if (!config) {
410
- throw new Error(
411
- "Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
412
- );
413
- }
414
- return new MicrofrontendConfigClient(
415
- JSON.parse(config),
416
- opts
417
- );
418
- }
419
- isEqual(other) {
420
- return this === other || JSON.stringify(this.applications) === JSON.stringify(other.applications);
421
- }
422
- getApplicationNameForPath(path6) {
423
- if (!path6.startsWith("/")) {
424
- throw new Error(`Path must start with a /`);
425
- }
426
- if (this.pathCache[path6]) {
427
- return this.pathCache[path6];
428
- }
429
- const pathname = new URL(path6, "https://example.com").pathname;
430
- for (const [name, application] of Object.entries(this.applications)) {
431
- if (application.routing) {
432
- for (const group of application.routing) {
433
- for (const childPath of group.paths) {
434
- const regexp = getRegexp(childPath);
435
- if (regexp.test(pathname)) {
436
- this.pathCache[path6] = name;
437
- return name;
438
- }
439
- }
440
- }
441
- }
442
- }
443
- const defaultApplication = Object.entries(this.applications).find(
444
- ([, application]) => application.default
445
- );
446
- if (!defaultApplication) {
447
- return null;
448
- }
449
- this.pathCache[path6] = defaultApplication[0];
450
- return defaultApplication[0];
451
- }
452
- serialize() {
453
- return this.serialized;
454
- }
455
- };
456
-
457
399
  // src/config/microfrontends-config/isomorphic/validation.ts
458
- var import_path_to_regexp2 = require("path-to-regexp");
400
+ var import_path_to_regexp = require("path-to-regexp");
459
401
  var LIST_FORMATTER = new Intl.ListFormat("en", {
460
402
  style: "long",
461
403
  type: "conjunction"
462
404
  });
405
+ var VALID_ASSET_PREFIX_REGEXP = /^[a-z](?:[a-z0-9-]*[a-z0-9])?$/;
463
406
  var validateConfigPaths = (applicationConfigsById) => {
464
407
  if (!applicationConfigsById) {
465
408
  return;
@@ -482,7 +425,7 @@ var validateConfigPaths = (applicationConfigsById) => {
482
425
  } else {
483
426
  pathsByApplicationId.set(path6, {
484
427
  applications: [id],
485
- matcher: (0, import_path_to_regexp2.pathToRegexp)(path6),
428
+ matcher: (0, import_path_to_regexp.pathToRegexp)(path6),
486
429
  applicationId: id
487
430
  });
488
431
  }
@@ -529,7 +472,7 @@ var validateConfigPaths = (applicationConfigsById) => {
529
472
  var PATH_DEFAULT_PATTERN = "[^\\/#\\?]+?";
530
473
  function validatePathExpression(path6) {
531
474
  try {
532
- const tokens = (0, import_path_to_regexp2.parse)(path6);
475
+ const tokens = (0, import_path_to_regexp.parse)(path6);
533
476
  if (/(?<!\\)\{/.test(path6)) {
534
477
  return `Optional paths are not supported: ${path6}`;
535
478
  }
@@ -586,6 +529,22 @@ var validateAppPaths = (name, app) => {
586
529
  }
587
530
  }
588
531
  }
532
+ if (app.assetPrefix) {
533
+ if (!VALID_ASSET_PREFIX_REGEXP.test(app.assetPrefix)) {
534
+ throw new MicrofrontendError(
535
+ `Invalid asset prefix for application "${name}". ${app.assetPrefix} must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`,
536
+ { type: "application", subtype: "invalid_asset_prefix" }
537
+ );
538
+ }
539
+ if (app.assetPrefix !== `vc-ap-${name}` && !app.routing.some(
540
+ (group) => group.paths.includes(`/${app.assetPrefix}/:path*`) && !group.flag
541
+ )) {
542
+ throw new MicrofrontendError(
543
+ `When \`assetPrefix\` is specified, \`/${app.assetPrefix}/:path*\` must be added the routing paths for the application. Changing the asset prefix is not a forwards and backwards compatible change, and the custom asset prefix should be added to \`paths\` and deployed before setting the \`assetPrefix\` field.`,
544
+ { type: "application", subtype: "invalid_asset_prefix" }
545
+ );
546
+ }
547
+ }
589
548
  };
590
549
  var validateConfigDefaultApplication = (applicationConfigsById) => {
591
550
  if (!applicationConfigsById) {
@@ -617,6 +576,15 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
617
576
  }
618
577
  };
619
578
 
579
+ // src/config/microfrontends-config/isomorphic/utils/hash-application-name.ts
580
+ var import_md5 = __toESM(require("md5"), 1);
581
+ function hashApplicationName(name) {
582
+ if (!name) {
583
+ throw new Error("Application name is required to generate hash");
584
+ }
585
+ return (0, import_md5.default)(name).substring(0, 6).padStart(6, "0");
586
+ }
587
+
620
588
  // src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
621
589
  var PREFIX = "vc-ap";
622
590
  function generateAssetPrefixFromName({
@@ -625,7 +593,7 @@ function generateAssetPrefixFromName({
625
593
  if (!name) {
626
594
  throw new Error("Name is required to generate an asset prefix");
627
595
  }
628
- return `${PREFIX}-${name}`;
596
+ return `${PREFIX}-${hashApplicationName(name)}`;
629
597
  }
630
598
 
631
599
  // src/config/microfrontends-config/isomorphic/utils/generate-port.ts
@@ -785,7 +753,13 @@ var Application = class {
785
753
  return this.default;
786
754
  }
787
755
  getAssetPrefix() {
788
- return generateAssetPrefixFromName({ name: this.name });
756
+ const generatedAssetPrefix = generateAssetPrefixFromName({
757
+ name: this.name
758
+ });
759
+ if ("assetPrefix" in this.serialized) {
760
+ return this.serialized.assetPrefix ?? generatedAssetPrefix;
761
+ }
762
+ return generatedAssetPrefix;
789
763
  }
790
764
  getAutomationBypassEnvVarName() {
791
765
  return generateAutomationBypassEnvVarName({ name: this.name });
@@ -919,7 +893,7 @@ var MicrofrontendConfigIsomorphic = class {
919
893
  );
920
894
  if (!app) {
921
895
  throw new MicrofrontendError(
922
- `Could not find microfrontends configuration for application "${name}"`,
896
+ `Could not find microfrontends configuration for application "${name}". If the name in package.json differs from your Vercel Project name, set the \`packageName\` field for the application in \`microfrontends.json\` to ensure that the configuration can be found locally.`,
923
897
  {
924
898
  type: "application",
925
899
  subtype: "not_found"
@@ -964,23 +938,6 @@ var MicrofrontendConfigIsomorphic = class {
964
938
  toSchemaJson() {
965
939
  return this.serialized.config;
966
940
  }
967
- toClientConfig() {
968
- const applications = Object.fromEntries(
969
- Object.entries(this.childApplications).map(([name, application]) => [
970
- name,
971
- {
972
- default: false,
973
- routing: application.routing
974
- }
975
- ])
976
- );
977
- applications[this.defaultApplication.name] = {
978
- default: true
979
- };
980
- return new MicrofrontendConfigClient({
981
- applications
982
- });
983
- }
984
941
  serialize() {
985
942
  return this.serialized;
986
943
  }
@@ -993,8 +950,31 @@ function getApplicationContext(opts) {
993
950
  if (opts?.appName) {
994
951
  return { name: opts.appName };
995
952
  }
953
+ if (process.env.VERCEL_PROJECT_NAME) {
954
+ return {
955
+ name: process.env.VERCEL_PROJECT_NAME,
956
+ projectName: process.env.VERCEL_PROJECT_NAME
957
+ };
958
+ }
996
959
  if (process.env.NX_TASK_TARGET_PROJECT) {
997
- return { name: process.env.NX_TASK_TARGET_PROJECT };
960
+ return {
961
+ name: process.env.NX_TASK_TARGET_PROJECT,
962
+ packageJsonName: process.env.NX_TASK_TARGET_PROJECT
963
+ };
964
+ }
965
+ try {
966
+ const vercelProjectJsonPath = import_node_fs6.default.readFileSync(
967
+ import_node_path6.default.join(opts?.packageRoot || ".", ".vercel", "project.json"),
968
+ "utf-8"
969
+ );
970
+ const projectJson = JSON.parse(vercelProjectJsonPath);
971
+ if (projectJson.projectName) {
972
+ return {
973
+ name: projectJson.projectName,
974
+ projectName: projectJson.projectName
975
+ };
976
+ }
977
+ } catch (_) {
998
978
  }
999
979
  try {
1000
980
  const packageJsonString = import_node_fs6.default.readFileSync(
@@ -1012,7 +992,7 @@ function getApplicationContext(opts) {
1012
992
  }
1013
993
  );
1014
994
  }
1015
- return { name: packageJson.name };
995
+ return { name: packageJson.name, packageJsonName: packageJson.name };
1016
996
  } catch (err) {
1017
997
  throw MicrofrontendError.handle(err, {
1018
998
  fileName: "package.json"
@@ -1152,6 +1132,10 @@ var schema_default = {
1152
1132
  routing: {
1153
1133
  $ref: "#/definitions/Routing",
1154
1134
  description: "Groups of path expressions that are routed to this application."
1135
+ },
1136
+ assetPrefix: {
1137
+ type: "string",
1138
+ 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."
1155
1139
  }
1156
1140
  },
1157
1141
  required: [
@@ -1377,7 +1361,7 @@ var MicrofrontendsServer = class {
1377
1361
  }
1378
1362
  try {
1379
1363
  const packageRoot = findPackageRoot(directory);
1380
- const { name: appName } = getApplicationContext({ packageRoot });
1364
+ const applicationContext = getApplicationContext({ packageRoot });
1381
1365
  const maybeConfig = findConfig({ dir: packageRoot });
1382
1366
  if (maybeConfig) {
1383
1367
  return MicrofrontendsServer.fromFile({
@@ -1411,7 +1395,7 @@ var MicrofrontendsServer = class {
1411
1395
  if (isMonorepo2) {
1412
1396
  const defaultPackage = inferMicrofrontendsLocation({
1413
1397
  repositoryRoot,
1414
- applicationName: appName
1398
+ applicationContext
1415
1399
  });
1416
1400
  const maybeConfigFromDefault = findConfig({ dir: defaultPackage });
1417
1401
  if (maybeConfigFromDefault) {
@@ -1811,6 +1795,128 @@ var transforms = {
1811
1795
  webpack: transform7
1812
1796
  };
1813
1797
 
1798
+ // src/config/microfrontends-config/client/index.ts
1799
+ var import_path_to_regexp2 = require("path-to-regexp");
1800
+ var regexpCache = /* @__PURE__ */ new Map();
1801
+ var getRegexp = (path6) => {
1802
+ const existing = regexpCache.get(path6);
1803
+ if (existing) {
1804
+ return existing;
1805
+ }
1806
+ const regexp = (0, import_path_to_regexp2.pathToRegexp)(path6);
1807
+ regexpCache.set(path6, regexp);
1808
+ return regexp;
1809
+ };
1810
+ var MicrofrontendConfigClient = class {
1811
+ constructor(config, opts) {
1812
+ this.pathCache = {};
1813
+ this.hasFlaggedPaths = config.hasFlaggedPaths ?? false;
1814
+ for (const app of Object.values(config.applications)) {
1815
+ if (app.routing) {
1816
+ if (app.routing.some((match) => match.flag)) {
1817
+ this.hasFlaggedPaths = true;
1818
+ }
1819
+ const newRouting = [];
1820
+ const pathsWithoutFlags = [];
1821
+ for (const group of app.routing) {
1822
+ if (group.flag) {
1823
+ if (opts?.removeFlaggedPaths) {
1824
+ continue;
1825
+ }
1826
+ if (group.group) {
1827
+ delete group.group;
1828
+ }
1829
+ newRouting.push(group);
1830
+ } else {
1831
+ pathsWithoutFlags.push(...group.paths);
1832
+ }
1833
+ }
1834
+ if (pathsWithoutFlags.length > 0) {
1835
+ newRouting.push({ paths: pathsWithoutFlags });
1836
+ }
1837
+ app.routing = newRouting;
1838
+ }
1839
+ }
1840
+ this.serialized = config;
1841
+ if (this.hasFlaggedPaths) {
1842
+ this.serialized.hasFlaggedPaths = this.hasFlaggedPaths;
1843
+ }
1844
+ this.applications = config.applications;
1845
+ }
1846
+ /**
1847
+ * Create a new `MicrofrontendConfigClient` from a JSON string.
1848
+ * Config must be passed in to remain framework agnostic
1849
+ */
1850
+ static fromEnv(config) {
1851
+ if (!config) {
1852
+ throw new Error(
1853
+ "Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
1854
+ );
1855
+ }
1856
+ return new MicrofrontendConfigClient(JSON.parse(config));
1857
+ }
1858
+ isEqual(other) {
1859
+ return this === other || JSON.stringify(this.applications) === JSON.stringify(other.applications);
1860
+ }
1861
+ getApplicationNameForPath(path6) {
1862
+ if (!path6.startsWith("/")) {
1863
+ throw new Error(`Path must start with a /`);
1864
+ }
1865
+ if (this.pathCache[path6]) {
1866
+ return this.pathCache[path6];
1867
+ }
1868
+ const pathname = new URL(path6, "https://example.com").pathname;
1869
+ for (const [name, application] of Object.entries(this.applications)) {
1870
+ if (application.routing) {
1871
+ for (const group of application.routing) {
1872
+ for (const childPath of group.paths) {
1873
+ const regexp = getRegexp(childPath);
1874
+ if (regexp.test(pathname)) {
1875
+ this.pathCache[path6] = name;
1876
+ return name;
1877
+ }
1878
+ }
1879
+ }
1880
+ }
1881
+ }
1882
+ const defaultApplication = Object.entries(this.applications).find(
1883
+ ([, application]) => application.default
1884
+ );
1885
+ if (!defaultApplication) {
1886
+ return null;
1887
+ }
1888
+ this.pathCache[path6] = defaultApplication[0];
1889
+ return defaultApplication[0];
1890
+ }
1891
+ serialize() {
1892
+ return this.serialized;
1893
+ }
1894
+ };
1895
+
1896
+ // src/config/microfrontends-config/client/from-isomorphic-config.ts
1897
+ function fromIsomorphicConfig(config, options) {
1898
+ const applications = Object.fromEntries(
1899
+ Object.entries(config.childApplications).map(([name, application]) => [
1900
+ hashApplicationName(name),
1901
+ {
1902
+ default: false,
1903
+ routing: application.routing
1904
+ }
1905
+ ])
1906
+ );
1907
+ applications[hashApplicationName(config.defaultApplication.name)] = {
1908
+ default: true
1909
+ };
1910
+ return new MicrofrontendConfigClient(
1911
+ {
1912
+ applications
1913
+ },
1914
+ {
1915
+ removeFlaggedPaths: options?.removeFlaggedPaths
1916
+ }
1917
+ );
1918
+ }
1919
+
1814
1920
  // src/next/config/env.ts
1815
1921
  function debugEnv(env) {
1816
1922
  if (process.env.MFE_DEBUG) {
@@ -1834,8 +1940,11 @@ function setEnvironment({
1834
1940
  }) {
1835
1941
  const clientEnvs = {
1836
1942
  NEXT_PUBLIC_MFE_CURRENT_APPLICATION: app.name,
1943
+ NEXT_PUBLIC_MFE_CURRENT_APPLICATION_HASH: hashApplicationName(app.name),
1837
1944
  NEXT_PUBLIC_MFE_CLIENT_CONFIG: JSON.stringify(
1838
- microfrontends.config.toClientConfig().serialize()
1945
+ fromIsomorphicConfig(microfrontends.config, {
1946
+ removeFlaggedPaths: true
1947
+ }).serialize()
1839
1948
  ),
1840
1949
  ...process.env.ROUTE_OBSERVABILITY_TO_THIS_PROJECT && app.getAssetPrefix() ? {
1841
1950
  NEXT_PUBLIC_VERCEL_OBSERVABILITY_BASEPATH: `/${app.getAssetPrefix()}/_vercel`
@@ -1843,7 +1952,10 @@ function setEnvironment({
1843
1952
  };
1844
1953
  const serverEnvs = {
1845
1954
  MFE_CURRENT_APPLICATION: app.name,
1846
- MFE_CONFIG: JSON.stringify(microfrontends.config.getConfig())
1955
+ MFE_CONFIG: JSON.stringify(microfrontends.config.getConfig()),
1956
+ MFE_CLIENT_CONFIG_FULL: JSON.stringify(
1957
+ fromIsomorphicConfig(microfrontends.config).serialize()
1958
+ )
1847
1959
  };
1848
1960
  const allEnvs = { ...clientEnvs, ...serverEnvs };
1849
1961
  for (const [key, value] of Object.entries(allEnvs)) {