171 lines
6.2 KiB
TypeScript
171 lines
6.2 KiB
TypeScript
import {
|
|
joinPathFragments,
|
|
parseTargetString,
|
|
readCachedProjectGraph,
|
|
} from '@nrwl/devkit';
|
|
import { WebpackNxBuildCoordinationPlugin } from '@nrwl/webpack/src/plugins/webpack-nx-build-coordination-plugin';
|
|
import { DependentBuildableProjectNode } from '@nrwl/js/src/utils/buildable-libs-utils';
|
|
import { readCachedProjectConfiguration } from 'nx/src/project-graph/project-graph';
|
|
import { existsSync } from 'fs';
|
|
import { isNpmProject } from 'nx/src/project-graph/operators';
|
|
import {
|
|
mergeCustomWebpackConfig,
|
|
resolveIndexHtmlTransformer,
|
|
} from '../utilities/webpack';
|
|
import { normalizeOptions } from './lib';
|
|
import type { Schema } from './schema';
|
|
import { createTmpTsConfigForBuildableLibs } from '../utilities/buildable-libs';
|
|
import { from } from 'rxjs';
|
|
import { switchMap } from 'rxjs/operators';
|
|
import { getRootTsConfigPath } from 'nx/src/utils/typescript';
|
|
|
|
export function executeWebpackDevServerBuilder(
|
|
rawOptions: Schema,
|
|
context: import('@angular-devkit/architect').BuilderContext
|
|
) {
|
|
process.env.NX_TSCONFIG_PATH = getRootTsConfigPath();
|
|
|
|
const options = normalizeOptions(rawOptions);
|
|
|
|
const parsedBrowserTarget = parseTargetString(
|
|
options.browserTarget,
|
|
readCachedProjectGraph()
|
|
);
|
|
const browserTargetProjectConfiguration = readCachedProjectConfiguration(
|
|
parsedBrowserTarget.project
|
|
);
|
|
|
|
const buildTarget =
|
|
browserTargetProjectConfiguration.targets[parsedBrowserTarget.target];
|
|
|
|
const buildTargetConfiguration = parsedBrowserTarget.configuration
|
|
? buildTarget.configurations[parsedBrowserTarget.configuration]
|
|
: buildTarget.defaultConfiguration
|
|
? buildTarget.configurations[buildTarget.defaultConfiguration]
|
|
: buildTarget.options;
|
|
|
|
const buildLibsFromSource =
|
|
options.buildLibsFromSource ??
|
|
buildTargetConfiguration?.buildLibsFromSource ??
|
|
buildTarget.options.buildLibsFromSource ??
|
|
true;
|
|
|
|
const customWebpackConfig: { path: string } =
|
|
buildTargetConfiguration?.customWebpackConfig ??
|
|
buildTarget.options.customWebpackConfig;
|
|
|
|
let pathToWebpackConfig: string;
|
|
if (customWebpackConfig && customWebpackConfig.path) {
|
|
pathToWebpackConfig = joinPathFragments(
|
|
context.workspaceRoot,
|
|
customWebpackConfig.path
|
|
);
|
|
|
|
if (pathToWebpackConfig && !existsSync(pathToWebpackConfig)) {
|
|
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}`
|
|
);
|
|
}
|
|
}
|
|
|
|
const indexFileTransformer: string =
|
|
buildTargetConfiguration?.indexFileTransformer ??
|
|
buildTarget.options.indexFileTransformer;
|
|
|
|
let pathToIndexFileTransformer: string;
|
|
if (indexFileTransformer) {
|
|
pathToIndexFileTransformer = joinPathFragments(
|
|
context.workspaceRoot,
|
|
indexFileTransformer
|
|
);
|
|
|
|
if (pathToIndexFileTransformer && !existsSync(pathToIndexFileTransformer)) {
|
|
throw new Error(
|
|
`File containing Index File Transformer function Not Found!\n Please ensure the path to the file containing the function is correct: \n${pathToIndexFileTransformer}`
|
|
);
|
|
}
|
|
}
|
|
|
|
let dependencies: DependentBuildableProjectNode[];
|
|
if (!buildLibsFromSource) {
|
|
const buildTargetTsConfigPath =
|
|
buildTargetConfiguration?.tsConfig ?? buildTarget.options.tsConfig;
|
|
const { tsConfigPath, dependencies: foundDependencies } =
|
|
createTmpTsConfigForBuildableLibs(buildTargetTsConfigPath, context, {
|
|
target: parsedBrowserTarget.target,
|
|
});
|
|
dependencies = foundDependencies;
|
|
|
|
// We can't just pass the tsconfig path in memory to the angular builder
|
|
// function because we can't pass the build target options to it, the build
|
|
// targets options will be retrieved by the builder from the project
|
|
// configuration. Therefore, we patch the method in the context to retrieve
|
|
// the target options to overwrite the tsconfig path to use the generated
|
|
// one with the updated path mappings.
|
|
const originalGetTargetOptions = context.getTargetOptions;
|
|
context.getTargetOptions = async (target) => {
|
|
const options = await originalGetTargetOptions(target);
|
|
options.tsConfig = tsConfigPath;
|
|
return options;
|
|
};
|
|
|
|
// The buildTargetConfiguration also needs to use the generated tsconfig path
|
|
// otherwise the build will fail if customWebpack function/file is referencing
|
|
// local libs. This synchronize the behavior with webpack-browser and
|
|
// webpack-server implementation.
|
|
buildTargetConfiguration.tsConfig = tsConfigPath;
|
|
}
|
|
|
|
return from(import('@angular-devkit/build-angular')).pipe(
|
|
switchMap(({ executeDevServerBuilder }) =>
|
|
executeDevServerBuilder(options, context, {
|
|
webpackConfiguration: async (baseWebpackConfig) => {
|
|
if (!buildLibsFromSource) {
|
|
const workspaceDependencies = dependencies
|
|
.filter((dep) => !isNpmProject(dep.node))
|
|
.map((dep) => dep.node.name);
|
|
// default for `nx run-many` is --all projects
|
|
// by passing an empty string for --projects, run-many will default to
|
|
// run the target for all projects.
|
|
// This will occur when workspaceDependencies = []
|
|
if (workspaceDependencies.length > 0) {
|
|
baseWebpackConfig.plugins.push(
|
|
new WebpackNxBuildCoordinationPlugin(
|
|
`nx run-many --target=${
|
|
parsedBrowserTarget.target
|
|
} --projects=${workspaceDependencies.join(',')}`
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
if (!pathToWebpackConfig) {
|
|
return baseWebpackConfig;
|
|
}
|
|
|
|
return mergeCustomWebpackConfig(
|
|
baseWebpackConfig,
|
|
pathToWebpackConfig,
|
|
buildTargetConfiguration,
|
|
context.target
|
|
);
|
|
},
|
|
|
|
...(pathToIndexFileTransformer
|
|
? {
|
|
indexHtml: resolveIndexHtmlTransformer(
|
|
pathToIndexFileTransformer,
|
|
buildTargetConfiguration.tsConfig,
|
|
context.target
|
|
),
|
|
}
|
|
: {}),
|
|
})
|
|
)
|
|
);
|
|
}
|
|
|
|
export default require('@angular-devkit/architect').createBuilder(
|
|
executeWebpackDevServerBuilder
|
|
) as any;
|