Skip to content

Commit

Permalink
fix(angular): share secondary entry points (#9896)
Browse files Browse the repository at this point in the history
  • Loading branch information
Coly010 authored Apr 20, 2022
1 parent 4ca470c commit cc38970
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 8 deletions.
104 changes: 103 additions & 1 deletion packages/angular/src/utils/mfe/mfe-webpack.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,17 @@ describe('MFE Webpack Utils', () => {
it('should correctly map the shared packages to objects', () => {
// ARRANGE
(fs.existsSync as jest.Mock).mockReturnValue(true);
(fs.readFileSync as jest.Mock).mockReturnValue(
(fs.readFileSync as jest.Mock).mockImplementation((file) =>
JSON.stringify({
name: file.replace(/\\/g, '/').replace(/^.*node_modules[/]/, ''),
dependencies: {
'@angular/core': '~13.2.0',
'@angular/common': '~13.2.0',
rxjs: '~7.4.0',
},
})
);
(fs.readdirSync as jest.Mock).mockReturnValue([]);

// ACT
const packages = sharePackages([
Expand All @@ -121,5 +123,105 @@ describe('MFE Webpack Utils', () => {
},
});
});

it('should correctly map the shared packages to objects even with nested entry points', () => {
// ARRANGE

/**
* This creates a bunch of mocks that aims to test that
* the sharePackages function can handle nested
* entrypoints in the package that is being shared.
*
* This will set up a directory structure that matches
* the following:
*
* - @angular/core/
* - package.json
* - @angular/common/
* - http/
* - testing/
* - package.json
* - package.json
* - rxjs
* - package.json
*
* The result is that there would be 4 packages that
* need to be shared, as determined by the folders
* containing the package.json files
*/
createMockedFSForNestedEntryPoints();

// ACT
const packages = sharePackages([
'@angular/core',
'@angular/common',
'rxjs',
]);
// ASSERT
expect(packages).toEqual({
'@angular/core': {
singleton: true,
strictVersion: true,
requiredVersion: '~13.2.0',
},
'@angular/common': {
singleton: true,
strictVersion: true,
requiredVersion: '~13.2.0',
},
'@angular/common/http/testing': {
singleton: true,
strictVersion: true,
requiredVersion: '~13.2.0',
},
rxjs: {
singleton: true,
strictVersion: true,
requiredVersion: '~7.4.0',
},
});
});
});
});

function createMockedFSForNestedEntryPoints() {
(fs.existsSync as jest.Mock).mockImplementation((file: string) => {
if (file.endsWith('http/package.json')) {
return false;
} else {
return true;
}
});

(fs.readFileSync as jest.Mock).mockImplementation((file) =>
JSON.stringify({
name: file
.replace(/\\/g, '/')
.replace(/^.*node_modules[/]/, '')
.replace('/package.json', ''),
dependencies: {
'@angular/core': '~13.2.0',
'@angular/common': '~13.2.0',
rxjs: '~7.4.0',
},
})
);

(fs.readdirSync as jest.Mock).mockImplementation((directoryPath: string) => {
const PACKAGE_SETUP = {
'@angular/core': [],
'@angular/common': ['http'],
http: ['testing'],
testing: [],
};

for (const key of Object.keys(PACKAGE_SETUP)) {
if (directoryPath.endsWith(key)) {
return PACKAGE_SETUP[key];
}
}
return [];
});

(fs.lstatSync as jest.Mock).mockReturnValue({ isDirectory: () => true });
}
59 changes: 52 additions & 7 deletions packages/angular/src/utils/mfe/mfe-webpack.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { existsSync, readFileSync } from 'fs';
import { existsSync, lstatSync, readdirSync, readFileSync } from 'fs';
import { NormalModuleReplacementPlugin } from 'webpack';
import { joinPathFragments, workspaceRoot } from '@nrwl/devkit';
import { dirname, join, normalize } from 'path';
Expand Down Expand Up @@ -81,6 +81,44 @@ export function shareWorkspaceLibraries(
};
}

function collectPackageSecondaries(pkgName: string, packages: string[]) {
const pathToPackage = join(workspaceRoot, 'node_modules', pkgName);
const directories = readdirSync(pathToPackage)
.filter((file) => file !== 'node_modules')
.map((file) => join(pathToPackage, file))
.filter((file) => lstatSync(file).isDirectory());

const recursivelyCheckSubDirectories = (
directories: string[],
secondaries: string[]
) => {
for (const directory of directories) {
if (existsSync(join(directory, 'package.json'))) {
secondaries.push(directory);
}

const subDirs = readdirSync(directory)
.filter((file) => file !== 'node_modules')
.map((file) => join(directory, file))
.filter((file) => lstatSync(file).isDirectory());
recursivelyCheckSubDirectories(subDirs, secondaries);
}
};

const secondaries = [];
recursivelyCheckSubDirectories(directories, secondaries);

for (const secondary of secondaries) {
const pathToPkg = join(secondary, 'package.json');
const libName = JSON.parse(readFileSync(pathToPkg, 'utf-8')).name;
if (!libName) {
continue;
}
packages.push(libName);
collectPackageSecondaries(libName, packages);
}
}

export function sharePackages(
packages: string[]
): Record<string, SharedLibraryConfig> {
Expand All @@ -93,15 +131,22 @@ export function sharePackages(

const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));

return packages.reduce(
(shared, pkgName) => ({
const allPackages = [...packages];
packages.forEach((pkg) => collectPackageSecondaries(pkg, allPackages));

return allPackages.reduce((shared, pkgName) => {
const nameToUseForVersionLookup =
pkgName.split('/').length > 2
? pkgName.split('/').slice(0, 2).join('/')
: pkgName;

return {
...shared,
[pkgName]: {
singleton: true,
strictVersion: true,
requiredVersion: pkgJson.dependencies[pkgName],
requiredVersion: pkgJson.dependencies[nameToUseForVersionLookup],
},
}),
{}
);
};
}, {});
}
8 changes: 8 additions & 0 deletions packages/angular/src/utils/mfe/with-module-federation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ describe('withModuleFederation', () => {
}),
});

(fs.readdirSync as jest.Mock).mockReturnValue([]);

// ACT
const config = (
await withModuleFederation({
Expand Down Expand Up @@ -115,6 +117,8 @@ describe('withModuleFederation', () => {
}),
});

(fs.readdirSync as jest.Mock).mockReturnValue([]);

// ACT
const config = (
await withModuleFederation({
Expand Down Expand Up @@ -171,6 +175,8 @@ describe('withModuleFederation', () => {
}),
});

(fs.readdirSync as jest.Mock).mockReturnValue([]);

// ACT
const config = (
await withModuleFederation({
Expand Down Expand Up @@ -227,6 +233,8 @@ describe('withModuleFederation', () => {
}),
});

(fs.readdirSync as jest.Mock).mockReturnValue([]);

// ACT
const config = (
await withModuleFederation({
Expand Down

0 comments on commit cc38970

Please sign in to comment.