feat(@angular-devkit/build-angular): add esbuild-based builder initial support for fileReplacements

Support for the `fileReplacements` option from the Webpack-based builder has now been integrated into
the experimental esbuild-based browser application builder. The option will no longer be ignored during
builds. Only the officially supported form of the option (`replace`/`with` fields) is implemented.
This commit is contained in:
Charles Lyding 2022-09-16 10:21:18 -04:00 committed by Douglas Parker
parent ca5648975c
commit 1c527a9da5
4 changed files with 34 additions and 32 deletions

View File

@ -128,6 +128,7 @@ export function createCompilerPlugin(
tsconfig: string; tsconfig: string;
advancedOptimizations?: boolean; advancedOptimizations?: boolean;
thirdPartySourcemaps?: boolean; thirdPartySourcemaps?: boolean;
fileReplacements?: Record<string, string>;
}, },
styleOptions: BundleStylesheetOptions, styleOptions: BundleStylesheetOptions,
): Plugin { ): Plugin {
@ -256,6 +257,13 @@ export function createCompilerPlugin(
return { content: contents }; return { content: contents };
}; };
// Augment TypeScript Host for file replacements option
if (pluginOptions.fileReplacements) {
// Temporary deep import for file replacements support
const { augmentHostWithReplacements } = require('@ngtools/webpack/src/ivy/host');
augmentHostWithReplacements(host, pluginOptions.fileReplacements);
}
// Create the Angular specific program that contains the Angular compiler // Create the Angular specific program that contains the Angular compiler
const angularProgram = new compilerCli.NgtscProgram(rootNames, compilerOptions, host); const angularProgram = new compilerCli.NgtscProgram(rootNames, compilerOptions, host);
const angularCompiler = angularProgram.compiler; const angularCompiler = angularProgram.compiler;
@ -316,7 +324,9 @@ export function createCompilerPlugin(
async (args) => { async (args) => {
assert.ok(fileEmitter, 'Invalid plugin execution order'); assert.ok(fileEmitter, 'Invalid plugin execution order');
const typescriptResult = await fileEmitter(args.path); const typescriptResult = await fileEmitter(
pluginOptions.fileReplacements?.[args.path] ?? args.path,
);
if (!typescriptResult) { if (!typescriptResult) {
// No TS result indicates the file is not part of the TypeScript program. // No TS result indicates the file is not part of the TypeScript program.
// If allowJs is enabled and the file is JS then defer to the next load hook. // If allowJs is enabled and the file is JS then defer to the next load hook.

View File

@ -13,7 +13,6 @@ const UNSUPPORTED_OPTIONS: Array<keyof BrowserBuilderOptions> = [
'allowedCommonJsDependencies', 'allowedCommonJsDependencies',
'budgets', 'budgets',
'extractLicenses', 'extractLicenses',
'fileReplacements',
'progress', 'progress',
'scripts', 'scripts',
'statsJson', 'statsJson',

View File

@ -249,6 +249,17 @@ async function bundleCode(
sourcemapOptions: SourceMapClass, sourcemapOptions: SourceMapClass,
tsconfig: string, tsconfig: string,
) { ) {
let fileReplacements: Record<string, string> | undefined;
if (options.fileReplacements) {
for (const replacement of options.fileReplacements) {
fileReplacements ??= {};
fileReplacements[path.join(workspaceRoot, replacement.replace)] = path.join(
workspaceRoot,
replacement.with,
);
}
}
return bundle({ return bundle({
absWorkingDir: workspaceRoot, absWorkingDir: workspaceRoot,
bundle: true, bundle: true,
@ -288,6 +299,7 @@ async function bundleCode(
thirdPartySourcemaps: sourcemapOptions.vendor, thirdPartySourcemaps: sourcemapOptions.vendor,
tsconfig, tsconfig,
advancedOptimizations: options.buildOptimizer, advancedOptimizations: options.buildOptimizer,
fileReplacements,
}, },
// Component stylesheet options // Component stylesheet options
{ {

View File

@ -461,38 +461,19 @@
] ]
}, },
"fileReplacement": { "fileReplacement": {
"oneOf": [ "type": "object",
{ "properties": {
"type": "object", "replace": {
"properties": { "type": "string",
"src": { "pattern": "\\.(([cm]?j|t)sx?|json)$"
"type": "string",
"pattern": "\\.(([cm]?j|t)sx?|json)$"
},
"replaceWith": {
"type": "string",
"pattern": "\\.(([cm]?j|t)sx?|json)$"
}
},
"additionalProperties": false,
"required": ["src", "replaceWith"]
}, },
{ "with": {
"type": "object", "type": "string",
"properties": { "pattern": "\\.(([cm]?j|t)sx?|json)$"
"replace": {
"type": "string",
"pattern": "\\.(([cm]?j|t)sx?|json)$"
},
"with": {
"type": "string",
"pattern": "\\.(([cm]?j|t)sx?|json)$"
}
},
"additionalProperties": false,
"required": ["replace", "with"]
} }
] },
"additionalProperties": false,
"required": ["replace", "with"]
}, },
"budget": { "budget": {
"type": "object", "type": "object",