From 4bab9bd0ea6cd745bf144d382db8d6c868d3ab5f Mon Sep 17 00:00:00 2001 From: Andrei Fiodorov Date: Sun, 23 Apr 2023 14:54:49 +0200 Subject: [PATCH 1/4] feat(react): refactor util `getModuleFederationConfig` to avoid to pass function to determinate the remote url --- packages/react/src/module-federation/utils.ts | 32 +++++++++++++++++-- .../with-module-federation-ssr.ts | 21 +----------- .../with-module-federation.ts | 21 +----------- 3 files changed, 31 insertions(+), 43 deletions(-) diff --git a/packages/react/src/module-federation/utils.ts b/packages/react/src/module-federation/utils.ts index 47d28700d5c71..5ed4c749e0423 100644 --- a/packages/react/src/module-federation/utils.ts +++ b/packages/react/src/module-federation/utils.ts @@ -6,16 +6,38 @@ import { mapRemotes, mapRemotesForSSR, ModuleFederationConfig, - ProjectConfiguration, ProjectGraph, readCachedProjectGraph, sharePackages, shareWorkspaceLibraries, } from '@nx/devkit'; +import { readCachedProjectConfiguration } from 'nx/src/project-graph/project-graph'; + +export function getFunctionDeterminateRemoteUrl(isServer: boolean = false) { + const target = isServer ? 'serve-server' : 'serve'; + const remoteEntry = isServer ? 'server/remoteEntry.js' : 'remoteEntry.js'; + + return function (remote: string) { + const remoteConfiguration = readCachedProjectConfiguration(remote); + const serveTarget = remoteConfiguration?.targets?.[target]; + + if (!serveTarget) { + throw new Error( + `Cannot automatically determine URL of remote (${remote}). Looked for property "host" in the project's "serve-server" target.\n + You can also use the tuple syntax in your webpack config to configure your remotes. e.g. \`remotes: [['remote1', 'http://localhost:4201']]\`` + ); + } + + const host = serveTarget.options?.host ?? 'http://localhost'; + const port = serveTarget.options?.port ?? 4201; + return `${ + host.endsWith('/') ? host.slice(0, -1) : host + }:${port}/${remoteEntry}`; + }; +} export async function getModuleFederationConfig( mfConfig: ModuleFederationConfig, - determineRemoteUrl: (remote: string) => string, options: { isServer: boolean } = { isServer: false } ) { let projectGraph: ProjectGraph; @@ -69,7 +91,11 @@ export async function getModuleFederationConfig( const mappedRemotes = !mfConfig.remotes || mfConfig.remotes.length === 0 ? {} - : mapRemotesFunction(mfConfig.remotes, 'js', determineRemoteUrl); + : mapRemotesFunction( + mfConfig.remotes, + 'js', + getFunctionDeterminateRemoteUrl(options.isServer) + ); return { sharedLibraries, sharedDependencies, mappedRemotes }; } diff --git a/packages/react/src/module-federation/with-module-federation-ssr.ts b/packages/react/src/module-federation/with-module-federation-ssr.ts index 807e7ec160b50..31ab9a5b8cb93 100644 --- a/packages/react/src/module-federation/with-module-federation-ssr.ts +++ b/packages/react/src/module-federation/with-module-federation-ssr.ts @@ -1,32 +1,13 @@ import { ModuleFederationConfig } from '@nx/devkit'; -import { readCachedProjectConfiguration } from 'nx/src/project-graph/project-graph'; import { getModuleFederationConfig } from './utils'; -function determineRemoteUrl(remote: string) { - const remoteConfiguration = readCachedProjectConfiguration(remote); - const serveTarget = remoteConfiguration?.targets?.['serve-server']; - - if (!serveTarget) { - throw new Error( - `Cannot automatically determine URL of remote (${remote}). Looked for property "host" in the project's "serve-server" target.\n - You can also use the tuple syntax in your webpack config to configure your remotes. e.g. \`remotes: [['remote1', 'http://localhost:4201']]\`` - ); - } - - const host = serveTarget.options?.host ?? 'http://localhost'; - const port = serveTarget.options?.port ?? 4201; - return `${ - host.endsWith('/') ? host.slice(0, -1) : host - }:${port}/server/remoteEntry.js`; -} - export async function withModuleFederationForSSR( options: ModuleFederationConfig ) { const reactWebpackConfig = require('../../plugins/webpack'); const { sharedLibraries, sharedDependencies, mappedRemotes } = - await getModuleFederationConfig(options, determineRemoteUrl, { + await getModuleFederationConfig(options, { isServer: true, }); diff --git a/packages/react/src/module-federation/with-module-federation.ts b/packages/react/src/module-federation/with-module-federation.ts index f1c1e185a6155..78808b9eae7ea 100644 --- a/packages/react/src/module-federation/with-module-federation.ts +++ b/packages/react/src/module-federation/with-module-federation.ts @@ -1,27 +1,8 @@ import { ModuleFederationConfig } from '@nx/devkit'; -import { readCachedProjectConfiguration } from 'nx/src/project-graph/project-graph'; import { getModuleFederationConfig } from './utils'; import ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); import type { AsyncNxWebpackPlugin } from '@nx/webpack'; -function determineRemoteUrl(remote: string) { - const remoteConfiguration = readCachedProjectConfiguration(remote); - const serveTarget = remoteConfiguration?.targets?.serve; - - if (!serveTarget) { - throw new Error( - `Cannot automatically determine URL of remote (${remote}). Looked for property "host" in the project's "serve" target.\n - You can also use the tuple syntax in your webpack config to configure your remotes. e.g. \`remotes: [['remote1', 'http://localhost:4201']]\`` - ); - } - - const host = serveTarget.options?.host ?? 'http://localhost'; - const port = serveTarget.options?.port ?? 4201; - return `${ - host.endsWith('/') ? host.slice(0, -1) : host - }:${port}/remoteEntry.js`; -} - /** * @param {ModuleFederationConfig} options * @return {Promise} @@ -32,7 +13,7 @@ export async function withModuleFederation( const reactWebpackConfig = require('../../plugins/webpack'); const { sharedDependencies, sharedLibraries, mappedRemotes } = - await getModuleFederationConfig(options, determineRemoteUrl); + await getModuleFederationConfig(options); return (config, ctx) => { config = reactWebpackConfig(config, ctx); From a70aeb27fbd291b8d6628355f9440562034ce0f5 Mon Sep 17 00:00:00 2001 From: Andrei Fiodorov Date: Wed, 26 Apr 2023 13:37:49 +0200 Subject: [PATCH 2/4] feat(react): provide default function for `determineRemoteUrl` instead of removing it --- packages/react/src/module-federation/utils.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/react/src/module-federation/utils.ts b/packages/react/src/module-federation/utils.ts index 5ed4c749e0423..24e7db630100e 100644 --- a/packages/react/src/module-federation/utils.ts +++ b/packages/react/src/module-federation/utils.ts @@ -38,7 +38,10 @@ export function getFunctionDeterminateRemoteUrl(isServer: boolean = false) { export async function getModuleFederationConfig( mfConfig: ModuleFederationConfig, - options: { isServer: boolean } = { isServer: false } + options: { + isServer: boolean; + determineRemoteUrl?: (remote: string) => string; + } = { isServer: false } ) { let projectGraph: ProjectGraph; try { @@ -88,14 +91,13 @@ export async function getModuleFederationConfig( ); const mapRemotesFunction = options.isServer ? mapRemotesForSSR : mapRemotes; + const determineRemoteUrlFn = + options.determineRemoteUrl || + getFunctionDeterminateRemoteUrl(options.isServer); const mappedRemotes = !mfConfig.remotes || mfConfig.remotes.length === 0 ? {} - : mapRemotesFunction( - mfConfig.remotes, - 'js', - getFunctionDeterminateRemoteUrl(options.isServer) - ); + : mapRemotesFunction(mfConfig.remotes, 'js', determineRemoteUrlFn); return { sharedLibraries, sharedDependencies, mappedRemotes }; } From 2d89603776fe7a8cb4b8602757532adbed481661 Mon Sep 17 00:00:00 2001 From: Andrei Fiodorov Date: Thu, 27 Apr 2023 10:21:31 +0200 Subject: [PATCH 3/4] fix(core): run prettier to fix code style issues --- e2e/angular-extensions/src/tailwind.test.ts | 8 ++++---- packages/nx/src/utils/find-matching-projects.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/e2e/angular-extensions/src/tailwind.test.ts b/e2e/angular-extensions/src/tailwind.test.ts index fe37942ed3884..aad50cd88fc50 100644 --- a/e2e/angular-extensions/src/tailwind.test.ts +++ b/e2e/angular-extensions/src/tailwind.test.ts @@ -73,7 +73,7 @@ describe('Tailwind support', () => { const createTailwindConfigFile = ( tailwindConfigFile = 'tailwind.config.js', - libSpacing: typeof spacing['projectVariant1'] + libSpacing: (typeof spacing)['projectVariant1'] ) => { const tailwindConfig = `const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); const { join } = require('path'); @@ -99,7 +99,7 @@ describe('Tailwind support', () => { const updateTailwindConfig = ( tailwindConfigPath: string, - projectSpacing: typeof spacing['root'] + projectSpacing: (typeof spacing)['root'] ) => { const tailwindConfig = readFile(tailwindConfigPath); @@ -174,7 +174,7 @@ describe('Tailwind support', () => { const assertLibComponentStyles = ( lib: string, - libSpacing: typeof spacing['root'] + libSpacing: (typeof spacing)['root'] ) => { const builtComponentContent = readFile( `dist/libs/${lib}/esm2020/lib/foo.component.mjs` @@ -342,7 +342,7 @@ describe('Tailwind support', () => { const assertAppComponentStyles = ( app: string, - appSpacing: typeof spacing['root'] + appSpacing: (typeof spacing)['root'] ) => { const mainBundlePath = listFiles(`dist/apps/${app}`).find((file) => file.startsWith('main.') diff --git a/packages/nx/src/utils/find-matching-projects.ts b/packages/nx/src/utils/find-matching-projects.ts index 3b988e9836277..9678d969b1f35 100644 --- a/packages/nx/src/utils/find-matching-projects.ts +++ b/packages/nx/src/utils/find-matching-projects.ts @@ -11,7 +11,7 @@ const validPatternTypes = [ 'directory', // Pattern is based on the project's root directory 'unlabeled', // Pattern was passed without specifying a type ] as const; -type ProjectPatternType = typeof validPatternTypes[number]; +type ProjectPatternType = (typeof validPatternTypes)[number]; interface ProjectPattern { // If true, the pattern is an exclude pattern From 72fbdf10431fbab51caf151f8f85c4ffa8d5dd81 Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Thu, 27 Apr 2023 11:49:54 +0100 Subject: [PATCH 4/4] feat(angular): ensure consistency with MF utils across frameworks --- e2e/angular-extensions/src/tailwind.test.ts | 8 ++--- packages/angular/src/utils/mf/utils.ts | 35 +++++++++++++++++-- .../utils/mf/with-module-federation-ssr.ts | 19 +--------- .../src/utils/mf/with-module-federation.ts | 19 +--------- .../nx/src/utils/find-matching-projects.ts | 2 +- packages/react/src/module-federation/utils.ts | 2 +- 6 files changed, 40 insertions(+), 45 deletions(-) diff --git a/e2e/angular-extensions/src/tailwind.test.ts b/e2e/angular-extensions/src/tailwind.test.ts index aad50cd88fc50..fe37942ed3884 100644 --- a/e2e/angular-extensions/src/tailwind.test.ts +++ b/e2e/angular-extensions/src/tailwind.test.ts @@ -73,7 +73,7 @@ describe('Tailwind support', () => { const createTailwindConfigFile = ( tailwindConfigFile = 'tailwind.config.js', - libSpacing: (typeof spacing)['projectVariant1'] + libSpacing: typeof spacing['projectVariant1'] ) => { const tailwindConfig = `const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); const { join } = require('path'); @@ -99,7 +99,7 @@ describe('Tailwind support', () => { const updateTailwindConfig = ( tailwindConfigPath: string, - projectSpacing: (typeof spacing)['root'] + projectSpacing: typeof spacing['root'] ) => { const tailwindConfig = readFile(tailwindConfigPath); @@ -174,7 +174,7 @@ describe('Tailwind support', () => { const assertLibComponentStyles = ( lib: string, - libSpacing: (typeof spacing)['root'] + libSpacing: typeof spacing['root'] ) => { const builtComponentContent = readFile( `dist/libs/${lib}/esm2020/lib/foo.component.mjs` @@ -342,7 +342,7 @@ describe('Tailwind support', () => { const assertAppComponentStyles = ( app: string, - appSpacing: (typeof spacing)['root'] + appSpacing: typeof spacing['root'] ) => { const mainBundlePath = listFiles(`dist/apps/${app}`).find((file) => file.startsWith('main.') diff --git a/packages/angular/src/utils/mf/utils.ts b/packages/angular/src/utils/mf/utils.ts index dae5ddd800375..a1c4234ca37e7 100644 --- a/packages/angular/src/utils/mf/utils.ts +++ b/packages/angular/src/utils/mf/utils.ts @@ -15,6 +15,7 @@ import { ProjectGraph, readCachedProjectGraph, } from '@nx/devkit'; +import { readCachedProjectConfiguration } from 'nx/src/project-graph/project-graph'; export function applyDefaultEagerPackages( sharedConfig: Record @@ -42,10 +43,35 @@ export const DEFAULT_ANGULAR_PACKAGES_TO_SHARE = [ '@angular/common', ]; +export function getFunctionDeterminateRemoteUrl(isServer: boolean = false) { + const target = 'serve'; + const remoteEntry = isServer ? 'server/remoteEntry.js' : 'remoteEntry.mjs'; + + return function (remote: string) { + const remoteConfiguration = readCachedProjectConfiguration(remote); + const serveTarget = remoteConfiguration?.targets?.[target]; + + if (!serveTarget) { + throw new Error( + `Cannot automatically determine URL of remote (${remote}). Looked for property "host" in the project's "serve" target.\n + You can also use the tuple syntax in your webpack config to configure your remotes. e.g. \`remotes: [['remote1', 'http://localhost:4201']]\`` + ); + } + + const host = serveTarget.options?.host ?? 'http://localhost'; + const port = serveTarget.options?.port ?? 4201; + return `${ + host.endsWith('/') ? host.slice(0, -1) : host + }:${port}/${remoteEntry}`; + }; +} + export async function getModuleFederationConfig( mfConfig: ModuleFederationConfig, - determineRemoteUrl: (remote: string) => string, - options: { isServer: boolean } = { isServer: false } + options: { + isServer: boolean; + determineRemoteUrl?: (remote: string) => string; + } = { isServer: false } ) { let projectGraph: ProjectGraph; try { @@ -107,11 +133,14 @@ export async function getModuleFederationConfig( mfConfig.additionalShared, projectGraph ); + const determineRemoteUrlFn = + options.determineRemoteUrl || + getFunctionDeterminateRemoteUrl(options.isServer); const mapRemotesFunction = options.isServer ? mapRemotesForSSR : mapRemotes; const mappedRemotes = !mfConfig.remotes || mfConfig.remotes.length === 0 ? {} - : mapRemotesFunction(mfConfig.remotes, 'mjs', determineRemoteUrl); + : mapRemotesFunction(mfConfig.remotes, 'mjs', determineRemoteUrlFn); return { sharedLibraries, sharedDependencies, mappedRemotes }; } diff --git a/packages/angular/src/utils/mf/with-module-federation-ssr.ts b/packages/angular/src/utils/mf/with-module-federation-ssr.ts index 3cc75f324222f..81d8ced86c65d 100644 --- a/packages/angular/src/utils/mf/with-module-federation-ssr.ts +++ b/packages/angular/src/utils/mf/with-module-federation-ssr.ts @@ -1,28 +1,11 @@ -import { readCachedProjectConfiguration } from 'nx/src/project-graph/project-graph'; import { ModuleFederationConfig } from '@nx/devkit/src/utils/module-federation'; import { getModuleFederationConfig } from './utils'; -function determineRemoteUrl(remote: string) { - const remoteProjectConfiguration = readCachedProjectConfiguration(remote); - let publicHost = ''; - try { - publicHost = remoteProjectConfiguration.targets.serve.options.publicHost; - } catch (error) { - throw new Error( - `Cannot automatically determine URL of remote (${remote}). Looked for property "publicHost" in the project's "serve" target.\n - You can also use the tuple syntax in your webpack config to configure your remotes. e.g. \`remotes: [['remote1', 'http://localhost:4201']]\`` - ); - } - return `${ - publicHost.endsWith('/') ? publicHost.slice(0, -1) : publicHost - }/server/remoteEntry.js`; -} - export async function withModuleFederationForSSR( options: ModuleFederationConfig ) { const { sharedLibraries, sharedDependencies, mappedRemotes } = - await getModuleFederationConfig(options, determineRemoteUrl, { + await getModuleFederationConfig(options, { isServer: true, }); diff --git a/packages/angular/src/utils/mf/with-module-federation.ts b/packages/angular/src/utils/mf/with-module-federation.ts index f9a61595d9018..71f615118add7 100644 --- a/packages/angular/src/utils/mf/with-module-federation.ts +++ b/packages/angular/src/utils/mf/with-module-federation.ts @@ -1,27 +1,10 @@ import { ModuleFederationConfig } from '@nx/devkit/src/utils/module-federation'; import { getModuleFederationConfig } from './utils'; -import { readCachedProjectConfiguration } from 'nx/src/project-graph/project-graph'; import ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); -function determineRemoteUrl(remote: string) { - const remoteProjectConfiguration = readCachedProjectConfiguration(remote); - let publicHost = ''; - try { - publicHost = remoteProjectConfiguration.targets.serve.options.publicHost; - } catch (error) { - throw new Error( - `Cannot automatically determine URL of remote (${remote}). Looked for property "publicHost" in the project's "serve" target.\n - You can also use the tuple syntax in your webpack config to configure your remotes. e.g. \`remotes: [['remote1', 'http://localhost:4201']]\`` - ); - } - return `${ - publicHost.endsWith('/') ? publicHost.slice(0, -1) : publicHost - }/remoteEntry.mjs`; -} - export async function withModuleFederation(options: ModuleFederationConfig) { const { sharedLibraries, sharedDependencies, mappedRemotes } = - await getModuleFederationConfig(options, determineRemoteUrl); + await getModuleFederationConfig(options); return (config) => ({ ...(config ?? {}), diff --git a/packages/nx/src/utils/find-matching-projects.ts b/packages/nx/src/utils/find-matching-projects.ts index 9678d969b1f35..3b988e9836277 100644 --- a/packages/nx/src/utils/find-matching-projects.ts +++ b/packages/nx/src/utils/find-matching-projects.ts @@ -11,7 +11,7 @@ const validPatternTypes = [ 'directory', // Pattern is based on the project's root directory 'unlabeled', // Pattern was passed without specifying a type ] as const; -type ProjectPatternType = (typeof validPatternTypes)[number]; +type ProjectPatternType = typeof validPatternTypes[number]; interface ProjectPattern { // If true, the pattern is an exclude pattern diff --git a/packages/react/src/module-federation/utils.ts b/packages/react/src/module-federation/utils.ts index c2d601924d251..ba67d6684ae9f 100644 --- a/packages/react/src/module-federation/utils.ts +++ b/packages/react/src/module-federation/utils.ts @@ -26,7 +26,7 @@ export function getFunctionDeterminateRemoteUrl(isServer: boolean = false) { if (!serveTarget) { throw new Error( - `Cannot automatically determine URL of remote (${remote}). Looked for property "host" in the project's "serve-server" target.\n + `Cannot automatically determine URL of remote (${remote}). Looked for property "host" in the project's "${serveTarget}" target.\n You can also use the tuple syntax in your webpack config to configure your remotes. e.g. \`remotes: [['remote1', 'http://localhost:4201']]\`` ); }