@angular/build
Version:
Official build system for Angular
91 lines (90 loc) • 4.14 kB
JavaScript
"use strict";
/**
* @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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateIndexHtml = generateIndexHtml;
const node_assert_1 = __importDefault(require("node:assert"));
const node_path_1 = __importDefault(require("node:path"));
const index_html_generator_1 = require("../../utils/index-file/index-html-generator");
const bundler_context_1 = require("./bundler-context");
/**
* The maximum number of module preload link elements that should be added for
* initial scripts.
*/
const MODULE_PRELOAD_MAX = 10;
async function generateIndexHtml(initialFiles, outputFiles, buildOptions, lang) {
// Analyze metafile for initial link-based hints.
// Skip if the internal externalPackages option is enabled since this option requires
// dev server cooperation to properly resolve and fetch imports.
const hints = [];
const { indexHtmlOptions, externalPackages, optimizationOptions, crossOrigin, subresourceIntegrity, baseHref, } = buildOptions;
(0, node_assert_1.default)(indexHtmlOptions, 'indexHtmlOptions cannot be undefined.');
if (!externalPackages && indexHtmlOptions.preloadInitial) {
const modulePreloads = [];
for (const [key, value] of initialFiles) {
if (value.entrypoint || value.serverFile) {
// Entry points are already referenced in the HTML
continue;
}
if (value.type === 'script') {
modulePreloads.push({ url: key, mode: 'modulepreload', depth: value.depth });
}
else if (value.type === 'style') {
// Provide an "as" value of "style" to ensure external URLs which may not have a
// file extension are treated as stylesheets.
hints.push({ url: key, mode: 'preload', as: 'style' });
}
}
// Limit the number of module preloads with smallest depth given priority
modulePreloads.sort((a, b) => a.depth - b.depth);
hints.push(...modulePreloads.slice(0, MODULE_PRELOAD_MAX));
}
/** Virtual output path to support reading in-memory files. */
const browserOutputFiles = outputFiles.filter(({ type }) => type === bundler_context_1.BuildOutputFileType.Browser);
const virtualOutputPath = '/';
const readAsset = async function (filePath) {
// Remove leading directory separator
const relativefilePath = node_path_1.default.relative(virtualOutputPath, filePath);
const file = browserOutputFiles.find((file) => file.path === relativefilePath);
if (file) {
return file.text;
}
throw new Error(`Output file does not exist: ${relativefilePath}`);
};
// Create an index HTML generator that reads from the in-memory output files
const indexHtmlGenerator = new index_html_generator_1.IndexHtmlGenerator({
indexPath: indexHtmlOptions.input,
entrypoints: indexHtmlOptions.insertionOrder,
sri: subresourceIntegrity,
optimization: optimizationOptions,
crossOrigin: crossOrigin,
deployUrl: buildOptions.publicPath,
postTransform: indexHtmlOptions.transformer,
generateDedicatedSSRContent: !!(buildOptions.ssrOptions ||
buildOptions.prerenderOptions ||
buildOptions.appShellOptions),
autoCsp: buildOptions.security.autoCsp,
});
indexHtmlGenerator.readAsset = readAsset;
return indexHtmlGenerator.process({
baseHref,
lang,
outputPath: virtualOutputPath,
files: [...initialFiles]
.filter(([, file]) => !file.serverFile)
.map(([file, record]) => ({
name: record.name ?? '',
file,
extension: node_path_1.default.extname(file),
})),
hints,
});
}