@angular-devkit/build-angular
Version:
Angular Webpack Build Facade
202 lines • 9.89 kB
JavaScript
;
/**
* @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.dev/license
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const babel_loader_1 = require("babel-loader");
const package_version_1 = require("../../utils/package-version");
const application_1 = require("./presets/application");
/**
* Cached instance of the compiler-cli linker's Babel plugin factory function.
*/
let linkerPluginCreator;
/**
* Cached instance of the localize Babel plugins factory functions.
*/
let i18nPluginCreators;
// eslint-disable-next-line max-lines-per-function
exports.default = (0, babel_loader_1.custom)(() => {
const baseOptions = Object.freeze({
babelrc: false,
configFile: false,
compact: false,
cacheCompression: false,
sourceType: 'unambiguous',
inputSourceMap: false,
});
return {
async customOptions(options, { source, map }) {
const { i18n, aot, optimize, instrumentCode, supportedBrowsers, ...rawOptions } = options;
// Must process file if plugins are added
let shouldProcess = Array.isArray(rawOptions.plugins) && rawOptions.plugins.length > 0;
const customOptions = {
forceAsyncTransformation: false,
angularLinker: undefined,
i18n: undefined,
instrumentCode: undefined,
supportedBrowsers,
};
// Analyze file for linking
if (await (0, application_1.requiresLinking)(this.resourcePath, source)) {
// Load ESM `@angular/compiler-cli/linker/babel` using the TypeScript dynamic import workaround.
// Once TypeScript provides support for keeping the dynamic import this workaround can be
// changed to a direct dynamic import.
linkerPluginCreator ??= (await Promise.resolve().then(() => __importStar(require('@angular/compiler-cli/linker/babel'))))
.createEs2015LinkerPlugin;
customOptions.angularLinker = {
shouldLink: true,
jitMode: aot !== true,
linkerPluginCreator,
};
shouldProcess = true;
}
// Application code (TS files) will only contain native async if target is ES2017+.
// However, third-party libraries can regardless of the target option.
// APF packages with code in [f]esm2015 directories is downlevelled to ES2015 and
// will not have native async.
customOptions.forceAsyncTransformation =
!/[\\/][_f]?esm2015[\\/]/.test(this.resourcePath) && source.includes('async');
shouldProcess ||=
customOptions.forceAsyncTransformation ||
customOptions.supportedBrowsers !== undefined ||
false;
// Analyze for i18n inlining
if (i18n &&
!/[\\/]@angular[\\/](?:compiler|localize)/.test(this.resourcePath) &&
source.includes('$localize')) {
// Load the i18n plugin creators from the new `@angular/localize/tools` entry point.
// This may fail during the transition to ESM due to the entry point not yet existing.
// During the transition, this will always attempt to load the entry point for each file.
// This will only occur during prerelease and will be automatically corrected once the new
// entry point exists.
if (i18nPluginCreators === undefined) {
// Load ESM `@angular/localize/tools` using the TypeScript dynamic import workaround.
// Once TypeScript provides support for keeping the dynamic import this workaround can be
// changed to a direct dynamic import.
i18nPluginCreators = await Promise.resolve().then(() => __importStar(require('@angular/localize/tools')));
}
customOptions.i18n = {
...i18n,
pluginCreators: i18nPluginCreators,
};
// Add translation files as dependencies of the file to support rebuilds
// Except for `@angular/core` which needs locale injection but has no translations
if (customOptions.i18n.translationFiles &&
!/[\\/]@angular[\\/]core/.test(this.resourcePath)) {
for (const file of customOptions.i18n.translationFiles) {
this.addDependency(file);
}
}
shouldProcess = true;
}
if (optimize) {
const AngularPackage = /[\\/]node_modules[\\/]@angular[\\/]/.test(this.resourcePath);
const sideEffectFree = !!this._module?.factoryMeta?.sideEffectFree;
customOptions.optimize = {
// Angular packages provide additional tested side effects guarantees and can use
// otherwise unsafe optimizations. (@angular/platform-server/init) however has side-effects.
topLevelSafeMode: !(AngularPackage && sideEffectFree),
// JavaScript modules that are marked as side effect free are considered to have
// no decorators that contain non-local effects.
wrapDecorators: sideEffectFree,
};
shouldProcess = true;
}
if (instrumentCode &&
!instrumentCode.excludedPaths.has(this.resourcePath) &&
!/\.(e2e|spec)\.tsx?$|[\\/]node_modules[\\/]/.test(this.resourcePath) &&
this.resourcePath.startsWith(instrumentCode.includedBasePath)) {
// `babel-plugin-istanbul` has it's own includes but we do the below so that we avoid running the loader.
customOptions.instrumentCode = {
includedBasePath: instrumentCode.includedBasePath,
inputSourceMap: map,
};
shouldProcess = true;
}
// Add provided loader options to default base options
const loaderOptions = {
...baseOptions,
...rawOptions,
cacheIdentifier: JSON.stringify({
buildAngular: package_version_1.VERSION,
customOptions,
baseOptions,
rawOptions,
}),
};
// Skip babel processing if no actions are needed
if (!shouldProcess) {
// Force the current file to be ignored
loaderOptions.ignore = [() => true];
}
return { custom: customOptions, loader: loaderOptions };
},
config(configuration, { customOptions }) {
return {
...configuration.options,
// Using `false` disables babel from attempting to locate sourcemaps or process any inline maps.
// The babel types do not include the false option even though it is valid
// eslint-disable-next-line @typescript-eslint/no-explicit-any
inputSourceMap: configuration.options.inputSourceMap ?? false,
presets: [
...(configuration.options.presets || []),
[
require('./presets/application').default,
{
...customOptions,
diagnosticReporter: (type, message) => {
switch (type) {
case 'error':
this.emitError(message);
break;
case 'info': // Webpack does not currently have an informational diagnostic
case 'warning':
this.emitWarning(message);
break;
}
},
},
],
],
};
},
};
});
//# sourceMappingURL=webpack-loader.js.map