From 17507fcde8b5325eed3ac10a1b835f19338da10b Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 19:30:41 +0000 Subject: [PATCH] Optimize build performance by combining JSDOM transforms Combines `img-dim` and `apply-csp` transforms into a single pass to reduce JSDOM parsing overhead. Exports processing logic from original files and orchestrates them in `_11ty/combined-transforms.js`. Ensures the combined transform runs last in the pipeline to support correct CSP hashing. --- .eleventy.js | 3 +-- _11ty/apply-csp.js | 20 ++++++++++++-------- _11ty/combined-transforms.js | 26 ++++++++++++++++++++++++++ _11ty/img-dim.js | 17 +++++++++++------ package-lock.json | 3 +++ 5 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 _11ty/combined-transforms.js diff --git a/.eleventy.js b/.eleventy.js index 5597bec..692a238 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -73,11 +73,10 @@ module.exports = function (eleventyConfig) { verbose: false, }); - eleventyConfig.addPlugin(require("./_11ty/img-dim.js")); eleventyConfig.addPlugin(require("./_11ty/json-ld.js")); eleventyConfig.addPlugin(require("./_11ty/youtube-html-transform.js")); eleventyConfig.addPlugin(require("./_11ty/optimize-html.js")); - eleventyConfig.addPlugin(require("./_11ty/apply-csp.js")); + eleventyConfig.addPlugin(require("./_11ty/combined-transforms.js")); eleventyConfig.setDataDeepMerge(true); eleventyConfig.addLayoutAlias("post", "layouts/post.njk"); eleventyConfig.addNunjucksAsyncFilter( diff --git a/_11ty/apply-csp.js b/_11ty/apply-csp.js index 5759f96..23b6812 100644 --- a/_11ty/apply-csp.js +++ b/_11ty/apply-csp.js @@ -45,13 +45,9 @@ function quote(str) { return `'${str}'`; } -const addCspHash = async (rawContent, outputPath) => { - let content = rawContent; - - if (outputPath && outputPath.endsWith(".html")) { - const dom = new JSDOM(content); +const processCsp = (document) => { const cspAble = [ - ...dom.window.document.querySelectorAll("script[csp-hash]"), + ...document.querySelectorAll("script[csp-hash]"), ]; const hashes = cspAble.map((element) => { @@ -63,17 +59,24 @@ const addCspHash = async (rawContent, outputPath) => { hashes.push.apply(hashes, AUTO_RELOAD_SCRIPTS); } - const csp = dom.window.document.querySelector( + const csp = document.querySelector( "meta[http-equiv='Content-Security-Policy']" ); if (!csp) { - return content; + return; } csp.setAttribute( "content", csp.getAttribute("content").replace("HASHES", hashes.join(" ")) ); +} +const addCspHash = async (rawContent, outputPath) => { + let content = rawContent; + + if (outputPath && outputPath.endsWith(".html")) { + const dom = new JSDOM(content); + processCsp(dom.window.document); content = dom.serialize(); } @@ -102,6 +105,7 @@ module.exports = { configFunction: async (eleventyConfig, pluginOptions = {}) => { eleventyConfig.addTransform("csp", addCspHash); }, + processCsp, // Exporting for reuse }; function isDevelopmentMode() { diff --git a/_11ty/combined-transforms.js b/_11ty/combined-transforms.js new file mode 100644 index 0000000..e2f7ad5 --- /dev/null +++ b/_11ty/combined-transforms.js @@ -0,0 +1,26 @@ +const { JSDOM } = require("jsdom"); +const { processImages } = require("./img-dim"); +const { processCsp } = require("./apply-csp"); + +const combinedTransform = async (rawContent, outputPath) => { + let content = rawContent; + + if (outputPath && outputPath.endsWith(".html")) { + const dom = new JSDOM(content); + const doc = dom.window.document; + + await processImages(doc, outputPath); + processCsp(doc, outputPath); + + content = dom.serialize(); + } + + return content; +}; + +module.exports = { + initArguments: {}, + configFunction: async (eleventyConfig, pluginOptions = {}) => { + eleventyConfig.addTransform("combined", combinedTransform); + }, +}; diff --git a/_11ty/img-dim.js b/_11ty/img-dim.js index 7013669..5a01f06 100644 --- a/_11ty/img-dim.js +++ b/_11ty/img-dim.js @@ -145,17 +145,21 @@ async function setSrcset(img, src, format) { return setInfo.fallback; } +const processImages = async (document, outputPath) => { + const images = [...document.querySelectorAll("img,amp-img")]; + + if (images.length > 0) { + await Promise.all(images.map((i) => processImage(i, outputPath))); + } +}; + const dimImages = async (rawContent, outputPath) => { let content = rawContent; if (outputPath && outputPath.endsWith(".html")) { const dom = new JSDOM(content); - const images = [...dom.window.document.querySelectorAll("img,amp-img")]; - - if (images.length > 0) { - await Promise.all(images.map((i) => processImage(i, outputPath))); - content = dom.serialize(); - } + await processImages(dom.window.document, outputPath); + content = dom.serialize(); } return content; @@ -166,4 +170,5 @@ module.exports = { configFunction: async (eleventyConfig, pluginOptions = {}) => { eleventyConfig.addTransform("imgDim", dimImages); }, + processImages, // Exporting for reuse }; diff --git a/package-lock.json b/package-lock.json index 5b4c1da..ef148fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,6 +66,7 @@ "integrity": "sha512-03ER4zukR6BgwppI5DHRE11lc+8B0fWsBrqacVWo3o49QkdEFXnEWjhyI9qd9LrPlgQHK2/MYyxuOvNwecyCLQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@11ty/dependency-tree": "^2.0.1", "@11ty/eleventy-utils": "^1.0.1", @@ -5468,6 +5469,7 @@ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.13.tgz", "integrity": "sha512-FCE5xLH+hjbzRdpbRb1IMCvPv9yZx2QnDarBEYSN0N0HYk+TcXsEhwdFcFb+SRWOKzKGErhIEbBK2ogyLdTtfQ==", "license": "MIT", + "peer": true, "dependencies": { "colorette": "^1.2.2", "nanoid": "^3.1.22", @@ -6554,6 +6556,7 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", "license": "MIT", + "peer": true, "bin": { "rollup": "dist/bin/rollup" },