feat(react): use TS config files for module federation (#19455)
This commit is contained in:
parent
cbeed02ee5
commit
14643b68b5
@ -164,7 +164,7 @@
|
|||||||
"typescriptConfiguration": {
|
"typescriptConfiguration": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether the module federation configuration and webpack configuration files should use TS.",
|
"description": "Whether the module federation configuration and webpack configuration files should use TS.",
|
||||||
"default": false
|
"default": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name"],
|
"required": ["name"],
|
||||||
|
|||||||
@ -162,7 +162,7 @@
|
|||||||
"typescriptConfiguration": {
|
"typescriptConfiguration": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether the module federation configuration and webpack configuration files should use TS.",
|
"description": "Whether the module federation configuration and webpack configuration files should use TS.",
|
||||||
"default": false
|
"default": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name"],
|
"required": ["name"],
|
||||||
|
|||||||
@ -45,10 +45,10 @@ describe('React Module Federation', () => {
|
|||||||
`generate @nx/react:remote ${remote3} --style=css --host=${shell} --no-interactive`
|
`generate @nx/react:remote ${remote3} --style=css --host=${shell} --no-interactive`
|
||||||
);
|
);
|
||||||
|
|
||||||
checkFilesExist(`apps/${shell}/module-federation.config.js`);
|
checkFilesExist(`apps/${shell}/module-federation.config.ts`);
|
||||||
checkFilesExist(`apps/${remote1}/module-federation.config.js`);
|
checkFilesExist(`apps/${remote1}/module-federation.config.ts`);
|
||||||
checkFilesExist(`apps/${remote2}/module-federation.config.js`);
|
checkFilesExist(`apps/${remote2}/module-federation.config.ts`);
|
||||||
checkFilesExist(`apps/${remote3}/module-federation.config.js`);
|
checkFilesExist(`apps/${remote3}/module-federation.config.ts`);
|
||||||
|
|
||||||
await expect(runCLIAsync(`test ${shell}`)).resolves.toMatchObject({
|
await expect(runCLIAsync(`test ${shell}`)).resolves.toMatchObject({
|
||||||
combinedOutput: expect.stringContaining('Test Suites: 1 passed, 1 total'),
|
combinedOutput: expect.stringContaining('Test Suites: 1 passed, 1 total'),
|
||||||
@ -60,15 +60,15 @@ describe('React Module Federation', () => {
|
|||||||
expect(readPort(remote3)).toEqual(4203);
|
expect(readPort(remote3)).toEqual(4203);
|
||||||
|
|
||||||
updateFile(
|
updateFile(
|
||||||
`apps/${shell}/webpack.config.js`,
|
`apps/${shell}/webpack.config.ts`,
|
||||||
stripIndents`
|
stripIndents`
|
||||||
const { composePlugins, withNx, ModuleFederationConfig } = require('@nx/webpack');
|
import { composePlugins, withNx, ModuleFederationConfig } from '@nx/webpack';
|
||||||
const { withReact } = require('@nx/react');
|
import { withReact } from '@nx/react';
|
||||||
const { withModuleFederation } = require('@nx/react/module-federation');
|
import { withModuleFederation } from '@nx/react/module-federation';
|
||||||
|
|
||||||
const baseConfig = require('./module-federation.config');
|
import baseConfig from './module-federation.config';
|
||||||
|
|
||||||
const config = {
|
const config: ModuleFederationConfig = {
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
remotes: [
|
remotes: [
|
||||||
'${remote1}',
|
'${remote1}',
|
||||||
@ -114,8 +114,17 @@ describe('React Module Federation', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (runE2ETests()) {
|
if (runE2ETests()) {
|
||||||
const e2eResults = runCLI(`e2e ${shell}-e2e --no-watch --verbose`);
|
const e2eResultsSwc = runCLI(`e2e ${shell}-e2e --no-watch --verbose`);
|
||||||
expect(e2eResults).toContain('All specs passed!');
|
expect(e2eResultsSwc).toContain('All specs passed!');
|
||||||
|
await killPorts(readPort(shell));
|
||||||
|
await killPorts(readPort(remote1));
|
||||||
|
await killPorts(readPort(remote2));
|
||||||
|
await killPorts(readPort(remote3));
|
||||||
|
|
||||||
|
const e2eResultsTsNode = runCLI(`e2e ${shell}-e2e --no-watch --verbose`, {
|
||||||
|
env: { NX_PREFER_TS_NODE: 'true' },
|
||||||
|
});
|
||||||
|
expect(e2eResultsTsNode).toContain('All specs passed!');
|
||||||
await killPorts(readPort(shell));
|
await killPorts(readPort(shell));
|
||||||
await killPorts(readPort(remote1));
|
await killPorts(readPort(remote1));
|
||||||
await killPorts(readPort(remote2));
|
await killPorts(readPort(remote2));
|
||||||
@ -137,15 +146,20 @@ describe('React Module Federation', () => {
|
|||||||
|
|
||||||
// check files are generated without the layout directory ("apps/") and
|
// check files are generated without the layout directory ("apps/") and
|
||||||
// using the project name as the directory when no directory is provided
|
// using the project name as the directory when no directory is provided
|
||||||
checkFilesExist(`${shell}/module-federation.config.js`);
|
checkFilesExist(`${shell}/module-federation.config.ts`);
|
||||||
checkFilesExist(`${remote}/module-federation.config.js`);
|
checkFilesExist(`${remote}/module-federation.config.ts`);
|
||||||
|
|
||||||
// check default generated host is built successfully
|
// check default generated host is built successfully
|
||||||
const buildOutput = runCLI(`run ${shell}:build:development`);
|
const buildOutputSwc = runCLI(`run ${shell}:build:development`);
|
||||||
expect(buildOutput).toContain('Successfully ran target build');
|
expect(buildOutputSwc).toContain('Successfully ran target build');
|
||||||
|
|
||||||
|
const buildOutputTsNode = runCLI(`run ${shell}:build:development`, {
|
||||||
|
env: { NX_PREFER_TS_NODE: 'true' },
|
||||||
|
});
|
||||||
|
expect(buildOutputTsNode).toContain('Successfully ran target build');
|
||||||
|
|
||||||
// check serves devRemotes ok
|
// check serves devRemotes ok
|
||||||
const shellProcess = await runCommandUntil(
|
const shellProcessSwc = await runCommandUntil(
|
||||||
`serve ${shell} --devRemotes=${remote} --verbose`,
|
`serve ${shell} --devRemotes=${remote} --verbose`,
|
||||||
(output) => {
|
(output) => {
|
||||||
return output.includes(
|
return output.includes(
|
||||||
@ -153,7 +167,20 @@ describe('React Module Federation', () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
await killProcessAndPorts(shellProcess.pid, shellPort);
|
await killProcessAndPorts(shellProcessSwc.pid, shellPort);
|
||||||
|
|
||||||
|
const shellProcessTsNode = await runCommandUntil(
|
||||||
|
`serve ${shell} --devRemotes=${remote} --verbose`,
|
||||||
|
(output) => {
|
||||||
|
return output.includes(
|
||||||
|
`All remotes started, server ready at http://localhost:${shellPort}`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
env: { NX_PREFER_TS_NODE: 'true' },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
await killProcessAndPorts(shellProcessTsNode.pid, shellPort);
|
||||||
}, 500_000);
|
}, 500_000);
|
||||||
|
|
||||||
it('should support different versions workspace libs for host and remote', async () => {
|
it('should support different versions workspace libs for host and remote', async () => {
|
||||||
@ -305,31 +332,31 @@ describe('React Module Federation', () => {
|
|||||||
|
|
||||||
// update host and remote to use library type var
|
// update host and remote to use library type var
|
||||||
updateFile(
|
updateFile(
|
||||||
`${shell}/module-federation.config.js`,
|
`${shell}/module-federation.config.ts`,
|
||||||
stripIndents`
|
stripIndents`
|
||||||
const { ModuleFederationConfig } = require('@nx/webpack');
|
import { ModuleFederationConfig } from '@nx/webpack';
|
||||||
|
|
||||||
const config = {
|
const config: ModuleFederationConfig = {
|
||||||
name: '${shell}',
|
name: '${shell}',
|
||||||
library: { type: 'var', name: '${shell}' },
|
library: { type: 'var', name: '${shell}' },
|
||||||
remotes: ['${remote}'],
|
remotes: ['${remote}'],
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = config;
|
export default config;
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
|
||||||
updateFile(
|
updateFile(
|
||||||
`${shell}/webpack.config.prod.js`,
|
`${shell}/webpack.config.prod.ts`,
|
||||||
`module.exports = require('./webpack.config');`
|
`export { default } from './webpack.config';`
|
||||||
);
|
);
|
||||||
|
|
||||||
updateFile(
|
updateFile(
|
||||||
`${remote}/module-federation.config.js`,
|
`${remote}/module-federation.config.ts`,
|
||||||
stripIndents`
|
stripIndents`
|
||||||
const { ModuleFederationConfig } = require('@nx/webpack');
|
import { ModuleFederationConfig } from '@nx/webpack';
|
||||||
|
|
||||||
const config = {
|
const config: ModuleFederationConfig = {
|
||||||
name: '${remote}',
|
name: '${remote}',
|
||||||
library: { type: 'var', name: '${remote}' },
|
library: { type: 'var', name: '${remote}' },
|
||||||
exposes: {
|
exposes: {
|
||||||
@ -337,13 +364,13 @@ describe('React Module Federation', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = config;
|
export default config;
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
|
||||||
updateFile(
|
updateFile(
|
||||||
`${remote}/webpack.config.prod.js`,
|
`${remote}/webpack.config.prod.ts`,
|
||||||
`module.exports = require('./webpack.config');`
|
`export { default } from './webpack.config';`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update host e2e test to check that the remote works with library type var via navigation
|
// Update host e2e test to check that the remote works with library type var via navigation
|
||||||
@ -379,11 +406,25 @@ describe('React Module Federation', () => {
|
|||||||
expect(remoteOutput).toContain('Successfully ran target build');
|
expect(remoteOutput).toContain('Successfully ran target build');
|
||||||
|
|
||||||
if (runE2ETests()) {
|
if (runE2ETests()) {
|
||||||
const hostE2eResults = runCLI(`e2e ${shell}-e2e --no-watch --verbose`);
|
const hostE2eResultsSwc = runCLI(`e2e ${shell}-e2e --no-watch --verbose`);
|
||||||
const remoteE2eResults = runCLI(`e2e ${remote}-e2e --no-watch --verbose`);
|
const remoteE2eResultsSwc = runCLI(
|
||||||
|
`e2e ${remote}-e2e --no-watch --verbose`
|
||||||
|
);
|
||||||
|
|
||||||
expect(hostE2eResults).toContain('All specs passed!');
|
expect(hostE2eResultsSwc).toContain('All specs passed!');
|
||||||
expect(remoteE2eResults).toContain('All specs passed!');
|
expect(remoteE2eResultsSwc).toContain('All specs passed!');
|
||||||
|
|
||||||
|
const hostE2eResultsTsNode = runCLI(
|
||||||
|
`e2e ${shell}-e2e --no-watch --verbose`,
|
||||||
|
{ env: { NX_PREFER_TS_NODE: 'true' } }
|
||||||
|
);
|
||||||
|
const remoteE2eResultsTsNode = runCLI(
|
||||||
|
`e2e ${remote}-e2e --no-watch --verbose`,
|
||||||
|
{ env: { NX_PREFER_TS_NODE: 'true' } }
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(hostE2eResultsTsNode).toContain('All specs passed!');
|
||||||
|
expect(remoteE2eResultsTsNode).toContain('All specs passed!');
|
||||||
}
|
}
|
||||||
}, 500_000);
|
}, 500_000);
|
||||||
|
|
||||||
|
|||||||
@ -253,7 +253,9 @@ function buildTargetWebpack(
|
|||||||
if (options.webpackConfig) {
|
if (options.webpackConfig) {
|
||||||
customWebpack = resolveCustomWebpackConfig(
|
customWebpack = resolveCustomWebpackConfig(
|
||||||
options.webpackConfig,
|
options.webpackConfig,
|
||||||
options.tsConfig
|
options.tsConfig.startsWith(context.root)
|
||||||
|
? options.tsConfig
|
||||||
|
: join(context.root, options.tsConfig)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -54,9 +54,12 @@ function getModuleFederationConfig(
|
|||||||
let moduleFederationConfigPath = moduleFederationConfigPathJS;
|
let moduleFederationConfigPath = moduleFederationConfigPathJS;
|
||||||
|
|
||||||
// create a no-op so this can be called with issue
|
// create a no-op so this can be called with issue
|
||||||
|
const fullTSconfigPath = tsconfigPath.startsWith(workspaceRoot)
|
||||||
|
? tsconfigPath
|
||||||
|
: join(workspaceRoot, tsconfigPath);
|
||||||
let cleanupTranspiler = () => {};
|
let cleanupTranspiler = () => {};
|
||||||
if (existsSync(moduleFederationConfigPathTS)) {
|
if (existsSync(moduleFederationConfigPathTS)) {
|
||||||
cleanupTranspiler = registerTsProject(join(workspaceRoot, tsconfigPath));
|
cleanupTranspiler = registerTsProject(fullTSconfigPath);
|
||||||
moduleFederationConfigPath = moduleFederationConfigPathTS;
|
moduleFederationConfigPath = moduleFederationConfigPathTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,8 @@ import {
|
|||||||
ExecutorContext,
|
ExecutorContext,
|
||||||
getPackageManagerCommand,
|
getPackageManagerCommand,
|
||||||
logger,
|
logger,
|
||||||
|
parseTargetString,
|
||||||
|
readTargetOptions,
|
||||||
runExecutor,
|
runExecutor,
|
||||||
workspaceRoot,
|
workspaceRoot,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
@ -16,6 +18,8 @@ import {
|
|||||||
tapAsyncIterable,
|
tapAsyncIterable,
|
||||||
} from '@nx/devkit/src/utils/async-iterable';
|
} from '@nx/devkit/src/utils/async-iterable';
|
||||||
import { execSync, fork } from 'child_process';
|
import { execSync, fork } from 'child_process';
|
||||||
|
import { existsSync } from 'fs';
|
||||||
|
import { registerTsProject } from '@nx/js/src/internal';
|
||||||
|
|
||||||
type ModuleFederationDevServerOptions = WebSsrDevServerOptions & {
|
type ModuleFederationDevServerOptions = WebSsrDevServerOptions & {
|
||||||
devRemotes?: string | string[];
|
devRemotes?: string | string[];
|
||||||
@ -23,29 +27,70 @@ type ModuleFederationDevServerOptions = WebSsrDevServerOptions & {
|
|||||||
host: string;
|
host: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getBuildOptions(buildTarget: string, context: ExecutorContext) {
|
||||||
|
const target = parseTargetString(buildTarget, context);
|
||||||
|
|
||||||
|
const buildOptions = readTargetOptions(target, context);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...buildOptions,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getModuleFederationConfig(
|
||||||
|
tsconfigPath: string,
|
||||||
|
workspaceRoot: string,
|
||||||
|
projectRoot: string
|
||||||
|
) {
|
||||||
|
const moduleFederationConfigPathJS = join(
|
||||||
|
workspaceRoot,
|
||||||
|
projectRoot,
|
||||||
|
'module-federation.config.js'
|
||||||
|
);
|
||||||
|
|
||||||
|
const moduleFederationConfigPathTS = join(
|
||||||
|
workspaceRoot,
|
||||||
|
projectRoot,
|
||||||
|
'module-federation.config.ts'
|
||||||
|
);
|
||||||
|
|
||||||
|
let moduleFederationConfigPath = moduleFederationConfigPathJS;
|
||||||
|
|
||||||
|
const fullTSconfigPath = tsconfigPath.startsWith(workspaceRoot)
|
||||||
|
? tsconfigPath
|
||||||
|
: join(workspaceRoot, tsconfigPath);
|
||||||
|
// create a no-op so this can be called with issue
|
||||||
|
let cleanupTranspiler = () => {};
|
||||||
|
if (existsSync(moduleFederationConfigPathTS)) {
|
||||||
|
cleanupTranspiler = registerTsProject(fullTSconfigPath);
|
||||||
|
moduleFederationConfigPath = moduleFederationConfigPathTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const config = require(moduleFederationConfigPath);
|
||||||
|
cleanupTranspiler();
|
||||||
|
|
||||||
|
return config.default || config;
|
||||||
|
} catch {
|
||||||
|
throw new Error(
|
||||||
|
`Could not load ${moduleFederationConfigPath}. Was this project generated with "@nx/react:host"?\nSee: https://nx.dev/concepts/more-concepts/faster-builds-with-module-federation`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default async function* moduleFederationSsrDevServer(
|
export default async function* moduleFederationSsrDevServer(
|
||||||
options: ModuleFederationDevServerOptions,
|
options: ModuleFederationDevServerOptions,
|
||||||
context: ExecutorContext
|
context: ExecutorContext
|
||||||
) {
|
) {
|
||||||
let iter: any = ssrDevServerExecutor(options, context);
|
let iter: any = ssrDevServerExecutor(options, context);
|
||||||
const p = context.projectsConfigurations.projects[context.projectName];
|
const p = context.projectsConfigurations.projects[context.projectName];
|
||||||
|
const buildOptions = getBuildOptions(options.browserTarget, context);
|
||||||
const moduleFederationConfigPath = join(
|
const moduleFederationConfig = getModuleFederationConfig(
|
||||||
|
buildOptions.tsConfig,
|
||||||
context.root,
|
context.root,
|
||||||
p.root,
|
p.root
|
||||||
'module-federation.config.js'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let moduleFederationConfig: any;
|
|
||||||
try {
|
|
||||||
moduleFederationConfig = require(moduleFederationConfigPath);
|
|
||||||
} catch {
|
|
||||||
// TODO(jack): Add a link to guide
|
|
||||||
throw new Error(
|
|
||||||
`Could not load ${moduleFederationConfigPath}. Was this project generated with "@nx/react:host"?`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const remotesToSkip = new Set(options.skipRemotes ?? []);
|
const remotesToSkip = new Set(options.skipRemotes ?? []);
|
||||||
const remotesNotInWorkspace: string[] = [];
|
const remotesNotInWorkspace: string[] = [];
|
||||||
const knownRemotes = (moduleFederationConfig.remotes ?? []).filter((r) => {
|
const knownRemotes = (moduleFederationConfig.remotes ?? []).filter((r) => {
|
||||||
|
|||||||
@ -32,7 +32,9 @@ export function addPathToExposes(
|
|||||||
) {
|
) {
|
||||||
const moduleFederationConfigPath = joinPathFragments(
|
const moduleFederationConfigPath = joinPathFragments(
|
||||||
projectPath,
|
projectPath,
|
||||||
'module-federation.config.js'
|
tree.exists(joinPathFragments(projectPath, 'module-federation.config.ts'))
|
||||||
|
? 'module-federation.config.ts'
|
||||||
|
: 'module-federation.config.js'
|
||||||
);
|
);
|
||||||
|
|
||||||
updateExposesProperty(
|
updateExposesProperty(
|
||||||
@ -51,9 +53,11 @@ export function addPathToExposes(
|
|||||||
export function checkRemoteExists(tree: Tree, remoteName: string) {
|
export function checkRemoteExists(tree: Tree, remoteName: string) {
|
||||||
const remote = getRemote(tree, remoteName);
|
const remote = getRemote(tree, remoteName);
|
||||||
if (!remote) return false;
|
if (!remote) return false;
|
||||||
const hasModuleFederationConfig = tree.exists(
|
const hasModuleFederationConfig =
|
||||||
joinPathFragments(remote.root, 'module-federation.config.js')
|
tree.exists(
|
||||||
);
|
joinPathFragments(remote.root, 'module-federation.config.js')
|
||||||
|
) ||
|
||||||
|
tree.exists(joinPathFragments(remote.root, 'module-federation.config.ts'));
|
||||||
|
|
||||||
return hasModuleFederationConfig ? remote : false;
|
return hasModuleFederationConfig ? remote : false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -170,7 +170,7 @@
|
|||||||
"typescriptConfiguration": {
|
"typescriptConfiguration": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether the module federation configuration and webpack configuration files should use TS.",
|
"description": "Whether the module federation configuration and webpack configuration files should use TS.",
|
||||||
"default": false
|
"default": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name"],
|
"required": ["name"],
|
||||||
|
|||||||
@ -168,7 +168,7 @@
|
|||||||
"typescriptConfiguration": {
|
"typescriptConfiguration": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether the module federation configuration and webpack configuration files should use TS.",
|
"description": "Whether the module federation configuration and webpack configuration files should use TS.",
|
||||||
"default": false
|
"default": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name"],
|
"required": ["name"],
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import { normalizeOptions } from './lib/normalize-options';
|
|||||||
|
|
||||||
async function getWebpackConfigs(
|
async function getWebpackConfigs(
|
||||||
options: NormalizedWebpackExecutorOptions,
|
options: NormalizedWebpackExecutorOptions,
|
||||||
|
projectRoot: string,
|
||||||
context: ExecutorContext
|
context: ExecutorContext
|
||||||
): Promise<Configuration | Configuration[]> {
|
): Promise<Configuration | Configuration[]> {
|
||||||
if (options.isolatedConfig && !options.webpackConfig) {
|
if (options.isolatedConfig && !options.webpackConfig) {
|
||||||
@ -41,11 +42,12 @@ async function getWebpackConfigs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let customWebpack = null;
|
let customWebpack = null;
|
||||||
|
|
||||||
if (options.webpackConfig) {
|
if (options.webpackConfig) {
|
||||||
customWebpack = resolveCustomWebpackConfig(
|
customWebpack = resolveCustomWebpackConfig(
|
||||||
options.webpackConfig,
|
options.webpackConfig,
|
||||||
options.tsConfig
|
options.tsConfig.startsWith(context.root)
|
||||||
|
? options.tsConfig
|
||||||
|
: join(context.root, options.tsConfig)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (typeof customWebpack.then === 'function') {
|
if (typeof customWebpack.then === 'function') {
|
||||||
@ -153,7 +155,7 @@ export async function* webpackExecutor(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const configs = await getWebpackConfigs(options, context);
|
const configs = await getWebpackConfigs(options, metadata.root, context);
|
||||||
|
|
||||||
return yield* eachValueFrom(
|
return yield* eachValueFrom(
|
||||||
of(configs).pipe(
|
of(configs).pipe(
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export type SharedWorkspaceLibraryConfig = {
|
|||||||
getReplacementPlugin: () => NormalModuleReplacementPlugin;
|
getReplacementPlugin: () => NormalModuleReplacementPlugin;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Remotes = string[] | [remoteName: string, remoteUrl: string][];
|
export type Remotes = Array<string | [remoteName: string, remoteUrl: string]>;
|
||||||
|
|
||||||
export interface SharedLibraryConfig {
|
export interface SharedLibraryConfig {
|
||||||
singleton?: boolean;
|
singleton?: boolean;
|
||||||
|
|||||||
@ -2,15 +2,24 @@ import { registerTsProject } from '@nx/js/src/internal';
|
|||||||
|
|
||||||
export function resolveCustomWebpackConfig(path: string, tsConfig: string) {
|
export function resolveCustomWebpackConfig(path: string, tsConfig: string) {
|
||||||
const cleanupTranspiler = registerTsProject(tsConfig);
|
const cleanupTranspiler = registerTsProject(tsConfig);
|
||||||
const customWebpackConfig = require(path);
|
const maybeCustomWebpackConfig = require(path);
|
||||||
cleanupTranspiler();
|
cleanupTranspiler();
|
||||||
|
|
||||||
// If the user provides a configuration in TS file
|
// If the user provides a configuration in TS file
|
||||||
// then there are 2 cases for exporing an object. The first one is:
|
// then there are 3 cases for exporing an object. The first one is:
|
||||||
// `module.exports = { ... }`. And the second one is:
|
// `module.exports = { ... }`. And the second one is:
|
||||||
// `export default { ... }`. The ESM format is compiled into:
|
// `export default { ... }`. The ESM format is compiled into:
|
||||||
// `{ default: { ... } }`
|
// `{ default: { ... } }`
|
||||||
return customWebpackConfig.default || customWebpackConfig;
|
// There is also a case of
|
||||||
|
// `{ default: { default: { ... } }`
|
||||||
|
const customWebpackConfig =
|
||||||
|
'default' in maybeCustomWebpackConfig
|
||||||
|
? 'default' in maybeCustomWebpackConfig.default
|
||||||
|
? maybeCustomWebpackConfig.default.default
|
||||||
|
: maybeCustomWebpackConfig.default
|
||||||
|
: maybeCustomWebpackConfig;
|
||||||
|
|
||||||
|
return customWebpackConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isRegistered() {
|
export function isRegistered() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user