mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
119 lines
4.3 KiB
JavaScript
119 lines
4.3 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright Google LLC
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.dev/license
|
|
*/
|
|
|
|
import fs from 'fs';
|
|
import babel from '@babel/core';
|
|
|
|
import {assertNoPartialDeclaration} from './ensure-no-linker-decl.mjs';
|
|
|
|
/**
|
|
* Creates an ESBuild plugin that configures various Angular optimization Babel plugins.
|
|
* The Babel plugins configured usually run in the Angular CLI compilation pipeline.
|
|
*
|
|
* @param {import('./esbuild-plugin').OptimizationOptions} opts Options
|
|
* @param additionalBabelPlugins List of additional Babel plugins that should run as part
|
|
* of this ESBuild plugin. This is primarily supported for reducing the amount of ESBuild
|
|
* load plugins needed (as they can impact performance significantly).
|
|
*/
|
|
export async function createEsbuildAngularOptimizePlugin(opts, additionalBabelPlugins = []) {
|
|
let linkerCreator = {
|
|
compiler: null,
|
|
babel: null,
|
|
};
|
|
let downlevelAsyncGeneratorPlugin = null;
|
|
|
|
if (opts.enableLinker) {
|
|
linkerCreator = {
|
|
compiler: await import('@angular/compiler-cli'),
|
|
babel: await import('@angular/compiler-cli/linker/babel'),
|
|
};
|
|
}
|
|
|
|
if (opts.downlevelAsyncGeneratorsIfPresent) {
|
|
downlevelAsyncGeneratorPlugin = (
|
|
await import('@babel/plugin-transform-async-generator-functions')
|
|
).default.default;
|
|
}
|
|
|
|
const {adjustStaticMembers, adjustTypeScriptEnums, elideAngularMetadata, markTopLevelPure} = (
|
|
await import('@angular/build/private')
|
|
).default;
|
|
|
|
return {
|
|
name: 'ng-babel-optimize-esbuild',
|
|
setup: (build) => {
|
|
build.onLoad({filter: /\.[cm]?js$/}, async (args) => {
|
|
const filePath = args.path;
|
|
const content = await fs.promises.readFile(filePath, 'utf8');
|
|
const plugins = [...additionalBabelPlugins];
|
|
|
|
if (opts.optimize) {
|
|
plugins.push(adjustStaticMembers, adjustTypeScriptEnums, elideAngularMetadata);
|
|
|
|
// If the current file is denoted as explicit side effect free, add the pure
|
|
// top-level functions optimization plugin for this file.
|
|
if (opts.optimize.isSideEffectFree && opts.optimize.isSideEffectFree(args.path)) {
|
|
plugins.push(markTopLevelPure);
|
|
}
|
|
}
|
|
|
|
const shouldRunLinker =
|
|
opts.enableLinker &&
|
|
(opts.enableLinker.filterPaths == null || opts.enableLinker.filterPaths.test(args.path));
|
|
|
|
if (shouldRunLinker) {
|
|
plugins.push(
|
|
linkerCreator.babel.createEs2015LinkerPlugin({
|
|
...(opts.enableLinker.linkerOptions ?? {}),
|
|
fileSystem: new linkerCreator.compiler.NodeJSFileSystem(),
|
|
logger: new linkerCreator.compiler.ConsoleLogger(
|
|
linkerCreator.compiler.LogLevel.warn,
|
|
),
|
|
// Workaround for https://github.com/angular/angular/issues/42769 and https://github.com/angular/angular-cli/issues/22647.
|
|
sourceMapping: false,
|
|
}),
|
|
);
|
|
}
|
|
|
|
// Matches Angular CLIs detection:
|
|
// https://github.com/angular/angular-cli/blob/afe9feaa45913cbebe7f22c678d693d96f38584a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/javascript-transformer.ts#L74-L76
|
|
if (
|
|
opts.downlevelAsyncGeneratorsIfPresent &&
|
|
content.includes('async') &&
|
|
/async(\s+function)?\s*\*/.test(content)
|
|
) {
|
|
plugins.push(downlevelAsyncGeneratorPlugin);
|
|
}
|
|
|
|
// If no plugins are enabled, return the original code and save time.
|
|
if (plugins.length === 0) {
|
|
return {contents: content};
|
|
}
|
|
|
|
const ensureNoPartialDeclaration =
|
|
opts.enableLinker && opts.enableLinker.ensureNoPartialDeclaration;
|
|
const {code, ast} = await babel.transformAsync(content, {
|
|
filename: filePath,
|
|
filenameRelative: filePath,
|
|
plugins: plugins,
|
|
// Sourcemaps are generated inline so that ESBuild can process them.
|
|
sourceMaps: 'inline',
|
|
compact: false,
|
|
// AST is needed when we want to ensure no partial declarations later.
|
|
ast: ensureNoPartialDeclaration,
|
|
});
|
|
|
|
if (ensureNoPartialDeclaration) {
|
|
assertNoPartialDeclaration(filePath, ast, babel.traverse);
|
|
}
|
|
|
|
return {contents: code};
|
|
});
|
|
},
|
|
};
|
|
}
|