feat(module-federation): add ssr support to rspack crystal plugin (#30437)
## Current Behavior The current `NxModuleFederationPlugin` does not support SSR ## Expected Behavior The current `NxModuleFederationPlugin` supports SSR
This commit is contained in:
parent
32f0acab42
commit
487aa6fa78
@ -2,3 +2,4 @@ export * from './src/with-module-federation/rspack/with-module-federation';
|
|||||||
export * from './src/with-module-federation/rspack/with-module-federation-ssr';
|
export * from './src/with-module-federation/rspack/with-module-federation-ssr';
|
||||||
export * from './src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-plugin';
|
export * from './src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-plugin';
|
||||||
export * from './src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-dev-server-plugin';
|
export * from './src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-dev-server-plugin';
|
||||||
|
export * from './src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-ssr-dev-server-plugin';
|
||||||
|
|||||||
@ -24,24 +24,30 @@ import {
|
|||||||
startStaticRemotesFileServer,
|
startStaticRemotesFileServer,
|
||||||
} from '../../utils';
|
} from '../../utils';
|
||||||
import { NxModuleFederationDevServerConfig } from '../../models';
|
import { NxModuleFederationDevServerConfig } from '../../models';
|
||||||
|
import { ChildProcess, fork } from 'node:child_process';
|
||||||
|
|
||||||
const PLUGIN_NAME = 'NxModuleFederationDevServerPlugin';
|
const PLUGIN_NAME = 'NxModuleFederationDevServerPlugin';
|
||||||
|
|
||||||
export class NxModuleFederationDevServerPlugin implements RspackPluginInstance {
|
export class NxModuleFederationDevServerPlugin implements RspackPluginInstance {
|
||||||
|
private devServerProcess: ChildProcess | undefined;
|
||||||
private nxBin = require.resolve('nx/bin/nx');
|
private nxBin = require.resolve('nx/bin/nx');
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _options: {
|
private _options: {
|
||||||
config: ModuleFederationConfig;
|
config: ModuleFederationConfig;
|
||||||
devServerConfig: NxModuleFederationDevServerConfig;
|
devServerConfig?: NxModuleFederationDevServerConfig;
|
||||||
}
|
}
|
||||||
) {}
|
) {
|
||||||
|
this._options.devServerConfig ??= {
|
||||||
|
host: 'localhost',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
apply(compiler: Compiler) {
|
apply(compiler: Compiler) {
|
||||||
compiler.hooks.beforeCompile.tapAsync(
|
compiler.hooks.beforeCompile.tapAsync(
|
||||||
PLUGIN_NAME,
|
PLUGIN_NAME,
|
||||||
async (params, callback) => {
|
async (params, callback) => {
|
||||||
const staticRemotesConfig = await this.setup();
|
const staticRemotesConfig = await this.setup(compiler);
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
`NX Starting module federation dev-server for ${pc.bold(
|
`NX Starting module federation dev-server for ${pc.bold(
|
||||||
@ -67,12 +73,13 @@ export class NxModuleFederationDevServerPlugin implements RspackPluginInstance {
|
|||||||
new DefinePlugin({
|
new DefinePlugin({
|
||||||
'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
|
'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
|
||||||
}).apply(compiler);
|
}).apply(compiler);
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async setup() {
|
private async setup(compiler: Compiler) {
|
||||||
const projectGraph = readCachedProjectGraph();
|
const projectGraph = readCachedProjectGraph();
|
||||||
const { projects: workspaceProjects } =
|
const { projects: workspaceProjects } =
|
||||||
readProjectsConfigurationFromProjectGraph(projectGraph);
|
readProjectsConfigurationFromProjectGraph(projectGraph);
|
||||||
|
|||||||
@ -12,6 +12,7 @@ export class NxModuleFederationPlugin implements RspackPluginInstance {
|
|||||||
private _options: {
|
private _options: {
|
||||||
config: ModuleFederationConfig;
|
config: ModuleFederationConfig;
|
||||||
devServerConfig?: NxModuleFederationDevServerConfig;
|
devServerConfig?: NxModuleFederationDevServerConfig;
|
||||||
|
isServer?: boolean;
|
||||||
},
|
},
|
||||||
private configOverride?: NxModuleFederationConfigOverride
|
private configOverride?: NxModuleFederationConfigOverride
|
||||||
) {}
|
) {}
|
||||||
@ -23,15 +24,32 @@ export class NxModuleFederationPlugin implements RspackPluginInstance {
|
|||||||
|
|
||||||
// This is required to ensure Module Federation will build the project correctly
|
// This is required to ensure Module Federation will build the project correctly
|
||||||
compiler.options.optimization.runtimeChunk = false;
|
compiler.options.optimization.runtimeChunk = false;
|
||||||
|
compiler.options.output.uniqueName = this._options.config.name;
|
||||||
|
if (this._options.isServer) {
|
||||||
|
compiler.options.target = 'async-node';
|
||||||
|
compiler.options.output.library ??= {
|
||||||
|
type: 'commonjs-module',
|
||||||
|
};
|
||||||
|
compiler.options.output.library.type = 'commonjs-module';
|
||||||
|
}
|
||||||
|
|
||||||
const isDevServer = !!process.env['WEBPACK_SERVE'];
|
const config = getModuleFederationConfig(this._options.config, {
|
||||||
|
isServer: this._options.isServer,
|
||||||
// TODO(colum): Add support for SSR
|
});
|
||||||
const config = getModuleFederationConfig(this._options.config);
|
|
||||||
const sharedLibraries = config.sharedLibraries;
|
const sharedLibraries = config.sharedLibraries;
|
||||||
const sharedDependencies = config.sharedDependencies;
|
const sharedDependencies = config.sharedDependencies;
|
||||||
const mappedRemotes = config.mappedRemotes;
|
const mappedRemotes = config.mappedRemotes;
|
||||||
|
|
||||||
|
const runtimePlugins = [];
|
||||||
|
if (this.configOverride?.runtimePlugins) {
|
||||||
|
runtimePlugins.push(...(this.configOverride.runtimePlugins ?? []));
|
||||||
|
}
|
||||||
|
if (this._options.isServer) {
|
||||||
|
runtimePlugins.push(
|
||||||
|
require.resolve('@module-federation/node/runtimePlugin')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
new (require('@module-federation/enhanced/rspack').ModuleFederationPlugin)({
|
new (require('@module-federation/enhanced/rspack').ModuleFederationPlugin)({
|
||||||
name: this._options.config.name.replace(/-/g, '_'),
|
name: this._options.config.name.replace(/-/g, '_'),
|
||||||
filename: 'remoteEntry.js',
|
filename: 'remoteEntry.js',
|
||||||
@ -40,25 +58,21 @@ export class NxModuleFederationPlugin implements RspackPluginInstance {
|
|||||||
shared: {
|
shared: {
|
||||||
...(sharedDependencies ?? {}),
|
...(sharedDependencies ?? {}),
|
||||||
},
|
},
|
||||||
|
...(this._options.isServer
|
||||||
|
? {
|
||||||
|
library: {
|
||||||
|
type: 'commonjs-module',
|
||||||
|
},
|
||||||
|
remoteType: 'script',
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
...(this.configOverride ? this.configOverride : {}),
|
...(this.configOverride ? this.configOverride : {}),
|
||||||
runtimePlugins: this.configOverride
|
runtimePlugins,
|
||||||
? this.configOverride.runtimePlugins ?? []
|
|
||||||
: [],
|
|
||||||
virtualRuntimeEntry: true,
|
virtualRuntimeEntry: true,
|
||||||
}).apply(compiler);
|
}).apply(compiler);
|
||||||
|
|
||||||
if (sharedLibraries) {
|
if (sharedLibraries) {
|
||||||
sharedLibraries.getReplacementPlugin().apply(compiler as any);
|
sharedLibraries.getReplacementPlugin().apply(compiler as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDevServer) {
|
|
||||||
new NxModuleFederationDevServerPlugin({
|
|
||||||
config: this._options.config,
|
|
||||||
devServerConfig: {
|
|
||||||
...(this._options.devServerConfig ?? {}),
|
|
||||||
host: this._options.devServerConfig?.host ?? 'localhost',
|
|
||||||
},
|
|
||||||
}).apply(compiler);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,187 @@
|
|||||||
|
import {
|
||||||
|
Compilation,
|
||||||
|
Compiler,
|
||||||
|
DefinePlugin,
|
||||||
|
RspackPluginInstance,
|
||||||
|
} from '@rspack/core';
|
||||||
|
import * as pc from 'picocolors';
|
||||||
|
import {
|
||||||
|
logger,
|
||||||
|
readCachedProjectGraph,
|
||||||
|
readProjectsConfigurationFromProjectGraph,
|
||||||
|
workspaceRoot,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { ModuleFederationConfig } from '../../../utils/models';
|
||||||
|
import { dirname, extname, join } from 'path';
|
||||||
|
import { existsSync } from 'fs';
|
||||||
|
import {
|
||||||
|
buildStaticRemotes,
|
||||||
|
getDynamicMfManifestFile,
|
||||||
|
getRemotes,
|
||||||
|
getStaticRemotes,
|
||||||
|
parseRemotesConfig,
|
||||||
|
startRemoteProxies,
|
||||||
|
startStaticRemotesFileServer,
|
||||||
|
} from '../../utils';
|
||||||
|
import { NxModuleFederationDevServerConfig } from '../../models';
|
||||||
|
import { ChildProcess, fork } from 'node:child_process';
|
||||||
|
|
||||||
|
const PLUGIN_NAME = 'NxModuleFederationSSRDevServerPlugin';
|
||||||
|
|
||||||
|
export class NxModuleFederationSSRDevServerPlugin
|
||||||
|
implements RspackPluginInstance
|
||||||
|
{
|
||||||
|
private devServerProcess: ChildProcess | undefined;
|
||||||
|
private nxBin = require.resolve('nx/bin/nx');
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _options: {
|
||||||
|
config: ModuleFederationConfig;
|
||||||
|
devServerConfig?: NxModuleFederationDevServerConfig;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
this._options.devServerConfig ??= {
|
||||||
|
host: 'localhost',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(compiler: Compiler) {
|
||||||
|
compiler.hooks.watchRun.tapAsync(
|
||||||
|
PLUGIN_NAME,
|
||||||
|
async (compiler, callback) => {
|
||||||
|
compiler.hooks.beforeCompile.tapAsync(
|
||||||
|
PLUGIN_NAME,
|
||||||
|
async (params, callback) => {
|
||||||
|
const staticRemotesConfig = await this.setup(compiler);
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
`NX Starting module federation dev-server for ${pc.bold(
|
||||||
|
this._options.config.name
|
||||||
|
)} with ${Object.keys(staticRemotesConfig).length} remotes`
|
||||||
|
);
|
||||||
|
|
||||||
|
const mappedLocationOfRemotes = await buildStaticRemotes(
|
||||||
|
staticRemotesConfig,
|
||||||
|
this._options.devServerConfig,
|
||||||
|
this.nxBin
|
||||||
|
);
|
||||||
|
startStaticRemotesFileServer(
|
||||||
|
staticRemotesConfig,
|
||||||
|
workspaceRoot,
|
||||||
|
this._options.devServerConfig.staticRemotesPort
|
||||||
|
);
|
||||||
|
startRemoteProxies(
|
||||||
|
staticRemotesConfig,
|
||||||
|
mappedLocationOfRemotes,
|
||||||
|
{
|
||||||
|
pathToCert: this._options.devServerConfig.sslCert,
|
||||||
|
pathToKey: this._options.devServerConfig.sslCert,
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
new DefinePlugin({
|
||||||
|
'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
|
||||||
|
}).apply(compiler);
|
||||||
|
|
||||||
|
await this.startServer(compiler);
|
||||||
|
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async startServer(compiler: Compiler) {
|
||||||
|
compiler.hooks.afterEmit.tapAsync(PLUGIN_NAME, async (_, callback) => {
|
||||||
|
const serverPath = join(
|
||||||
|
compiler.options.output.path,
|
||||||
|
(compiler.options.output.filename as string) ?? 'server.js'
|
||||||
|
);
|
||||||
|
if (this.devServerProcess) {
|
||||||
|
await new Promise<void>((res) => {
|
||||||
|
this.devServerProcess.on('exit', () => {
|
||||||
|
res();
|
||||||
|
});
|
||||||
|
this.devServerProcess.kill();
|
||||||
|
this.devServerProcess = undefined;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existsSync(serverPath)) {
|
||||||
|
for (let retries = 0; retries < 10; retries++) {
|
||||||
|
await new Promise<void>((res) => setTimeout(res, 100));
|
||||||
|
if (existsSync(serverPath)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!existsSync(serverPath)) {
|
||||||
|
throw new Error(`Could not find server bundle at ${serverPath}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.devServerProcess = fork(serverPath);
|
||||||
|
process.on('exit', () => {
|
||||||
|
this.devServerProcess?.kill();
|
||||||
|
});
|
||||||
|
process.on('SIGINT', () => {
|
||||||
|
this.devServerProcess?.kill();
|
||||||
|
});
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async setup(compiler: Compiler) {
|
||||||
|
const projectGraph = readCachedProjectGraph();
|
||||||
|
const { projects: workspaceProjects } =
|
||||||
|
readProjectsConfigurationFromProjectGraph(projectGraph);
|
||||||
|
const project = workspaceProjects[this._options.config.name];
|
||||||
|
if (!this._options.devServerConfig.pathToManifestFile) {
|
||||||
|
this._options.devServerConfig.pathToManifestFile =
|
||||||
|
getDynamicMfManifestFile(project, workspaceRoot);
|
||||||
|
} else {
|
||||||
|
const userPathToManifestFile = join(
|
||||||
|
workspaceRoot,
|
||||||
|
this._options.devServerConfig.pathToManifestFile
|
||||||
|
);
|
||||||
|
if (!existsSync(userPathToManifestFile)) {
|
||||||
|
throw new Error(
|
||||||
|
`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`
|
||||||
|
);
|
||||||
|
} else if (
|
||||||
|
extname(this._options.devServerConfig.pathToManifestFile) !== '.json'
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._options.devServerConfig.pathToManifestFile = userPathToManifestFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { remotes, staticRemotePort } = getRemotes(
|
||||||
|
this._options.config,
|
||||||
|
projectGraph,
|
||||||
|
this._options.devServerConfig.pathToManifestFile
|
||||||
|
);
|
||||||
|
this._options.devServerConfig.staticRemotesPort ??= staticRemotePort;
|
||||||
|
|
||||||
|
const remotesConfig = parseRemotesConfig(
|
||||||
|
remotes,
|
||||||
|
workspaceRoot,
|
||||||
|
projectGraph,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
const staticRemotesConfig = await getStaticRemotes(
|
||||||
|
remotesConfig.config ?? {}
|
||||||
|
);
|
||||||
|
const devRemotes = remotes.filter((r) => !staticRemotesConfig[r]);
|
||||||
|
process.env.NX_MF_DEV_REMOTES = JSON.stringify([
|
||||||
|
...(devRemotes.length > 0 ? devRemotes : []),
|
||||||
|
project.name,
|
||||||
|
]);
|
||||||
|
return staticRemotesConfig ?? {};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,7 +6,8 @@ import { StaticRemoteConfig } from '../../utils';
|
|||||||
export function parseRemotesConfig(
|
export function parseRemotesConfig(
|
||||||
remotes: string[] | undefined,
|
remotes: string[] | undefined,
|
||||||
workspaceRoot: string,
|
workspaceRoot: string,
|
||||||
projectGraph: ProjectGraph
|
projectGraph: ProjectGraph,
|
||||||
|
isServer?: boolean
|
||||||
) {
|
) {
|
||||||
if (!remotes?.length) {
|
if (!remotes?.length) {
|
||||||
return { remotes: [], config: undefined };
|
return { remotes: [], config: undefined };
|
||||||
@ -32,7 +33,12 @@ export function parseRemotesConfig(
|
|||||||
const basePath = dirname(outputPath);
|
const basePath = dirname(outputPath);
|
||||||
const urlSegment = app;
|
const urlSegment = app;
|
||||||
const port = projectGraph.nodes[app].data.targets?.['serve']?.options.port;
|
const port = projectGraph.nodes[app].data.targets?.['serve']?.options.port;
|
||||||
config[app] = { basePath, outputPath, urlSegment, port };
|
config[app] = {
|
||||||
|
basePath,
|
||||||
|
outputPath: isServer ? dirname(outputPath) : outputPath,
|
||||||
|
urlSegment,
|
||||||
|
port,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return { remotes, config };
|
return { remotes, config };
|
||||||
|
|||||||
@ -8,7 +8,8 @@ export function startRemoteProxies(
|
|||||||
sslOptions?: {
|
sslOptions?: {
|
||||||
pathToCert: string;
|
pathToCert: string;
|
||||||
pathToKey: string;
|
pathToKey: string;
|
||||||
}
|
},
|
||||||
|
isServer?: boolean
|
||||||
) {
|
) {
|
||||||
const { createProxyMiddleware } = require('http-proxy-middleware');
|
const { createProxyMiddleware } = require('http-proxy-middleware');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
@ -40,6 +41,15 @@ export function startRemoteProxies(
|
|||||||
target: mappedLocationsOfRemotes[app],
|
target: mappedLocationsOfRemotes[app],
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
secure: sslCert ? false : undefined,
|
secure: sslCert ? false : undefined,
|
||||||
|
pathRewrite: isServer
|
||||||
|
? (path) => {
|
||||||
|
if (path.includes('/server')) {
|
||||||
|
return path;
|
||||||
|
} else {
|
||||||
|
return `browser/${path}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
const proxyServer = (sslCert ? https : http)
|
const proxyServer = (sslCert ? https : http)
|
||||||
|
|||||||
@ -34,6 +34,14 @@ export class NxAppRspackPlugin {
|
|||||||
this.options.target = target;
|
this.options.target = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
compiler.options.entry &&
|
||||||
|
compiler.options.entry['main'] &&
|
||||||
|
typeof compiler.options.entry['main'] === 'object' &&
|
||||||
|
Object.keys(compiler.options.entry['main']).length === 0
|
||||||
|
) {
|
||||||
|
compiler.options.entry = {};
|
||||||
|
}
|
||||||
applyBaseConfig(this.options, compiler.options, {
|
applyBaseConfig(this.options, compiler.options, {
|
||||||
useNormalizedEntry: true,
|
useNormalizedEntry: true,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -65,11 +65,11 @@ function applyNxIndependentConfig(
|
|||||||
process.env.NODE_ENV === 'production' || options.mode === 'production';
|
process.env.NODE_ENV === 'production' || options.mode === 'production';
|
||||||
const hashFormat = getOutputHashFormat(options.outputHashing as string);
|
const hashFormat = getOutputHashFormat(options.outputHashing as string);
|
||||||
config.context = path.join(options.root, options.projectRoot);
|
config.context = path.join(options.root, options.projectRoot);
|
||||||
config.target ??= options.target as 'node' | 'web';
|
config.target ??= options.target as 'async-node' | 'node' | 'web';
|
||||||
config.node = false;
|
config.node = false;
|
||||||
config.mode =
|
config.mode =
|
||||||
// When the target is Node avoid any optimizations, such as replacing `process.env.NODE_ENV` with build time value.
|
// When the target is Node avoid any optimizations, such as replacing `process.env.NODE_ENV` with build time value.
|
||||||
config.target === 'node'
|
config.target === 'node' || config.target === 'async-node'
|
||||||
? 'none'
|
? 'none'
|
||||||
: // Otherwise, make sure it matches `process.env.NODE_ENV`.
|
: // Otherwise, make sure it matches `process.env.NODE_ENV`.
|
||||||
// When mode is development or production, rspack will automatically
|
// When mode is development or production, rspack will automatically
|
||||||
@ -86,7 +86,11 @@ function applyNxIndependentConfig(
|
|||||||
: 'none');
|
: 'none');
|
||||||
// When target is Node, the Webpack mode will be set to 'none' which disables in memory caching and causes a full rebuild on every change.
|
// When target is Node, the Webpack mode will be set to 'none' which disables in memory caching and causes a full rebuild on every change.
|
||||||
// So to mitigate this we enable in memory caching when target is Node and in watch mode.
|
// So to mitigate this we enable in memory caching when target is Node and in watch mode.
|
||||||
config.cache = options.target === 'node' && options.watch ? true : undefined;
|
config.cache =
|
||||||
|
(options.target === 'node' || options.target === 'async-node') &&
|
||||||
|
options.watch
|
||||||
|
? true
|
||||||
|
: undefined;
|
||||||
|
|
||||||
config.devtool =
|
config.devtool =
|
||||||
options.sourceMap === true ? 'source-map' : options.sourceMap;
|
options.sourceMap === true ? 'source-map' : options.sourceMap;
|
||||||
@ -94,8 +98,11 @@ function applyNxIndependentConfig(
|
|||||||
config.output = {
|
config.output = {
|
||||||
...(config.output ?? {}),
|
...(config.output ?? {}),
|
||||||
libraryTarget:
|
libraryTarget:
|
||||||
(config as Configuration).output?.libraryTarget ??
|
options.target === 'node'
|
||||||
(options.target === 'node' ? 'commonjs' : undefined),
|
? 'commonjs'
|
||||||
|
: options.target === 'async-node'
|
||||||
|
? 'commonjs-module'
|
||||||
|
: undefined,
|
||||||
path:
|
path:
|
||||||
config.output?.path ??
|
config.output?.path ??
|
||||||
(options.outputPath
|
(options.outputPath
|
||||||
@ -333,7 +340,10 @@ function applyNxDependentConfig(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const externals = [];
|
const externals = [];
|
||||||
if (options.target === 'node' && options.externalDependencies === 'all') {
|
if (
|
||||||
|
(options.target === 'node' || options.target === 'async-node') &&
|
||||||
|
options.externalDependencies === 'all'
|
||||||
|
) {
|
||||||
const modulesDir = `${options.root}/node_modules`;
|
const modulesDir = `${options.root}/node_modules`;
|
||||||
externals.push(nodeExternals({ modulesDir }));
|
externals.push(nodeExternals({ modulesDir }));
|
||||||
} else if (Array.isArray(options.externalDependencies)) {
|
} else if (Array.isArray(options.externalDependencies)) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user