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.",
|
||||
"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": {
|
||||
|
||||
@ -7,7 +7,10 @@ export function addMfEnvToTargetDefaultInputs(tree: Tree) {
|
||||
|
||||
nxJson.targetDefaults ??= {};
|
||||
nxJson.targetDefaults[webpackExecutor] ??= {};
|
||||
nxJson.targetDefaults[webpackExecutor].inputs ??= [];
|
||||
nxJson.targetDefaults[webpackExecutor].inputs ??= [
|
||||
'production',
|
||||
'^production',
|
||||
];
|
||||
|
||||
let mfEnvVarExists = false;
|
||||
for (const input of nxJson.targetDefaults[webpackExecutor].inputs) {
|
||||
|
||||
@ -26,6 +26,8 @@ describe('addMfEnvVarToTargetDefaults', () => {
|
||||
{
|
||||
"@nx/angular:webpack-browser": {
|
||||
"inputs": [
|
||||
"production",
|
||||
"^production",
|
||||
{
|
||||
"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",
|
||||
"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"
|
||||
},
|
||||
"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": {
|
||||
|
||||
@ -25,6 +25,8 @@ describe('addMfEnvVarToTargetDefaults', () => {
|
||||
{
|
||||
"@nx/webpack:webpack": {
|
||||
"inputs": [
|
||||
"production",
|
||||
"^production",
|
||||
{
|
||||
"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[webpackExecutor] ??= {};
|
||||
nxJson.targetDefaults[webpackExecutor].inputs ??= [];
|
||||
nxJson.targetDefaults[webpackExecutor].inputs ??= [
|
||||
'production',
|
||||
'^production',
|
||||
];
|
||||
|
||||
let mfEnvVarExists = false;
|
||||
for (const input of nxJson.targetDefaults[webpackExecutor].inputs) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user