fix(module-federation): ensure targetDefaults for module federation executors are setup correctly (#22282)
This commit is contained in:
parent
b6cd1962c8
commit
81df8485a1
@ -371,6 +371,12 @@
|
|||||||
},
|
},
|
||||||
"description": "Update the @angular/cli package version to ~17.2.0.",
|
"description": "Update the @angular/cli package version to ~17.2.0.",
|
||||||
"factory": "./src/migrations/update-18-1-0/update-angular-cli"
|
"factory": "./src/migrations/update-18-1-0/update-angular-cli"
|
||||||
|
},
|
||||||
|
"fix-target-defaults-for-webpack-browser": {
|
||||||
|
"cli": "nx",
|
||||||
|
"version": "18.1.1-beta.0",
|
||||||
|
"description": "Ensure targetDefaults inputs for task hashing when '@nx/angular:webpack-browser' is used are correct for Module Federation.",
|
||||||
|
"factory": "./src/migrations/update-18-1-1/fix-target-defaults-inputs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packageJsonUpdates": {
|
"packageJsonUpdates": {
|
||||||
|
|||||||
@ -7,7 +7,10 @@ export function addMfEnvToTargetDefaultInputs(tree: Tree) {
|
|||||||
|
|
||||||
nxJson.targetDefaults ??= {};
|
nxJson.targetDefaults ??= {};
|
||||||
nxJson.targetDefaults[webpackExecutor] ??= {};
|
nxJson.targetDefaults[webpackExecutor] ??= {};
|
||||||
nxJson.targetDefaults[webpackExecutor].inputs ??= [];
|
nxJson.targetDefaults[webpackExecutor].inputs ??= [
|
||||||
|
'production',
|
||||||
|
'^production',
|
||||||
|
];
|
||||||
|
|
||||||
let mfEnvVarExists = false;
|
let mfEnvVarExists = false;
|
||||||
for (const input of nxJson.targetDefaults[webpackExecutor].inputs) {
|
for (const input of nxJson.targetDefaults[webpackExecutor].inputs) {
|
||||||
|
|||||||
@ -26,6 +26,8 @@ describe('addMfEnvVarToTargetDefaults', () => {
|
|||||||
{
|
{
|
||||||
"@nx/angular:webpack-browser": {
|
"@nx/angular:webpack-browser": {
|
||||||
"inputs": [
|
"inputs": [
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
{
|
{
|
||||||
"env": "NX_MF_DEV_SERVER_STATIC_REMOTES",
|
"env": "NX_MF_DEV_SERVER_STATIC_REMOTES",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -0,0 +1,127 @@
|
|||||||
|
import fixTargetDefaultInputs from './fix-target-defaults-inputs';
|
||||||
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
|
import { addProjectConfiguration, readNxJson, updateNxJson } from '@nx/devkit';
|
||||||
|
|
||||||
|
describe('fixTargetDefaultsInputs', () => {
|
||||||
|
it('should add the executor and input when it does not exist', async () => {
|
||||||
|
// ARRANGE
|
||||||
|
const tree = createTreeWithEmptyWorkspace();
|
||||||
|
addProjectConfiguration(tree, 'test', {
|
||||||
|
root: '',
|
||||||
|
targets: {
|
||||||
|
build: {
|
||||||
|
executor: '@nx/angular:webpack-browser',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
tree.write('module-federation.config.ts', '');
|
||||||
|
|
||||||
|
// ACT
|
||||||
|
await fixTargetDefaultInputs(tree);
|
||||||
|
|
||||||
|
// ASSERT
|
||||||
|
const nxJson = readNxJson(tree);
|
||||||
|
expect(nxJson.targetDefaults).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"@nx/angular:webpack-browser": {
|
||||||
|
"inputs": [
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"env": "NX_MF_DEV_SERVER_STATIC_REMOTES",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"cache": true,
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"cache": true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not add the executor and input when no project uses it', async () => {
|
||||||
|
// ARRANGE
|
||||||
|
const tree = createTreeWithEmptyWorkspace();
|
||||||
|
addProjectConfiguration(tree, 'test', {
|
||||||
|
root: '',
|
||||||
|
targets: {
|
||||||
|
build: {
|
||||||
|
executor: '@nx/angular:module-federation-dev-server',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// ACT
|
||||||
|
await fixTargetDefaultInputs(tree);
|
||||||
|
|
||||||
|
// ASSERT
|
||||||
|
const nxJson = readNxJson(tree);
|
||||||
|
expect(nxJson.targetDefaults).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"cache": true,
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"cache": true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update the executor and input target default when it already exists', async () => {
|
||||||
|
// ARRANGE
|
||||||
|
const tree = createTreeWithEmptyWorkspace();
|
||||||
|
addProjectConfiguration(tree, 'test', {
|
||||||
|
root: '',
|
||||||
|
targets: {
|
||||||
|
build: {
|
||||||
|
executor: '@nx/angular:webpack-browser',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
tree.write('module-federation.config.ts', '');
|
||||||
|
|
||||||
|
let nxJson = readNxJson(tree);
|
||||||
|
nxJson = {
|
||||||
|
...nxJson,
|
||||||
|
targetDefaults: {
|
||||||
|
...nxJson.targetDefaults,
|
||||||
|
['@nx/angular:webpack-browser']: {
|
||||||
|
inputs: ['^build'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
updateNxJson(tree, nxJson);
|
||||||
|
|
||||||
|
// ACT
|
||||||
|
await fixTargetDefaultInputs(tree);
|
||||||
|
|
||||||
|
// ASSERT
|
||||||
|
nxJson = readNxJson(tree);
|
||||||
|
expect(nxJson.targetDefaults).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"@nx/angular:webpack-browser": {
|
||||||
|
"inputs": [
|
||||||
|
"^build",
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"env": "NX_MF_DEV_SERVER_STATIC_REMOTES",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"cache": true,
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"cache": true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
import {
|
||||||
|
getProjects,
|
||||||
|
type Tree,
|
||||||
|
type ProjectConfiguration,
|
||||||
|
joinPathFragments,
|
||||||
|
formatFiles,
|
||||||
|
readNxJson,
|
||||||
|
updateNxJson,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
|
||||||
|
export default async function (tree: Tree) {
|
||||||
|
if (!isWebpackBrowserUsed(tree)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ensureTargetDefaultsContainProductionInputs(tree);
|
||||||
|
|
||||||
|
await formatFiles(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureTargetDefaultsContainProductionInputs(tree: Tree) {
|
||||||
|
const nxJson = readNxJson(tree);
|
||||||
|
const webpackExecutor = '@nx/angular:webpack-browser';
|
||||||
|
const mfEnvVar = 'NX_MF_DEV_SERVER_STATIC_REMOTES';
|
||||||
|
|
||||||
|
nxJson.targetDefaults[webpackExecutor] ??= {};
|
||||||
|
|
||||||
|
nxJson.targetDefaults[webpackExecutor].inputs ??= [
|
||||||
|
'production',
|
||||||
|
'^production',
|
||||||
|
{ env: mfEnvVar },
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!nxJson.targetDefaults[webpackExecutor].inputs.includes('production')) {
|
||||||
|
nxJson.targetDefaults[webpackExecutor].inputs.push('production');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nxJson.targetDefaults[webpackExecutor].inputs.includes('^production')) {
|
||||||
|
nxJson.targetDefaults[webpackExecutor].inputs.push('^production');
|
||||||
|
}
|
||||||
|
|
||||||
|
let mfEnvVarExists = false;
|
||||||
|
for (const input of nxJson.targetDefaults[webpackExecutor].inputs) {
|
||||||
|
if (typeof input === 'object' && input['env'] === mfEnvVar) {
|
||||||
|
mfEnvVarExists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mfEnvVarExists) {
|
||||||
|
nxJson.targetDefaults[webpackExecutor].inputs.push({ env: mfEnvVar });
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNxJson(tree, nxJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isWebpackBrowserUsed(tree: Tree) {
|
||||||
|
const projects = getProjects(tree);
|
||||||
|
for (const project of projects.values()) {
|
||||||
|
const targets = project.targets || {};
|
||||||
|
for (const [_, target] of Object.entries(targets)) {
|
||||||
|
if (
|
||||||
|
target.executor === '@nx/angular:webpack-browser' &&
|
||||||
|
(tree.exists(
|
||||||
|
joinPathFragments(project.root, 'module-federation.config.ts')
|
||||||
|
) ||
|
||||||
|
tree.exists(
|
||||||
|
joinPathFragments(project.root, 'module-federation.config.js')
|
||||||
|
))
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@ -53,6 +53,12 @@
|
|||||||
"version": "18.0.0-beta.0",
|
"version": "18.0.0-beta.0",
|
||||||
"description": "Add NX_MF_DEV_SERVER_STATIC_REMOTES to inputs for task hashing when '@nx/webpack:webpack' is used for Module Federation.",
|
"description": "Add NX_MF_DEV_SERVER_STATIC_REMOTES to inputs for task hashing when '@nx/webpack:webpack' is used for Module Federation.",
|
||||||
"factory": "./src/migrations/update-18-0-0/add-mf-env-var-to-target-defaults"
|
"factory": "./src/migrations/update-18-0-0/add-mf-env-var-to-target-defaults"
|
||||||
|
},
|
||||||
|
"fix-target-defaults-for-webpack": {
|
||||||
|
"cli": "nx",
|
||||||
|
"version": "18.1.1-beta.0",
|
||||||
|
"description": "Ensure targetDefaults inputs for task hashing when '@nx/webpack:webpack' is used are correct for Module Federation.",
|
||||||
|
"factory": "./src/migrations/update-18-1-1/fix-target-defaults-inputs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packageJsonUpdates": {
|
"packageJsonUpdates": {
|
||||||
|
|||||||
@ -25,6 +25,8 @@ describe('addMfEnvVarToTargetDefaults', () => {
|
|||||||
{
|
{
|
||||||
"@nx/webpack:webpack": {
|
"@nx/webpack:webpack": {
|
||||||
"inputs": [
|
"inputs": [
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
{
|
{
|
||||||
"env": "NX_MF_DEV_SERVER_STATIC_REMOTES",
|
"env": "NX_MF_DEV_SERVER_STATIC_REMOTES",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -0,0 +1,127 @@
|
|||||||
|
import fixTargetDefaultsInputs from './fix-target-defaults-inputs';
|
||||||
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
|
import { addProjectConfiguration, readNxJson, updateNxJson } from '@nx/devkit';
|
||||||
|
|
||||||
|
describe('fixTargetDefaultsInputs', () => {
|
||||||
|
it('should add the executor and input when it does not exist', async () => {
|
||||||
|
// ARRANGE
|
||||||
|
const tree = createTreeWithEmptyWorkspace();
|
||||||
|
addProjectConfiguration(tree, 'test', {
|
||||||
|
root: '',
|
||||||
|
targets: {
|
||||||
|
build: {
|
||||||
|
executor: '@nx/webpack:webpack',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
tree.write('module-federation.config.ts', '');
|
||||||
|
|
||||||
|
// ACT
|
||||||
|
await fixTargetDefaultsInputs(tree);
|
||||||
|
|
||||||
|
// ASSERT
|
||||||
|
const nxJson = readNxJson(tree);
|
||||||
|
expect(nxJson.targetDefaults).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"@nx/webpack:webpack": {
|
||||||
|
"inputs": [
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"env": "NX_MF_DEV_SERVER_STATIC_REMOTES",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"cache": true,
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"cache": true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not add the executor and input when no project uses it', async () => {
|
||||||
|
// ARRANGE
|
||||||
|
const tree = createTreeWithEmptyWorkspace();
|
||||||
|
addProjectConfiguration(tree, 'test', {
|
||||||
|
root: '',
|
||||||
|
targets: {
|
||||||
|
build: {
|
||||||
|
executor: '@nx/angular:module-federation-dev-server',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// ACT
|
||||||
|
await fixTargetDefaultsInputs(tree);
|
||||||
|
|
||||||
|
// ASSERT
|
||||||
|
const nxJson = readNxJson(tree);
|
||||||
|
expect(nxJson.targetDefaults).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"cache": true,
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"cache": true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update the executor and input target default when it already exists', async () => {
|
||||||
|
// ARRANGE
|
||||||
|
const tree = createTreeWithEmptyWorkspace();
|
||||||
|
addProjectConfiguration(tree, 'test', {
|
||||||
|
root: '',
|
||||||
|
targets: {
|
||||||
|
build: {
|
||||||
|
executor: '@nx/webpack:webpack',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
tree.write('module-federation.config.ts', '');
|
||||||
|
|
||||||
|
let nxJson = readNxJson(tree);
|
||||||
|
nxJson = {
|
||||||
|
...nxJson,
|
||||||
|
targetDefaults: {
|
||||||
|
...nxJson.targetDefaults,
|
||||||
|
['@nx/webpack:webpack']: {
|
||||||
|
inputs: ['^build'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
updateNxJson(tree, nxJson);
|
||||||
|
|
||||||
|
// ACT
|
||||||
|
await fixTargetDefaultsInputs(tree);
|
||||||
|
|
||||||
|
// ASSERT
|
||||||
|
nxJson = readNxJson(tree);
|
||||||
|
expect(nxJson.targetDefaults).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"@nx/webpack:webpack": {
|
||||||
|
"inputs": [
|
||||||
|
"^build",
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"env": "NX_MF_DEV_SERVER_STATIC_REMOTES",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"cache": true,
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"cache": true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
import {
|
||||||
|
getProjects,
|
||||||
|
type Tree,
|
||||||
|
type ProjectConfiguration,
|
||||||
|
joinPathFragments,
|
||||||
|
formatFiles,
|
||||||
|
readNxJson,
|
||||||
|
updateNxJson,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
|
||||||
|
export default async function (tree: Tree) {
|
||||||
|
if (!hasModuleFederationProject(tree)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ensureTargetDefaultsContainProductionInputs(tree);
|
||||||
|
|
||||||
|
await formatFiles(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureTargetDefaultsContainProductionInputs(tree: Tree) {
|
||||||
|
const nxJson = readNxJson(tree);
|
||||||
|
const webpackExecutor = '@nx/webpack:webpack';
|
||||||
|
const mfEnvVar = 'NX_MF_DEV_SERVER_STATIC_REMOTES';
|
||||||
|
|
||||||
|
nxJson.targetDefaults[webpackExecutor] ??= {};
|
||||||
|
|
||||||
|
nxJson.targetDefaults[webpackExecutor].inputs ??= [
|
||||||
|
'production',
|
||||||
|
'^production',
|
||||||
|
{ env: mfEnvVar },
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!nxJson.targetDefaults[webpackExecutor].inputs.includes('production')) {
|
||||||
|
nxJson.targetDefaults[webpackExecutor].inputs.push('production');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nxJson.targetDefaults[webpackExecutor].inputs.includes('^production')) {
|
||||||
|
nxJson.targetDefaults[webpackExecutor].inputs.push('^production');
|
||||||
|
}
|
||||||
|
|
||||||
|
let mfEnvVarExists = false;
|
||||||
|
for (const input of nxJson.targetDefaults[webpackExecutor].inputs) {
|
||||||
|
if (typeof input === 'object' && input['env'] === mfEnvVar) {
|
||||||
|
mfEnvVarExists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mfEnvVarExists) {
|
||||||
|
nxJson.targetDefaults[webpackExecutor].inputs.push({ env: mfEnvVar });
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNxJson(tree, nxJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasModuleFederationProject(tree: Tree) {
|
||||||
|
const projects = getProjects(tree);
|
||||||
|
for (const project of projects.values()) {
|
||||||
|
const targets = project.targets || {};
|
||||||
|
for (const [_, target] of Object.entries(targets)) {
|
||||||
|
if (
|
||||||
|
target.executor === '@nx/webpack:webpack' &&
|
||||||
|
(tree.exists(
|
||||||
|
joinPathFragments(project.root, 'module-federation.config.ts')
|
||||||
|
) ||
|
||||||
|
tree.exists(
|
||||||
|
joinPathFragments(project.root, 'module-federation.config.js')
|
||||||
|
))
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@ -7,7 +7,10 @@ export function addMfEnvToTargetDefaultInputs(tree: Tree) {
|
|||||||
|
|
||||||
nxJson.targetDefaults ??= {};
|
nxJson.targetDefaults ??= {};
|
||||||
nxJson.targetDefaults[webpackExecutor] ??= {};
|
nxJson.targetDefaults[webpackExecutor] ??= {};
|
||||||
nxJson.targetDefaults[webpackExecutor].inputs ??= [];
|
nxJson.targetDefaults[webpackExecutor].inputs ??= [
|
||||||
|
'production',
|
||||||
|
'^production',
|
||||||
|
];
|
||||||
|
|
||||||
let mfEnvVarExists = false;
|
let mfEnvVarExists = false;
|
||||||
for (const input of nxJson.targetDefaults[webpackExecutor].inputs) {
|
for (const input of nxJson.targetDefaults[webpackExecutor].inputs) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user