Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(angular): shared transitive npm deps from host and remote applica… #9997

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -23,6 +23,11 @@ Array [
"eager": undefined,
"requiredVersion": false,
},
"npm:lodash": Object {
"requiredVersion": undefined,
"singleton": true,
"strictVersion": true,
},
"shared": Object {
"eager": undefined,
"requiredVersion": false,
Expand Down
Expand Up @@ -140,7 +140,7 @@ describe('withModuleFederation', () => {
{ target: 'npm:zone.js' },
{ target: 'core' },
],
core: [{ target: 'shared' }],
core: [{ target: 'shared' }, { target: 'npm:lodash' }],
},
});

Expand Down
55 changes: 39 additions & 16 deletions packages/angular/src/utils/mfe/with-module-federation.ts
Expand Up @@ -30,9 +30,15 @@ export interface MFEConfig {
) => SharedLibraryConfig | false;
}

interface DependencySets {
workspaceLibraries: Set<string>;
npmPackages: Set<string>;
}

function recursivelyResolveWorkspaceDependents(
projectGraph: ProjectGraph<any>,
target: string,
dependencySets: DependencySets,
seenTargets: Set<string> = new Set()
) {
if (seenTargets.has(target)) {
Expand All @@ -43,14 +49,27 @@ function recursivelyResolveWorkspaceDependents(

const workspaceDependencies = (
projectGraph.dependencies[target] ?? []
).filter((dep) => !dep.target.startsWith('npm:'));
).filter((dep) => {
const isNpm = dep.target.startsWith('npm:');

// If this is a npm dep ensure it is going to be added as a dep of this MFE so it can be shared if needed
if (isNpm) {
dependencySets.npmPackages.add(dep.target);
yharaskrik marked this conversation as resolved.
Show resolved Hide resolved
} else {
dependencySets.workspaceLibraries.add(dep.target);
}

return !isNpm;
});

if (workspaceDependencies.length > 0) {
for (const dep of workspaceDependencies) {
dependencies = [
...dependencies,
...recursivelyResolveWorkspaceDependents(
projectGraph,
dep.target,
dependencySets,
seenTargets
),
];
Expand Down Expand Up @@ -103,7 +122,8 @@ async function getDependentPackagesForProject(name: string) {
projectGraph = await createProjectGraphAsync();
}

const deps = projectGraph.dependencies[name].reduce(
// Build Sets for the direct deps (internal and external) for this MFE app
const dependencySets = projectGraph.dependencies[name].reduce(
(dependencies, dependency) => {
const workspaceLibraries = new Set(dependencies.workspaceLibraries);
const npmPackages = new Set(dependencies.npmPackages);
Expand All @@ -115,24 +135,27 @@ async function getDependentPackagesForProject(name: string) {
}

return {
workspaceLibraries: [...workspaceLibraries],
npmPackages: [...npmPackages],
workspaceLibraries,
npmPackages,
};
},
{ workspaceLibraries: [], npmPackages: [] }
{ workspaceLibraries: new Set<string>(), npmPackages: new Set<string>() }
);

const seenWorkspaceLibraries = new Set<string>();
deps.workspaceLibraries = deps.workspaceLibraries.reduce(
(workspaceLibraryDeps, workspaceLibrary) => [
...workspaceLibraryDeps,
...recursivelyResolveWorkspaceDependents(
projectGraph,
workspaceLibrary,
seenWorkspaceLibraries
),
],
[]
);
dependencySets.workspaceLibraries.forEach((workspaceLibrary) => {
recursivelyResolveWorkspaceDependents(
projectGraph,
workspaceLibrary,
dependencySets,
seenWorkspaceLibraries
);
});

const deps = {
workspaceLibraries: [...dependencySets.workspaceLibraries],
npmPackages: [...dependencySets.npmPackages],
};

deps.workspaceLibraries = mapWorkspaceLibrariesToTsConfigImport(
deps.workspaceLibraries
Expand Down
58 changes: 40 additions & 18 deletions packages/react/src/module-federation/with-module-federation.ts
Expand Up @@ -15,9 +15,15 @@ import { readWorkspaceJson } from 'nx/src/project-graph/file-utils';
import { ModuleFederationConfig, Remotes } from './models';
import ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

interface DependencySets {
workspaceLibraries: Set<string>;
npmPackages: Set<string>;
}

function recursivelyResolveWorkspaceDependents(
projectGraph: ProjectGraph<any>,
target: string,
dependencySets: DependencySets,
seenTargets: Set<string> = new Set()
) {
if (seenTargets.has(target)) {
Expand All @@ -28,14 +34,27 @@ function recursivelyResolveWorkspaceDependents(

const workspaceDependencies = (
projectGraph.dependencies[target] ?? []
).filter((dep) => !dep.target.startsWith('npm:'));
).filter((dep) => {
const isNpm = dep.target.startsWith('npm:');

// If this is a npm dep ensure it is going to be added as a dep of this MFE so it can be shared if needed
if (isNpm) {
dependencySets.npmPackages.add(dep.target);
yharaskrik marked this conversation as resolved.
Show resolved Hide resolved
} else {
dependencySets.workspaceLibraries.add(dep.target);
}

return !isNpm;
});

if (workspaceDependencies.length > 0) {
for (const dep of workspaceDependencies) {
dependencies = [
...dependencies,
...recursivelyResolveWorkspaceDependents(
projectGraph,
dep.target,
dependencySets,
seenTargets
),
];
Expand Down Expand Up @@ -81,15 +100,15 @@ function mapWorkspaceLibrariesToTsConfigImport(workspaceLibraries: string[]) {
}

async function getDependentPackagesForProject(name: string) {
let projectGraph: ProjectGraph;

let projectGraph: ProjectGraph<any>;
try {
projectGraph = readCachedProjectGraph();
} catch (e) {
projectGraph = await createProjectGraphAsync();
}

const deps = projectGraph.dependencies[name].reduce(
// Build Sets for the direct deps (internal and external) for this MFE app
const dependencySets = projectGraph.dependencies[name].reduce(
(dependencies, dependency) => {
const workspaceLibraries = new Set(dependencies.workspaceLibraries);
const npmPackages = new Set(dependencies.npmPackages);
Expand All @@ -101,24 +120,27 @@ async function getDependentPackagesForProject(name: string) {
}

return {
workspaceLibraries: [...workspaceLibraries],
npmPackages: [...npmPackages],
workspaceLibraries,
npmPackages,
};
},
{ workspaceLibraries: [], npmPackages: [] }
{ workspaceLibraries: new Set<string>(), npmPackages: new Set<string>() }
);

const seenWorkspaceLibraries = new Set<string>();
deps.workspaceLibraries = deps.workspaceLibraries.reduce(
(workspaceLibraryDeps, workspaceLibrary) => [
...workspaceLibraryDeps,
...recursivelyResolveWorkspaceDependents(
projectGraph,
workspaceLibrary,
seenWorkspaceLibraries
),
],
[]
);
dependencySets.workspaceLibraries.forEach((workspaceLibrary) => {
recursivelyResolveWorkspaceDependents(
projectGraph,
workspaceLibrary,
dependencySets,
seenWorkspaceLibraries
);
});

const deps = {
workspaceLibraries: [...dependencySets.workspaceLibraries],
npmPackages: [...dependencySets.npmPackages],
};

deps.workspaceLibraries = mapWorkspaceLibrariesToTsConfigImport(
deps.workspaceLibraries
Expand Down