diff --git a/packages/angular/ng-package.json b/packages/angular/ng-package.json index c5e38aed2a4c2..436468c0e9360 100644 --- a/packages/angular/ng-package.json +++ b/packages/angular/ng-package.json @@ -18,7 +18,8 @@ "ts-node", "tsconfig-paths", "semver", - "webpack" + "webpack", + "http-server" ], "keepLifecycleScripts": true } diff --git a/packages/angular/package.json b/packages/angular/package.json index f202433db7512..45ac88b8fe232 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -55,6 +55,7 @@ "ts-node": "~9.1.1", "tsconfig-paths": "^3.9.0", "semver": "7.3.4", - "webpack": "^5.58.1" + "webpack": "^5.58.1", + "http-server": "^14.1.0" } } diff --git a/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts index c8460f621514d..685d17c48f885 100644 --- a/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -5,51 +5,6 @@ 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, @@ -107,11 +62,6 @@ export function moduleFederationDevServer( ); } - // Cleanup ports on kill - process.on('exit', () => { - remotePorts.forEach((port) => killPort(port)); - }); - return webpackServer(options, context); } diff --git a/packages/angular/src/executors/file-server/file-server.impl.ts b/packages/angular/src/executors/file-server/file-server.impl.ts index bff7c510e788d..695133717c7e3 100644 --- a/packages/angular/src/executors/file-server/file-server.impl.ts +++ b/packages/angular/src/executors/file-server/file-server.impl.ts @@ -1,7 +1,8 @@ -import { execFile, execFileSync } from 'child_process'; +import { execFileSync, fork } from 'child_process'; import { ExecutorContext, joinPathFragments, + readJsonFile, workspaceLayout, } from '@nrwl/devkit'; import ignore from 'ignore'; @@ -9,6 +10,7 @@ import { readFileSync } from 'fs'; import { Schema } from './schema'; import { watch } from 'chokidar'; import { platform } from 'os'; +import { resolve } from 'path'; // platform specific command name const pmCmd = platform() === 'win32' ? `npx.cmd` : 'npx'; @@ -147,13 +149,24 @@ export default async function* fileServerExecutor( const outputPath = getBuildTargetOutputPath(options, context); const args = getHttpServerArgs(options); - const serve = execFile(pmCmd, ['http-server', outputPath, ...args], { + const pathToHttpServerPkgJson = require.resolve('http-server/package.json'); + const pathToHttpServerBin = readJsonFile(pathToHttpServerPkgJson).bin[ + 'http-server' + ]; + const pathToHttpServer = resolve( + pathToHttpServerPkgJson.replace('package.json', ''), + pathToHttpServerBin + ); + + const serve = fork(pathToHttpServer, [outputPath, ...args], { + stdio: 'pipe', cwd: context.root, env: { FORCE_COLOR: 'true', ...process.env, }, }); + const processExitListener = () => { serve.kill(); if (disposeWatch) { diff --git a/packages/web/package.json b/packages/web/package.json index 97283cd019607..f4e51eb074dbd 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -69,6 +69,7 @@ "file-loader": "^6.2.0", "fork-ts-checker-webpack-plugin": "6.2.10", "fs-extra": "^9.1.0", + "http-server": "^14.1.0", "identity-obj-proxy": "3.0.0", "less": "3.12.2", "less-loader": "^10.1.0", diff --git a/packages/web/src/executors/file-server/file-server.impl.ts b/packages/web/src/executors/file-server/file-server.impl.ts index a7cde8d4b31cf..2d452d8f7e491 100644 --- a/packages/web/src/executors/file-server/file-server.impl.ts +++ b/packages/web/src/executors/file-server/file-server.impl.ts @@ -1,7 +1,8 @@ -import { execFile, execFileSync } from 'child_process'; +import { execFileSync, fork } from 'child_process'; import { ExecutorContext, joinPathFragments, + readJsonFile, workspaceLayout, } from '@nrwl/devkit'; import ignore from 'ignore'; @@ -9,6 +10,7 @@ import { readFileSync } from 'fs'; import { Schema } from './schema'; import { watch } from 'chokidar'; import { platform } from 'os'; +import { resolve } from 'path'; // platform specific command name const pmCmd = platform() === 'win32' ? `npx.cmd` : 'npx'; @@ -145,13 +147,24 @@ export default async function* fileServerExecutor( const outputPath = getBuildTargetOutputPath(options, context); const args = getHttpServerArgs(options); - const serve = execFile(pmCmd, ['http-server', outputPath, ...args], { + const pathToHttpServerPkgJson = require.resolve('http-server/package.json'); + const pathToHttpServerBin = readJsonFile(pathToHttpServerPkgJson).bin[ + 'http-server' + ]; + const pathToHttpServer = resolve( + pathToHttpServerPkgJson.replace('package.json', ''), + pathToHttpServerBin + ); + + const serve = fork(pathToHttpServer, [outputPath, ...args], { + stdio: 'pipe', cwd: context.root, env: { FORCE_COLOR: 'true', ...process.env, }, }); + const processExitListener = () => { serve.kill(); if (disposeWatch) {