@vercel/microfrontends 2.1.3 → 2.2.1
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/CHANGELOG.md +20 -0
- package/README.md +4 -0
- package/dist/bin/cli.cjs +207 -90
- package/dist/config.d.ts +2 -2
- package/dist/experimental/sveltekit.cjs +180 -63
- package/dist/experimental/sveltekit.cjs.map +1 -1
- package/dist/experimental/sveltekit.d.ts +6 -0
- package/dist/experimental/sveltekit.js +180 -63
- package/dist/experimental/sveltekit.js.map +1 -1
- package/dist/experimental/vite.cjs +177 -66
- package/dist/experimental/vite.cjs.map +1 -1
- package/dist/experimental/vite.js +177 -66
- package/dist/experimental/vite.js.map +1 -1
- package/dist/microfrontends/server.cjs +173 -60
- package/dist/microfrontends/server.cjs.map +1 -1
- package/dist/microfrontends/server.d.ts +2 -2
- package/dist/microfrontends/server.js +173 -60
- package/dist/microfrontends/server.js.map +1 -1
- package/dist/microfrontends/utils.cjs +50 -7
- package/dist/microfrontends/utils.cjs.map +1 -1
- package/dist/microfrontends/utils.d.ts +1 -1
- package/dist/microfrontends/utils.js +50 -7
- package/dist/microfrontends/utils.js.map +1 -1
- package/dist/next/config.cjs +208 -113
- package/dist/next/config.cjs.map +1 -1
- package/dist/next/config.d.ts +11 -1
- package/dist/next/config.js +208 -113
- package/dist/next/config.js.map +1 -1
- package/dist/next/middleware.cjs +35 -17
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.js +35 -17
- package/dist/next/middleware.js.map +1 -1
- package/dist/next/testing.d.ts +2 -2
- package/dist/overrides.d.ts +3 -3
- package/dist/schema.d.ts +2 -2
- package/dist/{types-88602303.d.ts → types-b9ea41b2.d.ts} +1 -1
- package/dist/{types-e7523e61.d.ts → types-dcd8b17a.d.ts} +71 -24
- package/dist/utils/mfe-port.cjs +173 -60
- package/dist/utils/mfe-port.cjs.map +1 -1
- package/dist/utils/mfe-port.js +173 -60
- package/dist/utils/mfe-port.js.map +1 -1
- package/dist/validation.cjs +47 -38
- package/dist/validation.cjs.map +1 -1
- package/dist/validation.d.ts +1 -1
- package/dist/validation.js +47 -38
- package/dist/validation.js.map +1 -1
- package/package.json +1 -1
- package/schema/schema.json +47 -38
package/dist/next/config.cjs
CHANGED
|
@@ -34,12 +34,38 @@ __export(config_exports, {
|
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(config_exports);
|
|
36
36
|
|
|
37
|
+
// src/bin/local-proxy-is-running.ts
|
|
38
|
+
function localProxyIsRunning() {
|
|
39
|
+
return process.env.TURBO_TASK_HAS_MFE_PROXY === "true";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// src/bin/logger.ts
|
|
43
|
+
function debug(...args) {
|
|
44
|
+
if (process.env.MFE_DEBUG) {
|
|
45
|
+
console.log(...args);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function info(...args) {
|
|
49
|
+
console.log(...args);
|
|
50
|
+
}
|
|
51
|
+
function warn(...args) {
|
|
52
|
+
console.warn(...args);
|
|
53
|
+
}
|
|
54
|
+
function error(...args) {
|
|
55
|
+
console.error(...args);
|
|
56
|
+
}
|
|
57
|
+
var logger = {
|
|
58
|
+
debug,
|
|
59
|
+
info,
|
|
60
|
+
warn,
|
|
61
|
+
error
|
|
62
|
+
};
|
|
63
|
+
|
|
37
64
|
// src/bin/check-proxy.ts
|
|
38
65
|
function displayLocalProxyInfo(port) {
|
|
39
|
-
|
|
40
|
-
if (TURBO_TASK_HAS_MFE_PROXY === "true" && MFE_PROXY_MESSAGE_PRINTED !== "true") {
|
|
66
|
+
if (localProxyIsRunning() && process.env.MFE_PROXY_MESSAGE_PRINTED !== "true") {
|
|
41
67
|
process.env.MFE_PROXY_MESSAGE_PRINTED = "true";
|
|
42
|
-
|
|
68
|
+
logger.info(`Microfrontends Proxy running on http://localhost:${port}`);
|
|
43
69
|
}
|
|
44
70
|
}
|
|
45
71
|
|
|
@@ -234,8 +260,8 @@ var import_fast_glob = __toESM(require("fast-glob"), 1);
|
|
|
234
260
|
|
|
235
261
|
// src/config/microfrontends/utils/get-config-file-name.ts
|
|
236
262
|
var DEFAULT_CONFIGURATION_FILENAMES = [
|
|
237
|
-
"microfrontends.
|
|
238
|
-
"microfrontends.
|
|
263
|
+
"microfrontends.json",
|
|
264
|
+
"microfrontends.jsonc"
|
|
239
265
|
];
|
|
240
266
|
function getPossibleConfigurationFilenames({
|
|
241
267
|
customConfigFilename
|
|
@@ -243,7 +269,7 @@ function getPossibleConfigurationFilenames({
|
|
|
243
269
|
if (customConfigFilename) {
|
|
244
270
|
if (!customConfigFilename.endsWith(".json") && !customConfigFilename.endsWith(".jsonc")) {
|
|
245
271
|
throw new Error(
|
|
246
|
-
`
|
|
272
|
+
`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.`
|
|
247
273
|
);
|
|
248
274
|
}
|
|
249
275
|
return Array.from(
|
|
@@ -261,6 +287,10 @@ function findPackageWithMicrofrontendsConfig({
|
|
|
261
287
|
customConfigFilename
|
|
262
288
|
}) {
|
|
263
289
|
const applicationName = applicationContext.name;
|
|
290
|
+
logger.debug(
|
|
291
|
+
"[MFE Config] Searching repository for configs containing application:",
|
|
292
|
+
applicationName
|
|
293
|
+
);
|
|
264
294
|
try {
|
|
265
295
|
const microfrontendsJsonPaths = import_fast_glob.default.globSync(
|
|
266
296
|
`**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(",")}}`,
|
|
@@ -272,6 +302,11 @@ function findPackageWithMicrofrontendsConfig({
|
|
|
272
302
|
ignore: ["**/node_modules/**", "**/.git/**"]
|
|
273
303
|
}
|
|
274
304
|
);
|
|
305
|
+
logger.debug(
|
|
306
|
+
"[MFE Config] Found",
|
|
307
|
+
microfrontendsJsonPaths.length,
|
|
308
|
+
"config file(s) in repository"
|
|
309
|
+
);
|
|
275
310
|
const matchingPaths = [];
|
|
276
311
|
for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
|
|
277
312
|
try {
|
|
@@ -281,19 +316,31 @@ function findPackageWithMicrofrontendsConfig({
|
|
|
281
316
|
);
|
|
282
317
|
const microfrontendsJson = (0, import_jsonc_parser.parse)(microfrontendsJsonContent);
|
|
283
318
|
if (microfrontendsJson.applications[applicationName]) {
|
|
319
|
+
logger.debug(
|
|
320
|
+
"[MFE Config] Found application in config:",
|
|
321
|
+
microfrontendsJsonPath
|
|
322
|
+
);
|
|
284
323
|
matchingPaths.push(microfrontendsJsonPath);
|
|
285
324
|
} else {
|
|
286
325
|
for (const [_, app] of Object.entries(
|
|
287
326
|
microfrontendsJson.applications
|
|
288
327
|
)) {
|
|
289
328
|
if (app.packageName === applicationName) {
|
|
329
|
+
logger.debug(
|
|
330
|
+
"[MFE Config] Found application via packageName in config:",
|
|
331
|
+
microfrontendsJsonPath
|
|
332
|
+
);
|
|
290
333
|
matchingPaths.push(microfrontendsJsonPath);
|
|
291
334
|
}
|
|
292
335
|
}
|
|
293
336
|
}
|
|
294
|
-
} catch (
|
|
337
|
+
} catch (error2) {
|
|
295
338
|
}
|
|
296
339
|
}
|
|
340
|
+
logger.debug(
|
|
341
|
+
"[MFE Config] Total matching config files:",
|
|
342
|
+
matchingPaths.length
|
|
343
|
+
);
|
|
297
344
|
if (matchingPaths.length > 1) {
|
|
298
345
|
throw new MicrofrontendError(
|
|
299
346
|
`Found multiple \`microfrontends.json\` files in the repository referencing the application "${applicationName}", but only one is allowed.
|
|
@@ -327,9 +374,9 @@ If you suspect this is thrown in error, please reach out to the Vercel team.`,
|
|
|
327
374
|
}
|
|
328
375
|
const [packageJsonPath] = matchingPaths;
|
|
329
376
|
return (0, import_node_path2.dirname)(packageJsonPath);
|
|
330
|
-
} catch (
|
|
331
|
-
if (
|
|
332
|
-
throw
|
|
377
|
+
} catch (error2) {
|
|
378
|
+
if (error2 instanceof MicrofrontendError) {
|
|
379
|
+
throw error2;
|
|
333
380
|
}
|
|
334
381
|
return null;
|
|
335
382
|
}
|
|
@@ -374,8 +421,8 @@ function isMonorepo({
|
|
|
374
421
|
import_node_fs3.default.readFileSync(packageJsonPath, "utf-8")
|
|
375
422
|
);
|
|
376
423
|
return packageJson.workspaces !== void 0;
|
|
377
|
-
} catch (
|
|
378
|
-
|
|
424
|
+
} catch (error2) {
|
|
425
|
+
logger.error("Error determining if repository is a monorepo", error2);
|
|
379
426
|
return false;
|
|
380
427
|
}
|
|
381
428
|
}
|
|
@@ -1092,15 +1139,18 @@ var import_node_fs6 = __toESM(require("fs"), 1);
|
|
|
1092
1139
|
var import_node_path6 = __toESM(require("path"), 1);
|
|
1093
1140
|
function getApplicationContext(opts) {
|
|
1094
1141
|
if (opts?.appName) {
|
|
1142
|
+
logger.debug("[MFE Config] Application name from appName parameter:", opts.appName);
|
|
1095
1143
|
return { name: opts.appName };
|
|
1096
1144
|
}
|
|
1097
1145
|
if (process.env.VERCEL_PROJECT_NAME) {
|
|
1146
|
+
logger.debug("[MFE Config] Application name from VERCEL_PROJECT_NAME:", process.env.VERCEL_PROJECT_NAME);
|
|
1098
1147
|
return {
|
|
1099
1148
|
name: process.env.VERCEL_PROJECT_NAME,
|
|
1100
1149
|
projectName: process.env.VERCEL_PROJECT_NAME
|
|
1101
1150
|
};
|
|
1102
1151
|
}
|
|
1103
1152
|
if (process.env.NX_TASK_TARGET_PROJECT) {
|
|
1153
|
+
logger.debug("[MFE Config] Application name from NX_TASK_TARGET_PROJECT:", process.env.NX_TASK_TARGET_PROJECT);
|
|
1104
1154
|
return {
|
|
1105
1155
|
name: process.env.NX_TASK_TARGET_PROJECT,
|
|
1106
1156
|
packageJsonName: process.env.NX_TASK_TARGET_PROJECT
|
|
@@ -1113,6 +1163,7 @@ function getApplicationContext(opts) {
|
|
|
1113
1163
|
);
|
|
1114
1164
|
const projectJson = JSON.parse(vercelProjectJsonPath);
|
|
1115
1165
|
if (projectJson.projectName) {
|
|
1166
|
+
logger.debug("[MFE Config] Application name from .vercel/project.json:", projectJson.projectName);
|
|
1116
1167
|
return {
|
|
1117
1168
|
name: projectJson.projectName,
|
|
1118
1169
|
projectName: projectJson.projectName
|
|
@@ -1136,6 +1187,7 @@ function getApplicationContext(opts) {
|
|
|
1136
1187
|
}
|
|
1137
1188
|
);
|
|
1138
1189
|
}
|
|
1190
|
+
logger.debug("[MFE Config] Application name from package.json:", packageJson.name);
|
|
1139
1191
|
return { name: packageJson.name, packageJsonName: packageJson.name };
|
|
1140
1192
|
} catch (err) {
|
|
1141
1193
|
throw MicrofrontendError.handle(err, {
|
|
@@ -1169,38 +1221,28 @@ var schema_default = {
|
|
|
1169
1221
|
type: "object",
|
|
1170
1222
|
properties: {
|
|
1171
1223
|
$schema: {
|
|
1172
|
-
type: "string"
|
|
1224
|
+
type: "string",
|
|
1225
|
+
description: "See https://openapi.vercel.sh/microfrontends.json."
|
|
1173
1226
|
},
|
|
1174
1227
|
version: {
|
|
1175
1228
|
type: "string",
|
|
1176
|
-
const: "1"
|
|
1177
|
-
|
|
1178
|
-
options: {
|
|
1179
|
-
$ref: "#/definitions/Options"
|
|
1229
|
+
const: "1",
|
|
1230
|
+
description: "The version of the microfrontends config schema."
|
|
1180
1231
|
},
|
|
1181
1232
|
applications: {
|
|
1182
1233
|
$ref: "#/definitions/ApplicationRouting",
|
|
1183
|
-
description: "Mapping of
|
|
1234
|
+
description: "Mapping of Vercel project names to their microfrontend configurations."
|
|
1235
|
+
},
|
|
1236
|
+
options: {
|
|
1237
|
+
$ref: "#/definitions/Options",
|
|
1238
|
+
description: "Optional configuration options for the microfrontend."
|
|
1184
1239
|
}
|
|
1185
1240
|
},
|
|
1186
1241
|
required: [
|
|
1187
1242
|
"applications"
|
|
1188
1243
|
],
|
|
1189
|
-
additionalProperties: false
|
|
1190
|
-
|
|
1191
|
-
Options: {
|
|
1192
|
-
type: "object",
|
|
1193
|
-
properties: {
|
|
1194
|
-
disableOverrides: {
|
|
1195
|
-
type: "boolean",
|
|
1196
|
-
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."
|
|
1197
|
-
},
|
|
1198
|
-
localProxyPort: {
|
|
1199
|
-
type: "number",
|
|
1200
|
-
description: "The port number used by the local proxy server.\n\nThe default is `3024`."
|
|
1201
|
-
}
|
|
1202
|
-
},
|
|
1203
|
-
additionalProperties: false
|
|
1244
|
+
additionalProperties: false,
|
|
1245
|
+
description: "The microfrontends configuration schema. See https://vercel.com/docs/microfrontends/configuration."
|
|
1204
1246
|
},
|
|
1205
1247
|
ApplicationRouting: {
|
|
1206
1248
|
type: "object",
|
|
@@ -1208,8 +1250,9 @@ var schema_default = {
|
|
|
1208
1250
|
$ref: "#/definitions/Application"
|
|
1209
1251
|
},
|
|
1210
1252
|
propertyNames: {
|
|
1211
|
-
description: "The
|
|
1212
|
-
}
|
|
1253
|
+
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."
|
|
1254
|
+
},
|
|
1255
|
+
description: "Mapping of Vercel project names to their microfrontend configurations."
|
|
1213
1256
|
},
|
|
1214
1257
|
Application: {
|
|
1215
1258
|
anyOf: [
|
|
@@ -1219,14 +1262,15 @@ var schema_default = {
|
|
|
1219
1262
|
{
|
|
1220
1263
|
$ref: "#/definitions/ChildApplication"
|
|
1221
1264
|
}
|
|
1222
|
-
]
|
|
1265
|
+
],
|
|
1266
|
+
description: "The configuration for a microfrontend application. There must always be one default application."
|
|
1223
1267
|
},
|
|
1224
1268
|
DefaultApplication: {
|
|
1225
1269
|
type: "object",
|
|
1226
1270
|
properties: {
|
|
1227
1271
|
packageName: {
|
|
1228
1272
|
type: "string",
|
|
1229
|
-
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
|
|
1273
|
+
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."
|
|
1230
1274
|
},
|
|
1231
1275
|
development: {
|
|
1232
1276
|
$ref: "#/definitions/DefaultDevelopment",
|
|
@@ -1246,15 +1290,15 @@ var schema_default = {
|
|
|
1246
1290
|
"number",
|
|
1247
1291
|
"string"
|
|
1248
1292
|
],
|
|
1249
|
-
description: "A local port number or host
|
|
1293
|
+
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."
|
|
1250
1294
|
},
|
|
1251
1295
|
task: {
|
|
1252
1296
|
type: "string",
|
|
1253
|
-
description:
|
|
1297
|
+
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.'
|
|
1254
1298
|
},
|
|
1255
1299
|
fallback: {
|
|
1256
1300
|
type: "string",
|
|
1257
|
-
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."
|
|
1301
|
+
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."
|
|
1258
1302
|
}
|
|
1259
1303
|
},
|
|
1260
1304
|
required: [
|
|
@@ -1267,7 +1311,7 @@ var schema_default = {
|
|
|
1267
1311
|
properties: {
|
|
1268
1312
|
packageName: {
|
|
1269
1313
|
type: "string",
|
|
1270
|
-
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
|
|
1314
|
+
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."
|
|
1271
1315
|
},
|
|
1272
1316
|
development: {
|
|
1273
1317
|
$ref: "#/definitions/ChildDevelopment",
|
|
@@ -1275,11 +1319,11 @@ var schema_default = {
|
|
|
1275
1319
|
},
|
|
1276
1320
|
routing: {
|
|
1277
1321
|
$ref: "#/definitions/Routing",
|
|
1278
|
-
description: "Groups of path expressions that are routed to this application."
|
|
1322
|
+
description: "Groups of path expressions that are routed to this application.\n\nSee https://vercel.com/docs/microfrontends/path-routing."
|
|
1279
1323
|
},
|
|
1280
1324
|
assetPrefix: {
|
|
1281
1325
|
type: "string",
|
|
1282
|
-
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."
|
|
1326
|
+
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."
|
|
1283
1327
|
}
|
|
1284
1328
|
},
|
|
1285
1329
|
required: [
|
|
@@ -1295,15 +1339,15 @@ var schema_default = {
|
|
|
1295
1339
|
"number",
|
|
1296
1340
|
"string"
|
|
1297
1341
|
],
|
|
1298
|
-
description: "A local port number or host
|
|
1342
|
+
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."
|
|
1299
1343
|
},
|
|
1300
1344
|
task: {
|
|
1301
1345
|
type: "string",
|
|
1302
|
-
description:
|
|
1346
|
+
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.'
|
|
1303
1347
|
},
|
|
1304
1348
|
fallback: {
|
|
1305
1349
|
type: "string",
|
|
1306
|
-
description: "Fallback for local development, could point to any environment.
|
|
1350
|
+
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."
|
|
1307
1351
|
}
|
|
1308
1352
|
},
|
|
1309
1353
|
additionalProperties: false
|
|
@@ -1312,29 +1356,46 @@ var schema_default = {
|
|
|
1312
1356
|
type: "array",
|
|
1313
1357
|
items: {
|
|
1314
1358
|
$ref: "#/definitions/PathGroup"
|
|
1315
|
-
}
|
|
1359
|
+
},
|
|
1360
|
+
description: "A list of path groups that are routed to this application."
|
|
1316
1361
|
},
|
|
1317
1362
|
PathGroup: {
|
|
1318
1363
|
type: "object",
|
|
1319
1364
|
properties: {
|
|
1320
1365
|
group: {
|
|
1321
1366
|
type: "string",
|
|
1322
|
-
description: "
|
|
1367
|
+
description: "Group name for the paths."
|
|
1323
1368
|
},
|
|
1324
1369
|
flag: {
|
|
1325
1370
|
type: "string",
|
|
1326
|
-
description: "
|
|
1371
|
+
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."
|
|
1327
1372
|
},
|
|
1328
1373
|
paths: {
|
|
1329
1374
|
type: "array",
|
|
1330
1375
|
items: {
|
|
1331
1376
|
type: "string"
|
|
1332
|
-
}
|
|
1377
|
+
},
|
|
1378
|
+
description: "A list of path expressions that are routed to this application. See https://vercel.com/docs/microfrontends/path-routing#supported-path-expressions."
|
|
1333
1379
|
}
|
|
1334
1380
|
},
|
|
1335
1381
|
required: [
|
|
1336
1382
|
"paths"
|
|
1337
1383
|
],
|
|
1384
|
+
additionalProperties: false,
|
|
1385
|
+
description: "A group of paths that is routed to this application."
|
|
1386
|
+
},
|
|
1387
|
+
Options: {
|
|
1388
|
+
type: "object",
|
|
1389
|
+
properties: {
|
|
1390
|
+
disableOverrides: {
|
|
1391
|
+
type: "boolean",
|
|
1392
|
+
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."
|
|
1393
|
+
},
|
|
1394
|
+
localProxyPort: {
|
|
1395
|
+
type: "number",
|
|
1396
|
+
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."
|
|
1397
|
+
}
|
|
1398
|
+
},
|
|
1338
1399
|
additionalProperties: false
|
|
1339
1400
|
}
|
|
1340
1401
|
}
|
|
@@ -1353,19 +1414,19 @@ function formatAjvErrors(errors) {
|
|
|
1353
1414
|
return [];
|
|
1354
1415
|
}
|
|
1355
1416
|
const errorMessages = [];
|
|
1356
|
-
for (const
|
|
1357
|
-
if (
|
|
1417
|
+
for (const error2 of errors) {
|
|
1418
|
+
if (error2.instancePath === "" && (error2.keyword === "anyOf" || error2.keyword === "required" && error2.params.missingProperty === "partOf")) {
|
|
1358
1419
|
continue;
|
|
1359
1420
|
}
|
|
1360
|
-
const instancePath =
|
|
1421
|
+
const instancePath = error2.instancePath.slice(1);
|
|
1361
1422
|
const formattedInstancePath = instancePath === "" ? "at the root" : `in field ${instancePath}`;
|
|
1362
|
-
if (
|
|
1423
|
+
if (error2.keyword === "required" && error2.params.missingProperty === "routing" && instancePath.split("/").length === 2) {
|
|
1363
1424
|
errorMessages.push(
|
|
1364
1425
|
`Unable to infer if ${instancePath} is the default app or a child app. This usually means that there is another error in the configuration.`
|
|
1365
1426
|
);
|
|
1366
|
-
} else if (
|
|
1427
|
+
} else if (error2.keyword === "anyOf" && instancePath.split("/").length > 2) {
|
|
1367
1428
|
const anyOfErrors = errors.filter(
|
|
1368
|
-
(e) => e.instancePath ===
|
|
1429
|
+
(e) => e.instancePath === error2.instancePath && e.keyword !== "anyOf"
|
|
1369
1430
|
);
|
|
1370
1431
|
if (anyOfErrors.every((e) => e.keyword === "type")) {
|
|
1371
1432
|
const allowedTypes = LIST_FORMATTER2.format(
|
|
@@ -1381,13 +1442,13 @@ function formatAjvErrors(errors) {
|
|
|
1381
1442
|
`Invalid field for ${instancePath}. Possible error messages are ${LIST_FORMATTER2.format(anyOfErrors.map((e) => e.message ?? ""))}`
|
|
1382
1443
|
);
|
|
1383
1444
|
}
|
|
1384
|
-
} else if (
|
|
1445
|
+
} else if (error2.keyword === "additionalProperties" && !(error2.params.additionalProperty === "routing" && instancePath.split("/").length === 2)) {
|
|
1385
1446
|
errorMessages.push(
|
|
1386
|
-
`Property '${
|
|
1447
|
+
`Property '${error2.params.additionalProperty}' is not allowed ${formattedInstancePath}`
|
|
1387
1448
|
);
|
|
1388
|
-
} else if (
|
|
1449
|
+
} else if (error2.keyword === "required") {
|
|
1389
1450
|
errorMessages.push(
|
|
1390
|
-
`Property '${
|
|
1451
|
+
`Property '${error2.params.missingProperty}' is required ${formattedInstancePath}`
|
|
1391
1452
|
);
|
|
1392
1453
|
}
|
|
1393
1454
|
}
|
|
@@ -1400,8 +1461,8 @@ function validateSchema(configString) {
|
|
|
1400
1461
|
const isValid = validate(parsedConfig);
|
|
1401
1462
|
if (!isValid) {
|
|
1402
1463
|
throw new MicrofrontendError(
|
|
1403
|
-
`Invalid microfrontends config:${formatAjvErrors(validate.errors).map((
|
|
1404
|
-
- ${
|
|
1464
|
+
`Invalid microfrontends config:${formatAjvErrors(validate.errors).map((error2) => `
|
|
1465
|
+
- ${error2}`).join(
|
|
1405
1466
|
""
|
|
1406
1467
|
)}
|
|
1407
1468
|
|
|
@@ -1498,7 +1559,13 @@ var MicrofrontendsServer = class {
|
|
|
1498
1559
|
filePath,
|
|
1499
1560
|
cookies
|
|
1500
1561
|
} = {}) {
|
|
1562
|
+
logger.debug("[MFE Config] Starting config inference", {
|
|
1563
|
+
appName,
|
|
1564
|
+
directory: directory || process.cwd(),
|
|
1565
|
+
filePath
|
|
1566
|
+
});
|
|
1501
1567
|
if (filePath) {
|
|
1568
|
+
logger.debug("[MFE Config] Using explicit filePath:", filePath);
|
|
1502
1569
|
return MicrofrontendsServer.fromFile({
|
|
1503
1570
|
filePath,
|
|
1504
1571
|
cookies
|
|
@@ -1506,16 +1573,25 @@ var MicrofrontendsServer = class {
|
|
|
1506
1573
|
}
|
|
1507
1574
|
try {
|
|
1508
1575
|
const packageRoot = findPackageRoot(directory);
|
|
1576
|
+
logger.debug("[MFE Config] Package root:", packageRoot);
|
|
1509
1577
|
const applicationContext = getApplicationContext({
|
|
1510
1578
|
appName,
|
|
1511
1579
|
packageRoot
|
|
1512
1580
|
});
|
|
1581
|
+
logger.debug("[MFE Config] Application context:", applicationContext);
|
|
1513
1582
|
const customConfigFilename = process.env.VC_MICROFRONTENDS_CONFIG_FILE_NAME;
|
|
1583
|
+
if (customConfigFilename) {
|
|
1584
|
+
logger.debug(
|
|
1585
|
+
"[MFE Config] Custom config filename from VC_MICROFRONTENDS_CONFIG_FILE_NAME:",
|
|
1586
|
+
customConfigFilename
|
|
1587
|
+
);
|
|
1588
|
+
}
|
|
1514
1589
|
const maybeConfig = findConfig({
|
|
1515
1590
|
dir: packageRoot,
|
|
1516
1591
|
customConfigFilename
|
|
1517
1592
|
});
|
|
1518
1593
|
if (maybeConfig) {
|
|
1594
|
+
logger.debug("[MFE Config] Config found at package root:", maybeConfig);
|
|
1519
1595
|
return MicrofrontendsServer.fromFile({
|
|
1520
1596
|
filePath: maybeConfig,
|
|
1521
1597
|
cookies
|
|
@@ -1523,42 +1599,78 @@ var MicrofrontendsServer = class {
|
|
|
1523
1599
|
}
|
|
1524
1600
|
const repositoryRoot = findRepositoryRoot();
|
|
1525
1601
|
const isMonorepo2 = isMonorepo({ repositoryRoot });
|
|
1602
|
+
logger.debug(
|
|
1603
|
+
"[MFE Config] Repository root:",
|
|
1604
|
+
repositoryRoot,
|
|
1605
|
+
"Is monorepo:",
|
|
1606
|
+
isMonorepo2
|
|
1607
|
+
);
|
|
1526
1608
|
const configFromEnv = process.env.VC_MICROFRONTENDS_CONFIG;
|
|
1527
1609
|
if (typeof configFromEnv === "string") {
|
|
1610
|
+
logger.debug(
|
|
1611
|
+
"[MFE Config] Checking VC_MICROFRONTENDS_CONFIG:",
|
|
1612
|
+
configFromEnv
|
|
1613
|
+
);
|
|
1528
1614
|
const maybeConfigFromEnv = (0, import_node_path8.resolve)(packageRoot, configFromEnv);
|
|
1529
1615
|
if (maybeConfigFromEnv) {
|
|
1616
|
+
logger.debug(
|
|
1617
|
+
"[MFE Config] Config loaded from VC_MICROFRONTENDS_CONFIG:",
|
|
1618
|
+
maybeConfigFromEnv
|
|
1619
|
+
);
|
|
1530
1620
|
return MicrofrontendsServer.fromFile({
|
|
1531
1621
|
filePath: maybeConfigFromEnv,
|
|
1532
1622
|
cookies
|
|
1533
1623
|
});
|
|
1534
1624
|
}
|
|
1535
1625
|
} else {
|
|
1626
|
+
const vercelDir = (0, import_node_path8.join)(packageRoot, ".vercel");
|
|
1627
|
+
logger.debug(
|
|
1628
|
+
"[MFE Config] Searching for config in .vercel directory:",
|
|
1629
|
+
vercelDir
|
|
1630
|
+
);
|
|
1536
1631
|
const maybeConfigFromVercel = findConfig({
|
|
1537
|
-
dir:
|
|
1632
|
+
dir: vercelDir,
|
|
1538
1633
|
customConfigFilename
|
|
1539
1634
|
});
|
|
1540
1635
|
if (maybeConfigFromVercel) {
|
|
1636
|
+
logger.debug(
|
|
1637
|
+
"[MFE Config] Config found in .vercel directory:",
|
|
1638
|
+
maybeConfigFromVercel
|
|
1639
|
+
);
|
|
1541
1640
|
return MicrofrontendsServer.fromFile({
|
|
1542
1641
|
filePath: maybeConfigFromVercel,
|
|
1543
1642
|
cookies
|
|
1544
1643
|
});
|
|
1545
1644
|
}
|
|
1546
1645
|
if (isMonorepo2) {
|
|
1646
|
+
logger.debug(
|
|
1647
|
+
"[MFE Config] Inferring microfrontends location in monorepo for application:",
|
|
1648
|
+
applicationContext.name
|
|
1649
|
+
);
|
|
1547
1650
|
const defaultPackage = inferMicrofrontendsLocation({
|
|
1548
1651
|
repositoryRoot,
|
|
1549
1652
|
applicationContext,
|
|
1550
1653
|
customConfigFilename
|
|
1551
1654
|
});
|
|
1655
|
+
logger.debug(
|
|
1656
|
+
"[MFE Config] Inferred package location:",
|
|
1657
|
+
defaultPackage
|
|
1658
|
+
);
|
|
1552
1659
|
const maybeConfigFromDefault = findConfig({
|
|
1553
1660
|
dir: defaultPackage,
|
|
1554
1661
|
customConfigFilename
|
|
1555
1662
|
});
|
|
1556
1663
|
if (maybeConfigFromDefault) {
|
|
1664
|
+
logger.debug(
|
|
1665
|
+
"[MFE Config] Config found in inferred package:",
|
|
1666
|
+
maybeConfigFromDefault
|
|
1667
|
+
);
|
|
1557
1668
|
return MicrofrontendsServer.fromFile({
|
|
1558
1669
|
filePath: maybeConfigFromDefault,
|
|
1559
1670
|
cookies
|
|
1560
1671
|
});
|
|
1561
1672
|
}
|
|
1673
|
+
logger.debug("[MFE Config] No config found in inferred package");
|
|
1562
1674
|
}
|
|
1563
1675
|
}
|
|
1564
1676
|
throw new MicrofrontendError(
|
|
@@ -1584,8 +1696,13 @@ var MicrofrontendsServer = class {
|
|
|
1584
1696
|
cookies
|
|
1585
1697
|
}) {
|
|
1586
1698
|
try {
|
|
1699
|
+
logger.debug("[MFE Config] Reading config from file:", filePath);
|
|
1587
1700
|
const configJson = import_node_fs7.default.readFileSync(filePath, "utf-8");
|
|
1588
1701
|
const config = MicrofrontendsServer.validate(configJson);
|
|
1702
|
+
logger.debug(
|
|
1703
|
+
"[MFE Config] Config loaded with applications:",
|
|
1704
|
+
Object.keys(config.applications)
|
|
1705
|
+
);
|
|
1589
1706
|
return new MicrofrontendsServer({
|
|
1590
1707
|
config,
|
|
1591
1708
|
overrides: cookies ? parseOverrides(cookies) : void 0
|
|
@@ -1686,17 +1803,10 @@ function transform3(args) {
|
|
|
1686
1803
|
};
|
|
1687
1804
|
}
|
|
1688
1805
|
|
|
1689
|
-
// src/next/utils/route-to-local-proxy.ts
|
|
1690
|
-
function routeToLocalProxy() {
|
|
1691
|
-
const isDevEnv = (process.env.VERCEL_ENV ?? "development") === "development";
|
|
1692
|
-
return isDevEnv && Boolean(process.env.TURBO_TASK_HAS_MFE_PROXY);
|
|
1693
|
-
}
|
|
1694
|
-
|
|
1695
1806
|
// src/next/config/transforms/redirects.ts
|
|
1696
1807
|
function transform4(args) {
|
|
1697
|
-
const { next, microfrontend
|
|
1698
|
-
const
|
|
1699
|
-
const requireLocalProxyHeader = routeToLocalProxy() && !isProduction2 && !process.env.MFE_DISABLE_LOCAL_PROXY_REWRITE;
|
|
1808
|
+
const { next, microfrontend } = args;
|
|
1809
|
+
const requireLocalProxyHeader = localProxyIsRunning() && !process.env.MFE_DISABLE_LOCAL_PROXY_REWRITE;
|
|
1700
1810
|
if (requireLocalProxyHeader) {
|
|
1701
1811
|
const proxyRedirects = [
|
|
1702
1812
|
{
|
|
@@ -1723,17 +1833,15 @@ function transform4(args) {
|
|
|
1723
1833
|
} else {
|
|
1724
1834
|
next.redirects = async () => proxyRedirects;
|
|
1725
1835
|
}
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
`${indent}${header}
|
|
1836
|
+
const indent = " ".repeat(4);
|
|
1837
|
+
const header = "redirects";
|
|
1838
|
+
const separator = "\u23AF".repeat(header.length);
|
|
1839
|
+
logger.debug(
|
|
1840
|
+
`${indent}${header}
|
|
1732
1841
|
${indent}${separator}
|
|
1733
1842
|
${indent} - Automatically redirecting all requests to local microfrontends proxy
|
|
1734
1843
|
`
|
|
1735
|
-
|
|
1736
|
-
}
|
|
1844
|
+
);
|
|
1737
1845
|
}
|
|
1738
1846
|
return { next };
|
|
1739
1847
|
}
|
|
@@ -1754,22 +1862,18 @@ function transform5(args) {
|
|
|
1754
1862
|
|
|
1755
1863
|
// src/next/config/transforms/rewrites.ts
|
|
1756
1864
|
function debugRewrites(rewrites) {
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
return `${indent} ${idx + 1}. ${paddedSource} \u2192 ${route.destination}`;
|
|
1767
|
-
}).join("\n");
|
|
1768
|
-
console.log(`${indent}${header}
|
|
1865
|
+
const indent = " ".repeat(4);
|
|
1866
|
+
const header = "rewrites (source \u2192 destination)";
|
|
1867
|
+
const separator = "\u23AF".repeat(header.length);
|
|
1868
|
+
const maxSourceLength = Math.max(...rewrites.map((key) => key.source.length));
|
|
1869
|
+
const table = rewrites.map((route, idx) => {
|
|
1870
|
+
const paddedSource = route.source.padEnd(maxSourceLength);
|
|
1871
|
+
return `${indent} ${idx + 1}. ${paddedSource} \u2192 ${route.destination}`;
|
|
1872
|
+
}).join("\n");
|
|
1873
|
+
logger.debug(`${indent}${header}
|
|
1769
1874
|
${indent}${separator}
|
|
1770
1875
|
${table}
|
|
1771
1876
|
`);
|
|
1772
|
-
}
|
|
1773
1877
|
}
|
|
1774
1878
|
function rewritesMapToArr(rewrites) {
|
|
1775
1879
|
return Array.from(rewrites.entries()).flatMap(([source, rewrite]) => {
|
|
@@ -1968,20 +2072,18 @@ var transforms = {
|
|
|
1968
2072
|
|
|
1969
2073
|
// src/next/config/env.ts
|
|
1970
2074
|
function debugEnv(env) {
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
const
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
console.log(`${indent}${header}
|
|
2075
|
+
const indent = " ".repeat(4);
|
|
2076
|
+
const header = "env (key \u2192 val)";
|
|
2077
|
+
const separator = "\u23AF".repeat(header.length);
|
|
2078
|
+
const maxKeyLength = Math.max(...Object.keys(env).map((key) => key.length));
|
|
2079
|
+
const table = Object.keys(env).map((key, idx) => {
|
|
2080
|
+
const paddedKey = key.padEnd(maxKeyLength);
|
|
2081
|
+
return `${indent} ${idx + 1}. ${paddedKey} = ${env[key]}`;
|
|
2082
|
+
}).join("\n");
|
|
2083
|
+
logger.debug(`${indent}${header}
|
|
1981
2084
|
${indent}${separator}
|
|
1982
2085
|
${table}
|
|
1983
2086
|
`);
|
|
1984
|
-
}
|
|
1985
2087
|
}
|
|
1986
2088
|
function setEnvironment({
|
|
1987
2089
|
app,
|
|
@@ -2017,12 +2119,6 @@ function setEnvironment({
|
|
|
2017
2119
|
function typedEntries(obj) {
|
|
2018
2120
|
return Object.entries(obj);
|
|
2019
2121
|
}
|
|
2020
|
-
function isProduction(opts) {
|
|
2021
|
-
if (opts?.isProduction) {
|
|
2022
|
-
return opts.isProduction();
|
|
2023
|
-
}
|
|
2024
|
-
return process.env.VERCEL_ENV === "production";
|
|
2025
|
-
}
|
|
2026
2122
|
function withMicrofrontends(nextConfig, opts) {
|
|
2027
2123
|
if (opts?.debug) {
|
|
2028
2124
|
process.env.MFE_DEBUG = "true";
|
|
@@ -2037,7 +2133,7 @@ function withMicrofrontends(nextConfig, opts) {
|
|
|
2037
2133
|
let next = { ...nextConfig };
|
|
2038
2134
|
for (const [key, transform8] of typedEntries(transforms)) {
|
|
2039
2135
|
if (opts?.skipTransforms?.includes(key)) {
|
|
2040
|
-
|
|
2136
|
+
logger.info(`Skipping ${key} transform`);
|
|
2041
2137
|
continue;
|
|
2042
2138
|
}
|
|
2043
2139
|
try {
|
|
@@ -2046,13 +2142,12 @@ function withMicrofrontends(nextConfig, opts) {
|
|
|
2046
2142
|
next,
|
|
2047
2143
|
microfrontend: microfrontends.config,
|
|
2048
2144
|
opts: {
|
|
2049
|
-
isProduction: isProduction(opts),
|
|
2050
2145
|
supportPagesRouter: opts?.supportPagesRouter
|
|
2051
2146
|
}
|
|
2052
2147
|
});
|
|
2053
2148
|
next = transformedConfig.next;
|
|
2054
2149
|
} catch (e) {
|
|
2055
|
-
|
|
2150
|
+
logger.error("Error transforming next config", e);
|
|
2056
2151
|
throw e;
|
|
2057
2152
|
}
|
|
2058
2153
|
}
|