Skip to content

Commit

Permalink
fix(angular): cleanup ports on exit of mf server (#10060)
Browse files Browse the repository at this point in the history
  • Loading branch information
Coly010 committed Apr 29, 2022
1 parent ab738fe commit b78d353
Showing 1 changed file with 58 additions and 1 deletion.
Expand Up @@ -5,6 +5,51 @@ import { BuilderContext, createBuilder } from '@angular-devkit/architect';
import { JsonObject } from '@angular-devkit/core';
import { join } from 'path';
import { webpackServer } from '../webpack-server/webpack-server.impl';
import { exec, execSync } from 'child_process';

/**
* Inline kill-port to prevent adding a new dependency
*/
function killPort(port, method = 'tcp') {
port = Number.parseInt(port);

if (!port) {
throw new Error('Invalid argument provided for port');
}

if (process.platform === 'win32') {
return exec('netstat -nao', (error, stdout, stderr) => {
if (!stdout) return;

const lines = stdout.split('\n');
// The second white-space delimited column of netstat output is the local port,
// which is the only port we care about.
// The regex here will match only the local port column of the output
const lineWithLocalPortRegEx = new RegExp(
`^ *${method.toUpperCase()} *[^ ]*:${port}`,
'gm'
);
const linesWithLocalPort = lines.filter((line) =>
line.match(lineWithLocalPortRegEx)
);

const pids = linesWithLocalPort.reduce((acc, line) => {
const match = line.match(/(\d*)\w*(\n|$)/gm);
return match && match[0] && !acc.includes(match[0])
? acc.concat(match[0])
: acc;
}, []);

return execSync(`TaskKill /F /PID ${pids.join(' /PID ')}`);
});
}

return execSync(
`lsof -ni ${method === 'udp' ? 'udp' : 'tcp'}:${port} | grep ${
method === 'udp' ? 'UDP' : 'LISTEN'
} | awk '{print $2}' | xargs kill -9`
);
}

export function moduleFederationDevServer(
schema: Schema,
Expand Down Expand Up @@ -40,13 +85,20 @@ export function moduleFederationDevServer(
? options.devRemotes
: [options.devRemotes];

const remotePorts: number[] = [];
for (const remote of remotes) {
const isDev = devServeRemotes.includes(remote);
const target = isDev ? 'serve' : 'serve-static';

remotePorts.push(
workspaceConfig.projects[remote]?.targets[target]?.options.port ?? 4200
);

scheduleTarget(
context.workspaceRoot,
{
project: remote,
target: isDev ? 'serve' : 'serve-static',
target,
configuration: context.target.configuration,
runOptions: {},
executor: context.builder.builderName,
Expand All @@ -55,6 +107,11 @@ export function moduleFederationDevServer(
);
}

// Cleanup ports on kill
process.on('kill', () => {
remotePorts.forEach((port) => killPort(port));
});

return webpackServer(options, context);
}

Expand Down

0 comments on commit b78d353

Please sign in to comment.