Skip to content

Commit

Permalink
perf(@angular-devkit/build-angular): reduce babel transformation in e…
Browse files Browse the repository at this point in the history
…sbuild builder

When using the experimental esbuild-based browser application builder, babel transformation
is now only performed on a file if the file requires the specific transformations enabled
for the build. This has the benefit of removing the need to parse and process files that
will not be affected by the enabled transformations.
From initial testing, this provides a 30% build time improvement for development builds of a
newly generated application and a 10% improvement for production builds.

(cherry picked from commit 3e3dc69)
  • Loading branch information
clydin authored and dgp1130 committed Aug 4, 2022
1 parent 38b71bc commit e6c45c3
Showing 1 changed file with 36 additions and 11 deletions.
Expand Up @@ -323,11 +323,23 @@ export function createCompilerPlugin(
};
}

const data = typescriptResult.content ?? '';
const forceAsyncTransformation = /for\s+await\s*\(|async\s+function\s*\*/.test(data);
const useInputSourcemap =
pluginOptions.sourcemap &&
(!!pluginOptions.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(args.path));

const data = typescriptResult.content ?? '';
// If no additional transformations are needed, return the TypeScript output directly
if (!forceAsyncTransformation && !pluginOptions.advancedOptimizations) {
return {
// Strip sourcemaps if they should not be used
contents: useInputSourcemap
? data
: data.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, ''),
loader: 'js',
};
}

const babelResult = await transformAsync(data, {
filename: args.path,
inputSourceMap: (useInputSourcemap ? undefined : false) as undefined,
Expand All @@ -341,7 +353,7 @@ export function createCompilerPlugin(
[
angularApplicationPreset,
{
forceAsyncTransformation: /for\s+await\s*\(|async\s+function\s*\*/.test(data),
forceAsyncTransformation,
optimize: pluginOptions.advancedOptimizations && {},
},
],
Expand All @@ -356,6 +368,26 @@ export function createCompilerPlugin(
);

build.onLoad({ filter: /\.[cm]?js$/ }, async (args) => {
const data = await fs.readFile(args.path, 'utf-8');
const forceAsyncTransformation =
!/[\\/][_f]?esm2015[\\/]/.test(args.path) &&
/for\s+await\s*\(|async\s+function\s*\*/.test(data);
const shouldLink = await requiresLinking(args.path, data);
const useInputSourcemap =
pluginOptions.sourcemap &&
(!!pluginOptions.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(args.path));

// If no additional transformations are needed, return the TypeScript output directly
if (!forceAsyncTransformation && !pluginOptions.advancedOptimizations && !shouldLink) {
return {
// Strip sourcemaps if they should not be used
contents: useInputSourcemap
? data
: data.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, ''),
loader: 'js',
};
}

const angularPackage = /[\\/]node_modules[\\/]@angular[\\/]/.test(args.path);

const linkerPluginCreator = (
Expand All @@ -364,11 +396,6 @@ export function createCompilerPlugin(
)
).createEs2015LinkerPlugin;

const useInputSourcemap =
pluginOptions.sourcemap &&
(!!pluginOptions.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(args.path));

const data = await fs.readFile(args.path, 'utf-8');
const result = await transformAsync(data, {
filename: args.path,
inputSourceMap: (useInputSourcemap ? undefined : false) as undefined,
Expand All @@ -383,13 +410,11 @@ export function createCompilerPlugin(
angularApplicationPreset,
{
angularLinker: {
shouldLink: await requiresLinking(args.path, data),
shouldLink,
jitMode: false,
linkerPluginCreator,
},
forceAsyncTransformation:
!/[\\/][_f]?esm2015[\\/]/.test(args.path) &&
/for\s+await\s*\(|async\s+function\s*\*/.test(data),
forceAsyncTransformation,
optimize: pluginOptions.advancedOptimizations && {
looseEnums: angularPackage,
pureTopLevel: angularPackage,
Expand Down

0 comments on commit e6c45c3

Please sign in to comment.