123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.postProcessHTML = void 0;
- var _constants = require("../shared/lib/constants");
- var _nonNullable = require("../lib/non-nullable");
- let optimizeAmp;
- let getFontDefinitionFromManifest;
- let parse;
- if (process.env.NEXT_RUNTIME !== "edge") {
- optimizeAmp = require("./optimize-amp").default;
- getFontDefinitionFromManifest = require("./font-utils").getFontDefinitionFromManifest;
- parse = require("next/dist/compiled/node-html-parser").parse;
- }
- const middlewareRegistry = [];
- function registerPostProcessor(name, middleware, condition) {
- middlewareRegistry.push({
- name,
- middleware,
- condition: condition || null
- });
- }
- async function processHTML(html, data, options) {
- // Don't parse unless there's at least one processor middleware
- if (!middlewareRegistry[0]) {
- return html;
- }
- const root = parse(html);
- let document = html;
- // Calls the middleware, with some instrumentation and logging
- async function callMiddleWare(middleware) {
- // let timer = Date.now()
- const inspectData = middleware.inspect(root, data);
- document = await middleware.mutate(document, inspectData, data);
- // timer = Date.now() - timer
- // if (timer > MIDDLEWARE_TIME_BUDGET) {
- // TODO: Identify a correct upper limit for the postprocess step
- // and add a warning to disable the optimization
- // }
- return;
- }
- for(let i = 0; i < middlewareRegistry.length; i++){
- let middleware = middlewareRegistry[i];
- if (!middleware.condition || middleware.condition(options)) {
- await callMiddleWare(middlewareRegistry[i].middleware);
- }
- }
- return document;
- }
- class FontOptimizerMiddleware {
- inspect(originalDom, options) {
- if (!options.getFontDefinition) {
- return;
- }
- const fontDefinitions = [];
- // collecting all the requested font definitions
- originalDom.querySelectorAll("link").filter((tag)=>tag.getAttribute("rel") === "stylesheet" && tag.hasAttribute("data-href") && _constants.OPTIMIZED_FONT_PROVIDERS.some(({ url })=>{
- const dataHref = tag.getAttribute("data-href");
- return dataHref ? dataHref.startsWith(url) : false;
- })).forEach((element)=>{
- const url = element.getAttribute("data-href");
- const nonce = element.getAttribute("nonce");
- if (url) {
- fontDefinitions.push([
- url,
- nonce
- ]);
- }
- });
- return fontDefinitions;
- }
- mutate = async (markup, fontDefinitions, options)=>{
- let result = markup;
- let preconnectUrls = new Set();
- if (!options.getFontDefinition) {
- return markup;
- }
- fontDefinitions.forEach((fontDef)=>{
- const [url, nonce] = fontDef;
- const fallBackLinkTag = `<link rel="stylesheet" href="${url}"/>`;
- if (result.indexOf(`<style data-href="${url}">`) > -1 || result.indexOf(fallBackLinkTag) > -1) {
- // The font is already optimized and probably the response is cached
- return;
- }
- const fontContent = options.getFontDefinition ? options.getFontDefinition(url) : null;
- if (!fontContent) {
- /**
- * In case of unreachable font definitions, fallback to default link tag.
- */ result = result.replace("</head>", `${fallBackLinkTag}</head>`);
- } else {
- const nonceStr = nonce ? ` nonce="${nonce}"` : "";
- result = result.replace("</head>", `<style data-href="${url}"${nonceStr}>${fontContent}</style></head>`);
- // Remove inert font tag
- const escapedUrl = url.replace(/&/g, "&").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
- const fontRegex = new RegExp(`<link[^>]*data-href="${escapedUrl}"[^>]*/>`);
- result = result.replace(fontRegex, "");
- const provider = _constants.OPTIMIZED_FONT_PROVIDERS.find((p)=>url.startsWith(p.url));
- if (provider) {
- preconnectUrls.add(provider.preconnect);
- }
- }
- });
- let preconnectTag = "";
- preconnectUrls.forEach((url)=>{
- preconnectTag += `<link rel="preconnect" href="${url}" crossorigin />`;
- });
- result = result.replace('<meta name="next-font-preconnect"/>', preconnectTag);
- return result;
- };
- }
- async function postProcessHTML(pathname, content, renderOpts, { inAmpMode , hybridAmp }) {
- const postProcessors = [
- process.env.NEXT_RUNTIME !== "edge" && inAmpMode ? async (html)=>{
- html = await optimizeAmp(html, renderOpts.ampOptimizerConfig);
- if (!renderOpts.ampSkipValidation && renderOpts.ampValidator) {
- await renderOpts.ampValidator(html, pathname);
- }
- return html;
- } : null,
- process.env.NEXT_RUNTIME !== "edge" && renderOpts.optimizeFonts ? async (html)=>{
- const getFontDefinition = (url)=>{
- if (renderOpts.fontManifest) {
- return getFontDefinitionFromManifest(url, renderOpts.fontManifest);
- }
- return "";
- };
- return await processHTML(html, {
- getFontDefinition
- }, {
- optimizeFonts: renderOpts.optimizeFonts
- });
- } : null,
- process.env.NEXT_RUNTIME !== "edge" && renderOpts.optimizeCss ? async (html)=>{
- // eslint-disable-next-line import/no-extraneous-dependencies
- const Critters = require("critters");
- const cssOptimizer = new Critters({
- ssrMode: true,
- reduceInlineStyles: false,
- path: renderOpts.distDir,
- publicPath: `${renderOpts.assetPrefix}/_next/`,
- preload: "media",
- fonts: false,
- ...renderOpts.optimizeCss
- });
- return await cssOptimizer.process(html);
- } : null,
- inAmpMode || hybridAmp ? async (html)=>{
- return html.replace(/&amp=1/g, "&=1");
- } : null,
- ].filter(_nonNullable.nonNullable);
- for (const postProcessor of postProcessors){
- if (postProcessor) {
- content = await postProcessor(content);
- }
- }
- return content;
- }
- // Initialization
- registerPostProcessor("Inline-Fonts", new FontOptimizerMiddleware(), // Using process.env because passing Experimental flag through loader is not possible.
- // @ts-ignore
- (options)=>options.optimizeFonts || process.env.__NEXT_OPTIMIZE_FONTS);
- exports.postProcessHTML = postProcessHTML;
- //# sourceMappingURL=post-process.js.map
|