feat(mfe): support user specified local proxy (#9695)
### Description
Adds support for users specifying a custom proxy command instead of the
default MFE one. This is done by having a `proxy` script on the default
application.
The interface the proxy must implement:
- First argument is the path to the `microfrontends.json` file
- Next arguments are `--name` and a list of applications currently being
run. These will be a subset of the `applications` section in the passed
configuration file.
The schema that Turborepo will require of `microfrontends.json` is very
permissive to allow for extensibility:
- `version?: string` field can be omitted or must be `"2"` explicitly
- `applications: {[string]: { dev?: string, local?: { port:?: number } }
}`: keys must match the `name`s in `package.json`
To use the provided `@turbo/proxy` implementation, `microfrontends.json`
will need to match the existing MFE schema.
### Testing Instructions
Some unit tests. A quick sample repo with following changes from a fresh
`create-turbo`:
```
[0 olszewski@chriss-mbp] /tmp/turborepo-next-basic $ git diff HEAD^1
diff --git a/apps/docs/package.json b/apps/docs/package.json
index 78f191e..a976901 100644
--- a/apps/docs/package.json
+++ b/apps/docs/package.json
@@ -4,7 +4,7 @@
"type": "module",
"private": true,
"scripts": {
- "dev": "next dev --turbopack",
+ "dev": "next dev --turbopack --port=${TURBO_PORT:-3001}",
"build": "next build",
"start": "next start",
"lint": "next lint --max-warnings 0",
diff --git a/apps/web/microfrontends.json b/apps/web/microfrontends.json
new file mode 100644
index 0000000..b940ac9
--- /dev/null
+++ b/apps/web/microfrontends.json
@@ -0,0 +1,6 @@
+{
+ "applications": {
+ "web": {},
+ "docs": {}
+ }
+}
diff --git a/apps/web/package.json b/apps/web/package.json
index 8016401..50f985d 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -4,11 +4,12 @@
"type": "module",
"private": true,
"scripts": {
- "dev": "next dev --turbopack",
+ "dev": "next dev --turbopack --port=${TURBO_PORT:-3000}",
"build": "next build",
"start": "next start",
"lint": "next lint --max-warnings 0",
- "check-types": "tsc --noEmit"
+ "check-types": "tsc --noEmit",
+ "proxy": "./proxy.sh"
},
"dependencies": {
"@repo/ui": "workspace:*",
diff --git a/apps/web/proxy.sh b/apps/web/proxy.sh
new file mode 100755
index 0000000..6094f03
--- /dev/null
+++ b/apps/web/proxy.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+echo "Proxy ran with $@"
+cat
```
Now if we run the dev task:
```
[0 olszewski@chriss-mbp] /tmp/turborepo-next-basic $ turbo_dev --skip-infer dev
turbo 2.3.4-canary.6
• Packages in scope: @repo/eslint-config, @repo/typescript-config, @repo/ui, docs, web
• Running dev in 5 packages
• Remote caching disabled
┌ web#proxy > cache bypass, force executing 257fe50862891df3
│
│
│ > web@0.1.0 proxy /private/tmp/turborepo-next-basic/apps/web
│ > ./proxy.sh "/private/tmp/turborepo-next-basic/apps/web/microfrontends.json" "--names" "docs" "web"
│
│ Proxy ran with /private/tmp/turborepo-next-basic/apps/web/microfrontends.json --names docs web
└────>
┌ web#dev > cache bypass, force executing ab1756f2a3090b20
│
│ > web@0.1.0 dev /private/tmp/turborepo-next-basic/apps/web
│ > next dev --turbopack --port=${TURBO_PORT:-3000}
│
│ ▲ Next.js 15.1.0 (Turbopack)
│ - Local: http://localhost:5588
│ - Network: http://192.168.86.46:5588
│
│ ✓ Starting...
│ ✓ Ready in 670ms
└────>
┌ docs#dev > cache bypass, force executing 30705dbd6c0968b4
│
│ > docs@0.1.0 dev /private/tmp/turborepo-next-basic/apps/docs
│ > next dev --turbopack --port=${TURBO_PORT:-3001}
│
│ ▲ Next.js 15.1.0 (Turbopack)
│ - Local: http://localhost:6955
│ - Network: http://192.168.86.46:6955
│
│ ✓ Starting...
│ ✓ Ready in 671ms
└────>
```
Things to take note of:
- First arg is the path to the `microfrontends.json` configuration file.
- `--names` arg for the proxy matches the names of the applications that
have dev tasks running
- The dev tasks got ran with `TURBO_PORT` which was derived from the
application name