Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ function createCodeBundleOptions(
const {
workspaceRoot,
entryPoints,
polyfills,
optimizationOptions,
sourcemapOptions,
tsconfig,
Expand All @@ -327,7 +328,7 @@ function createCodeBundleOptions(
tailwindConfiguration,
} = options;

return {
const buildOptions: BuildOptions = {
absWorkingDir: workspaceRoot,
bundle: true,
format: 'esm',
Expand Down Expand Up @@ -391,6 +392,39 @@ function createCodeBundleOptions(
'ngJitMode': jit ? 'true' : 'false',
},
};

if (polyfills?.length) {
const namespace = 'angular:polyfills';
buildOptions.entryPoints = {
...buildOptions.entryPoints,
['polyfills']: namespace,
};

buildOptions.plugins?.unshift({
name: 'angular-polyfills',
setup(build) {
build.onResolve({ filter: /^angular:polyfills$/ }, (args) => {
if (args.kind !== 'entry-point') {
return null;
}

return {
path: 'entry',
namespace,
};
});
build.onLoad({ filter: /./, namespace }, () => {
return {
contents: polyfills.map((file) => `import '${file.replace(/\\/g, '/')}';`).join('\n'),
loader: 'js',
resolveDir: workspaceRoot,
};
});
},
});
}

return buildOptions;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { createRequire } from 'node:module';
import path from 'node:path';
import { normalizeAssetPatterns, normalizeOptimization, normalizeSourceMaps } from '../../utils';
import { normalizeCacheOptions } from '../../utils/normalize-cache';
import { normalizePolyfills } from '../../utils/normalize-polyfills';
import { generateEntryPoints } from '../../utils/package-chunk-sort';
import { getIndexInputFile, getIndexOutputFile } from '../../utils/webpack-browser-config';
import { normalizeGlobalStyles } from '../../webpack/utils/helpers';
Expand Down Expand Up @@ -46,19 +45,6 @@ export async function normalizeOptions(
const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot);

const mainEntryPoint = path.join(workspaceRoot, options.main);

// Currently esbuild do not support multiple files per entry-point
const [polyfillsEntryPoint, ...remainingPolyfills] = normalizePolyfills(
options.polyfills,
workspaceRoot,
);

if (remainingPolyfills.length) {
context.logger.warn(
`The 'polyfills' option currently does not support multiple entries by this experimental builder. The first entry will be used.`,
);
}

const tsconfig = path.join(workspaceRoot, options.tsConfig);
const outputPath = path.join(workspaceRoot, options.outputPath);
const optimizationOptions = normalizeOptimization(options.optimization);
Expand Down Expand Up @@ -133,9 +119,6 @@ export async function normalizeOptions(
const entryPoints: Record<string, string> = {
main: mainEntryPoint,
};
if (polyfillsEntryPoint) {
entryPoints['polyfills'] = polyfillsEntryPoint;
}

let indexHtmlOptions;
if (options.index) {
Expand All @@ -162,6 +145,7 @@ export async function normalizeOptions(
extractLicenses,
inlineStyleLanguage = 'css',
poll,
polyfills,
preserveSymlinks,
statsJson,
stylePreprocessorOptions,
Expand All @@ -182,6 +166,7 @@ export async function normalizeOptions(
inlineStyleLanguage,
jit: !aot,
stats: !!statsJson,
polyfills: polyfills === undefined || Array.isArray(polyfills) ? polyfills : [polyfills],
poll,
// If not explicitly set, default to the Node.js process argument
preserveSymlinks: preserveSymlinks ?? process.execArgv.includes('--preserve-symlinks'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import { buildEsbuildBrowser } from '../../index';
import { BASE_OPTIONS, BROWSER_BUILDER_INFO, describeBuilder } from '../setup';

describeBuilder(buildEsbuildBrowser, BROWSER_BUILDER_INFO, (harness) => {
describe('Option: "polyfills"', () => {
it('uses a provided TypeScript file', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
polyfills: 'src/polyfills.ts',
});

const { result } = await harness.executeOnce();

expect(result?.success).toBe(true);

harness.expectFile('dist/polyfills.js').toExist();
});

it('uses a provided JavaScript file', async () => {
await harness.writeFile('src/polyfills.js', `console.log('main');`);

harness.useTarget('build', {
...BASE_OPTIONS,
polyfills: 'src/polyfills.js',
});

const { result } = await harness.executeOnce();

expect(result?.success).toBe(true);

harness.expectFile('dist/polyfills.js').content.toContain(`console.log("main")`);
});

it('fails and shows an error when file does not exist', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
polyfills: 'src/missing.ts',
});

const { result, logs } = await harness.executeOnce({ outputLogsOnFailure: false });

expect(result?.success).toBe(false);
expect(logs).toContain(
jasmine.objectContaining({ message: jasmine.stringMatching('Could not resolve') }),
);

harness.expectFile('dist/polyfills.js').toNotExist();
});

it('resolves module specifiers in array', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
polyfills: ['zone.js', 'zone.js/testing'],
});

const { result } = await harness.executeOnce();
expect(result?.success).toBeTrue();
harness.expectFile('dist/polyfills.js').toExist();
});
});
});