From 2d455613f69086430abc06b31d203b0e628c6d9e Mon Sep 17 00:00:00 2001 From: 2heal1 Date: Tue, 1 Apr 2025 16:48:30 +0800 Subject: [PATCH 1/6] chore(modern-js-plugin): warn if header origin is not specified --- .changeset/shy-ghosts-worry.md | 5 +++ apps/modernjs/project.json | 2 +- packages/modernjs/src/cli/configPlugin.ts | 45 ++++++++++++++++++++--- 3 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 .changeset/shy-ghosts-worry.md diff --git a/.changeset/shy-ghosts-worry.md b/.changeset/shy-ghosts-worry.md new file mode 100644 index 00000000000..b1553837565 --- /dev/null +++ b/.changeset/shy-ghosts-worry.md @@ -0,0 +1,5 @@ +--- +'@module-federation/modern-js': patch +--- + +chore(modern-js-plugin): warn if header origin is not specified diff --git a/apps/modernjs/project.json b/apps/modernjs/project.json index 953912b3513..140bf2f4304 100644 --- a/apps/modernjs/project.json +++ b/apps/modernjs/project.json @@ -63,7 +63,7 @@ "parallel": true, "commands": [ { - "command": "lsof -i :8080 || nx run modernjs:serve & echo 'done'", + "command": "lsof -i :4001 || nx run modernjs:serve & echo 'done'", "forwardAllArgs": false }, { diff --git a/packages/modernjs/src/cli/configPlugin.ts b/packages/modernjs/src/cli/configPlugin.ts index 99dc5550d9c..0740ded58c7 100644 --- a/packages/modernjs/src/cli/configPlugin.ts +++ b/packages/modernjs/src/cli/configPlugin.ts @@ -10,6 +10,7 @@ import { isWebTarget, skipByTarget, } from './utils'; +import logger from './logger'; export function setEnv(enableSSR: boolean) { if (enableSSR) { @@ -77,15 +78,47 @@ export const moduleFederationConfigPlugin = ( } } + const devServerConfig = modernjsConfig.tools?.devServer; + const corsWarnMsgs = [ + ', which exposes your dev server to all origins, potentially compromising your source code security. It is recommended to specify an allowlist of trusted origins instead.', + ]; + if ( + typeof devServerConfig !== 'object' || + !('headers' in devServerConfig) + ) { + corsWarnMsgs.unshift( + 'Detect devServer.headers is empty, mf modern plugin will add default cors header: devServer.headers["Access-Control-Allow-Headers"] = "*"', + ); + } else if ( + devServerConfig.headers?.['Access-Control-Allow-Headers'] === '*' + ) { + corsWarnMsgs.unshift( + 'Detect devServer.headers["Access-Control-Allow-Headers"] is *', + ); + } + + const exposes = userConfig.csrConfig?.exposes; + const hasExposes = + exposes && Array.isArray(exposes) + ? exposes.length + : Object.keys(exposes ?? {}).length; + + if (corsWarnMsgs.length > 1 && hasExposes) { + logger.warn(corsWarnMsgs.join('')); + } + + const corsHeaders = hasExposes + ? { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': + 'GET, POST, PUT, DELETE, PATCH, OPTIONS', + 'Access-Control-Allow-Headers': '*', + } + : undefined; return { tools: { devServer: { - headers: { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': - 'GET, POST, PUT, DELETE, PATCH, OPTIONS', - 'Access-Control-Allow-Headers': '*', - }, + headers: corsHeaders, }, }, source: { From da58e517eb9c61149c1cbca877350c29760efc11 Mon Sep 17 00:00:00 2001 From: 2heal1 Date: Tue, 1 Apr 2025 17:21:59 +0800 Subject: [PATCH 2/6] chore: error info add hostName --- packages/runtime-core/src/plugins/snapshot/SnapshotHandler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/runtime-core/src/plugins/snapshot/SnapshotHandler.ts b/packages/runtime-core/src/plugins/snapshot/SnapshotHandler.ts index 5bcd4d99236..42dfef06fde 100644 --- a/packages/runtime-core/src/plugins/snapshot/SnapshotHandler.ts +++ b/packages/runtime-core/src/plugins/snapshot/SnapshotHandler.ts @@ -326,6 +326,7 @@ export class SnapshotHandler { { manifestUrl, moduleName: moduleInfo.name, + hostName: this.HostInstance.options.name, }, `${err}`, ), From a5cde4b473732743d71cab7b6f441c9b14a17b35 Mon Sep 17 00:00:00 2001 From: 2heal1 Date: Tue, 1 Apr 2025 17:27:37 +0800 Subject: [PATCH 3/6] chore: wait response content-type is application/json --- .github/workflows/e2e-modern-ssr.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/e2e-modern-ssr.yml b/.github/workflows/e2e-modern-ssr.yml index 896a409e087..a2a7d3266b3 100644 --- a/.github/workflows/e2e-modern-ssr.yml +++ b/.github/workflows/e2e-modern-ssr.yml @@ -48,12 +48,16 @@ jobs: lsof -ti tcp:3050,3051,3052,3053,3054,3055,3056 | xargs -r kill && pnpm run app:modern:dev & sleep 30 && - npx wait-on http://127.0.0.1:3051/mf-manifest.json && - npx wait-on http://127.0.0.1:3053/mf-manifest.json && - npx wait-on http://127.0.0.1:3055/mf-manifest.json && - npx wait-on http://127.0.0.1:3056/mf-manifest.json && - npx wait-on http://127.0.0.1:3054/mf-manifest.json && - npx wait-on http://127.0.0.1:3052/mf-manifest.json && - npx wait-on http://127.0.0.1:3050/mf-manifest.json && + # wait response content-type is application/json + for port in 3050 3051 3052 3053 3054 3055 3056; do + while true; do + response=$(curl -s -I http://127.0.0.1:$port/mf-manifest.json) + content_type=$(echo "$response" | grep -i "Content-Type" | awk '{print $2}' | tr -d '\r') + if [[ $content_type == *"application/json"* ]]; then + break + fi + sleep 1 + done + done npx nx run modernjs-ssr-host:e2e && lsof -ti tcp:3050,3051,3052,3053,3054,3055,3056 | xargs kill From d712ddda5a90201d718d70e27f0530a269b23315 Mon Sep 17 00:00:00 2001 From: 2heal1 Date: Wed, 2 Apr 2025 11:12:17 +0800 Subject: [PATCH 4/6] chore: only judge content-type --- .github/workflows/e2e-modern-ssr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e-modern-ssr.yml b/.github/workflows/e2e-modern-ssr.yml index a2a7d3266b3..8268232b7f6 100644 --- a/.github/workflows/e2e-modern-ssr.yml +++ b/.github/workflows/e2e-modern-ssr.yml @@ -53,7 +53,7 @@ jobs: while true; do response=$(curl -s -I http://127.0.0.1:$port/mf-manifest.json) content_type=$(echo "$response" | grep -i "Content-Type" | awk '{print $2}' | tr -d '\r') - if [[ $content_type == *"application/json"* ]]; then + if [[ $content_type != *"text/html"* ]]; then break fi sleep 1 From 8b9b20fc0abf4c4c2c547ea2cc1fad2b1ffc0fd4 Mon Sep 17 00:00:00 2001 From: 2heal1 Date: Wed, 2 Apr 2025 11:47:21 +0800 Subject: [PATCH 5/6] chore: update docs --- .../docs/en/guide/troubleshooting/other.mdx | 12 +++++++++++- .../docs/zh/guide/troubleshooting/other.mdx | 12 +++++++++++- packages/modernjs/src/cli/configPlugin.ts | 12 +++--------- packages/rsbuild-plugin/src/cli/index.ts | 8 ++++++++ 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/apps/website-new/docs/en/guide/troubleshooting/other.mdx b/apps/website-new/docs/en/guide/troubleshooting/other.mdx index ef230439e9d..d457f55be79 100644 --- a/apps/website-new/docs/en/guide/troubleshooting/other.mdx +++ b/apps/website-new/docs/en/guide/troubleshooting/other.mdx @@ -79,4 +79,14 @@ new ModuleFederationPlugin({ * If shared is provided from online host, use [Module Federation DevTools](../basic/chrome-devtool), and click `Enable HMR` button . -![](@public/guide/chrome-devtools/mf-devtool-hmr.jpg) \ No newline at end of file +![](@public/guide/chrome-devtools/mf-devtool-hmr.jpg) + +## CORS warn + +When `exposes` is set in the project, it will be regarded as a producer. To ensure that the producer resources can be loaded normally by consumers, `@module-federation/modern-js` and `@module-federation/rsbuild-plugin` will set `Access-Control-Allow-Origin` to `*` and issue a warning at the same time. + +#### Solutions + +* [Modern.js]: Set [devServer.headers](https://modernjs.dev/configure/app/tools/dev-server.html#headers) value to the specified domain whitelist instead of `*` + +* [Rsbuild]: Set [server.cors.origin](https://rsbuild.dev/config/server/cors#origin) value to the specified domain whitelist instead of `*` \ No newline at end of file diff --git a/apps/website-new/docs/zh/guide/troubleshooting/other.mdx b/apps/website-new/docs/zh/guide/troubleshooting/other.mdx index 0b6c57b3104..1921cc3409e 100644 --- a/apps/website-new/docs/zh/guide/troubleshooting/other.mdx +++ b/apps/website-new/docs/zh/guide/troubleshooting/other.mdx @@ -53,4 +53,14 @@ Uncaught TypeError: Cannot read properties on null (reading `useState`) * 若 shared 提供方是线上的 react ,那么需要使用 [Module Federation DevTools](../basic/chrome-devtool),并点击 `Enable HMR` 按钮 -![](@public/guide/chrome-devtools/mf-devtool-hmr.jpg) \ No newline at end of file +![](@public/guide/chrome-devtools/mf-devtool-hmr.jpg) + +## CORS 警告 + +当项目中设置了 `exposes` ,会被视为生产者,为保证生产者资源能正常被消费者加载,`@module-federation/modern-js`、`@module-federation/rsbuild-plugin` 会设置 `Access-Control-Allow-Origin` 为 `*` ,并同时发出警告。 + +#### 解决方案 + +* [Modern.js]: 设置 [devServer.headers](https://modernjs.dev/configure/app/tools/dev-server.html#headers) 值为指定的域名白名单而非 `*` + +* [Rsbuild]: 设置 [server.cors.origin](https://rsbuild.dev/config/server/cors#origin) 值为指定的域名白名单而非 `*` diff --git a/packages/modernjs/src/cli/configPlugin.ts b/packages/modernjs/src/cli/configPlugin.ts index 0740ded58c7..0e6d0d2d743 100644 --- a/packages/modernjs/src/cli/configPlugin.ts +++ b/packages/modernjs/src/cli/configPlugin.ts @@ -80,20 +80,14 @@ export const moduleFederationConfigPlugin = ( const devServerConfig = modernjsConfig.tools?.devServer; const corsWarnMsgs = [ - ', which exposes your dev server to all origins, potentially compromising your source code security. It is recommended to specify an allowlist of trusted origins instead.', + 'View https://module-federation.io/guide/troubleshooting/other.html#cors-warn for more details.', ]; if ( typeof devServerConfig !== 'object' || !('headers' in devServerConfig) ) { corsWarnMsgs.unshift( - 'Detect devServer.headers is empty, mf modern plugin will add default cors header: devServer.headers["Access-Control-Allow-Headers"] = "*"', - ); - } else if ( - devServerConfig.headers?.['Access-Control-Allow-Headers'] === '*' - ) { - corsWarnMsgs.unshift( - 'Detect devServer.headers["Access-Control-Allow-Headers"] is *', + 'Detect devServer.headers is empty, mf modern plugin will add default cors header: devServer.headers["Access-Control-Allow-Headers"] = "*", which exposes your dev server to all origins, potentially compromising your source code security. It is recommended to specify an allowlist of trusted origins instead.', ); } @@ -104,7 +98,7 @@ export const moduleFederationConfigPlugin = ( : Object.keys(exposes ?? {}).length; if (corsWarnMsgs.length > 1 && hasExposes) { - logger.warn(corsWarnMsgs.join('')); + logger.warn(corsWarnMsgs.join('\n')); } const corsHeaders = hasExposes diff --git a/packages/rsbuild-plugin/src/cli/index.ts b/packages/rsbuild-plugin/src/cli/index.ts index 062f9012bf7..a74e4e66355 100644 --- a/packages/rsbuild-plugin/src/cli/index.ts +++ b/packages/rsbuild-plugin/src/cli/index.ts @@ -182,6 +182,14 @@ export const pluginModuleFederation = ( // Allow remote modules to be loaded by setting CORS headers // This is required for MF to work properly across different origins config.server.headers ||= {}; + if (!config.server.headers['Access-Control-Allow-Origin']) { + const corsWarnMsgs = [ + 'Detect devServer.headers is empty, mf modern plugin will add default cors header: devServer.headers["Access-Control-Allow-Headers"] = "*", which exposes your dev server to all origins, potentially compromising your source code security. It is recommended to specify an allowlist of trusted origins instead.', + 'View https://module-federation.io/guide/troubleshooting/other.html#cors-warn for more details.', + ]; + + logger.warn(corsWarnMsgs.join('\n')); + } config.server.headers['Access-Control-Allow-Origin'] ||= '*'; // For remote modules, Rsbuild should send the ws request to the provider's dev server. From 993fc914d528436280bd8a7a36c7d4730b4a5402 Mon Sep 17 00:00:00 2001 From: 2heal1 Date: Wed, 2 Apr 2025 11:53:05 +0800 Subject: [PATCH 6/6] chore: remove --- packages/modernjs/src/cli/configPlugin.ts | 2 +- packages/rsbuild-plugin/src/cli/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/modernjs/src/cli/configPlugin.ts b/packages/modernjs/src/cli/configPlugin.ts index 0e6d0d2d743..b1d83bae57f 100644 --- a/packages/modernjs/src/cli/configPlugin.ts +++ b/packages/modernjs/src/cli/configPlugin.ts @@ -87,7 +87,7 @@ export const moduleFederationConfigPlugin = ( !('headers' in devServerConfig) ) { corsWarnMsgs.unshift( - 'Detect devServer.headers is empty, mf modern plugin will add default cors header: devServer.headers["Access-Control-Allow-Headers"] = "*", which exposes your dev server to all origins, potentially compromising your source code security. It is recommended to specify an allowlist of trusted origins instead.', + 'Detect devServer.headers is empty, mf modern plugin will add default cors header: devServer.headers["Access-Control-Allow-Headers"] = "*". It is recommended to specify an allowlist of trusted origins instead.', ); } diff --git a/packages/rsbuild-plugin/src/cli/index.ts b/packages/rsbuild-plugin/src/cli/index.ts index a74e4e66355..14cce148601 100644 --- a/packages/rsbuild-plugin/src/cli/index.ts +++ b/packages/rsbuild-plugin/src/cli/index.ts @@ -184,7 +184,7 @@ export const pluginModuleFederation = ( config.server.headers ||= {}; if (!config.server.headers['Access-Control-Allow-Origin']) { const corsWarnMsgs = [ - 'Detect devServer.headers is empty, mf modern plugin will add default cors header: devServer.headers["Access-Control-Allow-Headers"] = "*", which exposes your dev server to all origins, potentially compromising your source code security. It is recommended to specify an allowlist of trusted origins instead.', + 'Detect devServer.headers is empty, mf modern plugin will add default cors header: devServer.headers["Access-Control-Allow-Headers"] = "*". It is recommended to specify an allowlist of trusted origins instead.', 'View https://module-federation.io/guide/troubleshooting/other.html#cors-warn for more details.', ];