nx/packages/angular/src/builders/webpack-server/webpack-server.impl.ts
Colum Ferry f17e5efc08
fix(module-federation): ssr uses async-node with runtime plugin (#27492)
- fix(module-federation): SSR should work correctly
- fix(module-federation): ssr-dev-servers should wait for remotes before
starting final executor

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2024-09-04 11:33:24 -04:00

115 lines
3.9 KiB
TypeScript

import {
joinPathFragments,
normalizePath,
targetToTargetString,
} from '@nx/devkit';
import { existsSync } from 'fs';
import { relative } from 'path';
import { Observable, from } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { createTmpTsConfigForBuildableLibs } from '../utilities/buildable-libs';
import { mergeCustomWebpackConfig } from '../utilities/webpack';
import { Schema } from './schema';
function buildServerApp(
options: Schema,
context: import('@angular-devkit/architect').BuilderContext
): Observable<import('@angular-devkit/build-angular').ServerBuilderOutput> {
const { buildLibsFromSource, customWebpackConfig, ...delegateOptions } =
options;
// If there is a path to custom webpack config
// Invoke our own support for custom webpack config
if (customWebpackConfig && customWebpackConfig.path) {
const pathToWebpackConfig = joinPathFragments(
context.workspaceRoot,
customWebpackConfig.path
);
if (existsSync(pathToWebpackConfig)) {
return buildServerAppWithCustomWebpackConfiguration(
delegateOptions,
context,
pathToWebpackConfig
);
} else {
throw new Error(
`Custom Webpack Config File Not Found!\nTo use a custom webpack config, please ensure the path to the custom webpack file is correct: \n${pathToWebpackConfig}`
);
}
}
return from(import('@angular-devkit/build-angular')).pipe(
switchMap(({ executeServerBuilder }) =>
executeServerBuilder(delegateOptions, context)
)
);
}
function buildServerAppWithCustomWebpackConfiguration(
options: Schema,
context: import('@angular-devkit/architect').BuilderContext,
pathToWebpackConfig: string
) {
return from(import('@angular-devkit/build-angular')).pipe(
switchMap(({ executeServerBuilder }) =>
executeServerBuilder(options, context as any, {
webpackConfiguration: async (baseWebpackConfig) => {
// Angular auto includes code from @angular/platform-server
// This includes the code outside the shared scope created by ModuleFederation
// This code will be included in the generated code from our generators,
// maintaining it within the shared scope.
// Therefore, if the build is an MF Server build, remove the auto-includes from
// the base webpack config from Angular
let mergedConfig = await mergeCustomWebpackConfig(
baseWebpackConfig,
pathToWebpackConfig,
options,
context.target
);
if (mergedConfig.target === 'async-node') {
mergedConfig.entry.main = mergedConfig.entry.main.filter(
(m) => !m.startsWith('@angular/platform-server/init')
);
mergedConfig.module.rules = mergedConfig.module.rules.filter((m) =>
!m.loader
? true
: !m.loader.endsWith(
'@angular-devkit/build-angular/src/builders/server/platform-server-exports-loader.js'
)
);
}
return mergedConfig;
},
})
)
);
}
export function executeWebpackServerBuilder(
options: Schema,
context: import('@angular-devkit/architect').BuilderContext
): Observable<import('@angular-devkit/build-angular').ServerBuilderOutput> {
options.buildLibsFromSource ??= true;
process.env.NX_BUILD_LIBS_FROM_SOURCE = `${options.buildLibsFromSource}`;
process.env.NX_BUILD_TARGET = targetToTargetString({ ...context.target });
if (!options.buildLibsFromSource) {
const { tsConfigPath } = createTmpTsConfigForBuildableLibs(
options.tsConfig,
context
);
options.tsConfig = normalizePath(
relative(context.workspaceRoot, tsConfigPath)
);
}
return buildServerApp(options, context);
}
export default require('@angular-devkit/architect').createBuilder(
executeWebpackServerBuilder
) as any;