diff --git a/packages/cli/src/commands/build.js b/packages/cli/src/commands/build.js
index 9579c8240..4c8a211d0 100644
--- a/packages/cli/src/commands/build.js
+++ b/packages/cli/src/commands/build.js
@@ -38,13 +38,7 @@ const runProductionBuild = async (compilation) => {
});
}
- await Promise.all(
- servers.map(async (server) => {
- await server.start();
-
- return Promise.resolve(server);
- }),
- );
+ await Promise.all(servers.map((server) => server.start()));
if (prerenderPlugin.executeModuleUrl) {
await preRenderCompilationWorker(compilation, prerenderPlugin);
diff --git a/packages/cli/src/lib/async-utils.js b/packages/cli/src/lib/async-utils.js
index 9cedd3626..1c086853b 100644
--- a/packages/cli/src/lib/async-utils.js
+++ b/packages/cli/src/lib/async-utils.js
@@ -1,27 +1,33 @@
// https://stackoverflow.com/a/76974728/417806
+// Constraint: callback functions must not depend on each other
async function asyncFilter(arr, cb) {
const filtered = [];
- for (const element of arr) {
+ await asyncForEach(arr, async (element) => {
const needAdd = await cb(element);
if (needAdd) {
filtered.push(element);
}
- }
+ });
return filtered;
}
// https://stackoverflow.com/a/71278238/417806
+// Constraint: mapper functions must not depend on each other
async function asyncMap(items, mapper) {
- const mappedItems = [];
+ const promises = [];
for (const item of items) {
- mappedItems.push(await mapper(item));
+ promises.push(mapper(item));
}
- return mappedItems;
+ return await Promise.all(promises);
+}
+
+async function asyncForEach(items, callback) {
+ await asyncMap(items, callback);
}
-export { asyncFilter, asyncMap };
+export { asyncFilter, asyncMap, asyncForEach };
diff --git a/packages/cli/src/lifecycles/bundle.js b/packages/cli/src/lifecycles/bundle.js
index e72146e62..60ab9f215 100644
--- a/packages/cli/src/lifecycles/bundle.js
+++ b/packages/cli/src/lifecycles/bundle.js
@@ -16,6 +16,7 @@ import {
import path from "node:path";
import { rollup } from "rollup";
import { pruneGraph } from "../lib/content-utils.js";
+import { asyncForEach } from "../lib/async-utils.js";
async function interceptPage(url, request, plugins, body) {
let response = new Response(body, {
@@ -101,7 +102,7 @@ async function emitResources(compilation) {
async function cleanUpResources(compilation) {
const { outputDir } = compilation.context;
- for (const resource of compilation.resources.values()) {
+ await asyncForEach(compilation.resources.values(), async (resource) => {
const { src, optimizedFileName, optimizationAttr } = resource;
const optConfig = ["inline", "static"].indexOf(compilation.config.optimization) >= 0;
const optAttr = ["inline", "static"].indexOf(optimizationAttr) >= 0;
@@ -109,57 +110,53 @@ async function cleanUpResources(compilation) {
if (optimizedFileName && (!src || optAttr || optConfig)) {
await fs.unlink(new URL(`./${optimizedFileName}`, outputDir));
}
- }
+ });
}
async function optimizeStaticPages(compilation, plugins) {
const { scratchDir, outputDir } = compilation.context;
- return Promise.all(
- compilation.graph
- .filter(
- (page) =>
- !page.isSSR ||
- (page.isSSR && page.prerender) ||
- (page.isSSR && compilation.config.prerender),
- )
- .map(async (page) => {
- const { route, outputHref } = page;
- const outputDirUrl = new URL(outputHref.replace("index.html", "").replace("404.html", ""));
- const url = new URL(`http://localhost:${compilation.config.port}${route}`);
- const contents = await fs.readFile(
- new URL(`./${outputHref.replace(outputDir.href, "")}`, scratchDir),
- "utf-8",
- );
- const headers = new Headers({ "Content-Type": "text/html" });
- let response = new Response(contents, { headers });
-
- if (!(await checkResourceExists(outputDirUrl))) {
- await fs.mkdir(outputDirUrl, {
- recursive: true,
- });
- }
+ const pages = compilation.graph.filter(
+ (page) =>
+ !page.isSSR || (page.isSSR && page.prerender) || (page.isSSR && compilation.config.prerender),
+ );
- for (const plugin of plugins) {
- if (plugin.shouldOptimize && (await plugin.shouldOptimize(url, response.clone()))) {
- const currentResponse = await plugin.optimize(url, response.clone());
+ await asyncForEach(pages, async (page) => {
+ const { route, outputHref } = page;
+ const outputDirUrl = new URL(outputHref.replace("index.html", "").replace("404.html", ""));
+ const url = new URL(`http://localhost:${compilation.config.port}${route}`);
+ const contents = await fs.readFile(
+ new URL(`./${outputHref.replace(outputDir.href, "")}`, scratchDir),
+ "utf-8",
+ );
+ const headers = new Headers({ "Content-Type": "text/html" });
+ let response = new Response(contents, { headers });
+
+ if (!(await checkResourceExists(outputDirUrl))) {
+ await fs.mkdir(outputDirUrl, {
+ recursive: true,
+ });
+ }
- response = mergeResponse(response.clone(), currentResponse.clone());
- }
- }
+ for (const plugin of plugins) {
+ if (plugin.shouldOptimize && (await plugin.shouldOptimize(url, response.clone()))) {
+ const currentResponse = await plugin.optimize(url, response.clone());
- // clean up optimization markers
- const body = (await response.text()).replace(/data-gwd-opt=".*?[a-z]"/g, "");
+ response = mergeResponse(response.clone(), currentResponse.clone());
+ }
+ }
- await fs.writeFile(new URL(outputHref), body);
- }),
- );
+ // clean up optimization markers
+ const body = (await response.text()).replace(/data-gwd-opt=".*?[a-z]"/g, "");
+
+ await fs.writeFile(new URL(outputHref), body);
+ });
}
async function bundleStyleResources(compilation, resourcePlugins) {
const { outputDir } = compilation.context;
- for (const resource of compilation.resources.values()) {
+ await asyncForEach(compilation.resources.values(), async (resource) => {
const { contents, src = "", type } = resource;
if (["style", "link"].includes(type)) {
@@ -202,84 +199,58 @@ async function bundleStyleResources(compilation, resourcePlugins) {
const request = new Request(url, { headers });
const initResponse = new Response(contents, { headers });
- let response = await resourcePlugins.reduce(async (responsePromise, plugin) => {
- const intermediateResponse = await responsePromise;
+ let response = initResponse;
+
+ for (const plugin of resourcePlugins) {
const shouldServe = plugin.shouldServe && (await plugin.shouldServe(url, request));
if (shouldServe) {
const currentResponse = await plugin.serve(url, request);
- const mergedResponse = mergeResponse(
- intermediateResponse.clone(),
- currentResponse.clone(),
- );
+ const mergedResponse = mergeResponse(response.clone(), currentResponse.clone());
if (mergedResponse.headers.get("Content-Type").indexOf(contentType) >= 0) {
- return Promise.resolve(mergedResponse.clone());
+ response = mergedResponse.clone();
}
}
+ }
- return Promise.resolve(responsePromise);
- }, Promise.resolve(initResponse));
-
- response = await resourcePlugins.reduce(async (responsePromise, plugin) => {
- const intermediateResponse = await responsePromise;
+ for (const plugin of resourcePlugins) {
const shouldPreIntercept =
plugin.shouldPreIntercept &&
- (await plugin.shouldPreIntercept(url, request, intermediateResponse.clone()));
+ (await plugin.shouldPreIntercept(url, request, response.clone()));
if (shouldPreIntercept) {
- const currentResponse = await plugin.preIntercept(
- url,
- request,
- intermediateResponse.clone(),
- );
- const mergedResponse = mergeResponse(
- intermediateResponse.clone(),
- currentResponse.clone(),
- );
+ const currentResponse = await plugin.preIntercept(url, request, response.clone());
+ const mergedResponse = mergeResponse(response.clone(), currentResponse.clone());
if (mergedResponse.headers.get("Content-Type").indexOf(contentType) >= 0) {
- return Promise.resolve(mergedResponse.clone());
+ response = mergedResponse.clone();
}
}
+ }
- return Promise.resolve(responsePromise);
- }, Promise.resolve(response.clone()));
-
- response = await resourcePlugins.reduce(async (responsePromise, plugin) => {
- const intermediateResponse = await responsePromise;
+ for (const plugin of resourcePlugins) {
const shouldIntercept =
- plugin.shouldIntercept &&
- (await plugin.shouldIntercept(url, request, intermediateResponse.clone()));
+ plugin.shouldIntercept && (await plugin.shouldIntercept(url, request, response.clone()));
if (shouldIntercept) {
- const currentResponse = await plugin.intercept(
- url,
- request,
- intermediateResponse.clone(),
- );
- const mergedResponse = mergeResponse(
- intermediateResponse.clone(),
- currentResponse.clone(),
- );
+ const currentResponse = await plugin.intercept(url, request, response.clone());
+ const mergedResponse = mergeResponse(response.clone(), currentResponse.clone());
if (mergedResponse.headers.get("Content-Type").indexOf(contentType) >= 0) {
- return Promise.resolve(mergedResponse.clone());
+ response = mergedResponse.clone();
}
}
+ }
- return Promise.resolve(responsePromise);
- }, Promise.resolve(response.clone()));
-
- response = await resourcePlugins.reduce(async (responsePromise, plugin) => {
- const intermediateResponse = await responsePromise;
+ for (const plugin of resourcePlugins) {
const shouldOptimize =
- plugin.shouldOptimize && (await plugin.shouldOptimize(url, intermediateResponse.clone()));
+ plugin.shouldOptimize && (await plugin.shouldOptimize(url, response.clone()));
- return shouldOptimize
- ? Promise.resolve(await plugin.optimize(url, intermediateResponse.clone()))
- : Promise.resolve(responsePromise);
- }, Promise.resolve(response.clone()));
+ if (shouldOptimize) {
+ response = await plugin.optimize(url, response.clone());
+ }
+ }
optimizedFileContents = await response.text();
@@ -291,7 +262,7 @@ async function bundleStyleResources(compilation, resourcePlugins) {
await fs.writeFile(new URL(`./${optimizedFileName}`, outputDir), optimizedFileContents);
}
- }
+ });
}
async function bundleApiRoutes(compilation) {
@@ -300,11 +271,10 @@ async function bundleApiRoutes(compilation) {
if (apiConfigs.length > 0 && apiConfigs[0].input.length !== 0) {
console.info("bundling API routes...");
- for (const configIndex in apiConfigs) {
- const rollupConfig = apiConfigs[configIndex];
+ await asyncForEach(apiConfigs, async (rollupConfig) => {
const bundle = await rollup(rollupConfig);
await bundle.write(rollupConfig.output);
- }
+ });
}
}
@@ -326,7 +296,7 @@ async function bundleSsrPages(compilation, optimizePlugins) {
// one pass to generate initial static HTML and to track all combined static resources across layouts
// and before we optimize so that all bundled assets can tracked up front
// would be nice to see if this can be done in a single pass though...
- for (const page of ssrPages) {
+ await asyncForEach(ssrPages, async (page) => {
const { route } = page;
let staticHtml = "";
@@ -346,7 +316,7 @@ async function bundleSsrPages(compilation, optimizePlugins) {
await trackResourcesForRoute(staticHtml, compilation, route);
ssrPrerenderPagesRouteMapper[route] = staticHtml;
- }
+ });
// technically this happens in the start of bundleCompilation once
// so might be nice to detect those static assets to see if they have be "de-duped" from bundling here
@@ -354,7 +324,7 @@ async function bundleSsrPages(compilation, optimizePlugins) {
await bundleStyleResources(compilation, optimizePlugins);
// second pass to link all bundled assets to their resources before optimizing and generating SSR bundles
- for (const page of ssrPages) {
+ await asyncForEach(ssrPages, async (page) => {
const { id, route, pageHref } = page;
const pagePath = new URL(pageHref).pathname.replace(pagesDir.pathname, "./");
const entryFileUrl = new URL(pageHref);
@@ -422,17 +392,16 @@ async function bundleSsrPages(compilation, optimizePlugins) {
id,
inputPath: normalizePathnameForWindows(entryFileOutputUrl),
});
- }
+ });
const ssrConfigs = await getRollupConfigForSsrPages(compilation, input);
if (ssrConfigs.length > 0 && ssrConfigs[0].input !== "") {
console.info("bundling dynamic pages...");
- for (const configIndex in ssrConfigs) {
- const rollupConfig = ssrConfigs[configIndex];
+ await asyncForEach(ssrConfigs, async (rollupConfig) => {
const bundle = await rollup(rollupConfig);
await bundle.write(rollupConfig.output);
- }
+ });
}
}
}
diff --git a/packages/cli/src/lifecycles/compile.js b/packages/cli/src/lifecycles/compile.js
index c00426efb..fb1d0b626 100644
--- a/packages/cli/src/lifecycles/compile.js
+++ b/packages/cli/src/lifecycles/compile.js
@@ -59,7 +59,7 @@ const generateCompilation = async () => {
if (!(await checkResourceExists(new URL("./graph.json", outputDir)))) {
return Promise.reject(
- new Error("No build output detected. Make sure you have run greenwood build"),
+ new Error("No build output detected. Make sure you have run greenwood build"),
);
}
diff --git a/packages/cli/src/lifecycles/config.js b/packages/cli/src/lifecycles/config.js
index f3ab21ede..fa74e5a3f 100644
--- a/packages/cli/src/lifecycles/config.js
+++ b/packages/cli/src/lifecycles/config.js
@@ -1,6 +1,7 @@
// @ts-nocheck
import fs from "node:fs/promises";
import { checkResourceExists } from "../lib/resource-utils.js";
+import { asyncMap } from "../lib/async-utils.js";
const cwd = new URL(`file://${process.cwd()}/`);
const greenwoodPluginsDirectoryUrl = new URL("../plugins/", import.meta.url);
@@ -9,26 +10,25 @@ const PLUGINS_FLATTENED_DEPTH = 2;
// get and "tag" all plugins provided / maintained by the @greenwood/cli
// and include as the default set, with all user plugins getting appended
const greenwoodPlugins = (
- await Promise.all(
+ await asyncMap(
[
new URL("./copy/", greenwoodPluginsDirectoryUrl),
new URL("./renderer/", greenwoodPluginsDirectoryUrl),
new URL("./resource/", greenwoodPluginsDirectoryUrl),
new URL("./server/", greenwoodPluginsDirectoryUrl),
- ].map(async (pluginDirectoryUrl) => {
+ ],
+ async (pluginDirectoryUrl) => {
const files = await fs.readdir(pluginDirectoryUrl);
- return await Promise.all(
- files.map(async (file) => {
- const importUrl = new URL(`./${file}`, pluginDirectoryUrl);
- // @ts-expect-error see https://github.com/microsoft/TypeScript/issues/42866
- const pluginImport = await import(importUrl);
- const plugin = pluginImport[Object.keys(pluginImport)[0]];
+ return await asyncMap(files, async (file) => {
+ const importUrl = new URL(`./${file}`, pluginDirectoryUrl);
+ // @ts-expect-error see https://github.com/microsoft/TypeScript/issues/42866
+ const pluginImport = await import(importUrl);
+ const plugin = pluginImport[Object.keys(pluginImport)[0]];
- return Array.isArray(plugin) ? plugin : [plugin];
- }),
- );
- }),
+ return Array.isArray(plugin) ? plugin : [plugin];
+ });
+ },
)
)
.flat(PLUGINS_FLATTENED_DEPTH)
diff --git a/packages/cli/src/lifecycles/copy.js b/packages/cli/src/lifecycles/copy.js
index 83672d9c8..070adc003 100644
--- a/packages/cli/src/lifecycles/copy.js
+++ b/packages/cli/src/lifecycles/copy.js
@@ -1,17 +1,17 @@
import fs from "node:fs/promises";
import { checkResourceExists } from "../lib/resource-utils.js";
+import { asyncForEach } from "../lib/async-utils.js";
async function rreaddir(dir, allFiles = []) {
const files = (await fs.readdir(dir)).map((f) => new URL(`./${f}`, dir));
allFiles.push(...files);
- await Promise.all(
- files.map(
- async (f) =>
- (await fs.stat(f)).isDirectory() &&
- (await rreaddir(new URL(`file://${f.pathname}/`), allFiles)),
- ),
+ await asyncForEach(
+ files,
+ async (f) =>
+ (await fs.stat(f)).isDirectory() &&
+ (await rreaddir(new URL(`file://${f.pathname}/`), allFiles)),
);
return allFiles;
@@ -39,7 +39,7 @@ async function copyDirectory(fromUrl, toUrl, projectDirectory) {
});
}
- for (const fileUrl of files) {
+ await asyncForEach(files, async (fileUrl) => {
const targetUrl = new URL(
`file://${fileUrl.pathname.replace(fromUrl.pathname, toUrl.pathname)}`,
);
@@ -52,7 +52,7 @@ async function copyDirectory(fromUrl, toUrl, projectDirectory) {
} else if (!isDirectory) {
await copyFile(fileUrl, targetUrl, projectDirectory);
}
- }
+ });
}
} catch (e) {
console.error("ERROR", e);
@@ -63,10 +63,10 @@ const copyAssets = async (compilation) => {
const copyPlugins = compilation.config.plugins.filter((plugin) => plugin.type === "copy");
const { projectDirectory } = compilation.context;
- for (const plugin of copyPlugins) {
+ await asyncForEach(copyPlugins, async (plugin) => {
const locations = await plugin.provider(compilation);
- for (const location of locations) {
+ await asyncForEach(locations, async (location) => {
const { from, to } = location;
if (from.pathname.endsWith("/")) {
@@ -74,8 +74,8 @@ const copyAssets = async (compilation) => {
} else {
await copyFile(from, to, projectDirectory);
}
- }
- }
+ });
+ });
};
export { copyAssets };
diff --git a/packages/cli/src/lifecycles/prerender.js b/packages/cli/src/lifecycles/prerender.js
index 994c15b8a..e3f29b79c 100644
--- a/packages/cli/src/lifecycles/prerender.js
+++ b/packages/cli/src/lifecycles/prerender.js
@@ -6,6 +6,7 @@ import {
} from "../lib/resource-utils.js";
import os from "node:os";
import { WorkerPool } from "../lib/threadpool.js";
+import { asyncForEach } from "../lib/async-utils.js";
async function createOutputDirectory(outputDir) {
// ignore creating directory for 404 pages since they live at the root of the output directory
@@ -81,7 +82,7 @@ async function preRenderCompilationWorker(compilation, workerPrerender) {
new URL("../lib/ssr-route-worker.js", import.meta.url),
);
- for (const page of pages) {
+ await asyncForEach(pages, async (page) => {
const { route, outputHref } = page;
const scratchUrl = toScratchUrl(outputHref, context);
const url = new URL(`http://localhost:${config.port}${route}`);
@@ -143,7 +144,7 @@ async function preRenderCompilationWorker(compilation, workerPrerender) {
await fs.writeFile(scratchUrl, body);
console.info("generated page...", route);
- }
+ });
}
async function preRenderCompilationCustom(compilation, customPrerender) {
@@ -187,25 +188,23 @@ async function staticRenderCompilation(compilation) {
console.info("pages to generate", `\n ${pages.map((page) => page.route).join("\n ")}`);
- await Promise.all(
- pages.map(async (page) => {
- const { route, outputHref } = page;
- const scratchUrl = toScratchUrl(outputHref, context);
- const url = new URL(`http://localhost:${config.port}${route}`);
- const request = new Request(url);
+ await asyncForEach(pages, async (page) => {
+ const { route, outputHref } = page;
+ const scratchUrl = toScratchUrl(outputHref, context);
+ const url = new URL(`http://localhost:${config.port}${route}`);
+ const request = new Request(url);
- let body = await (await servePage(url, request, plugins)).text();
- body = await (await interceptPage(url, request, plugins, body)).text();
+ let body = await (await servePage(url, request, plugins)).text();
+ body = await (await interceptPage(url, request, plugins, body)).text();
- await trackResourcesForRoute(body, compilation, route);
- await createOutputDirectory(new URL(scratchUrl.href.replace("index.html", "")));
- await fs.writeFile(scratchUrl, body);
+ await trackResourcesForRoute(body, compilation, route);
+ await createOutputDirectory(new URL(scratchUrl.href.replace("index.html", "")));
+ await fs.writeFile(scratchUrl, body);
- console.info("generated page...", route);
+ console.info("generated page...", route);
- return Promise.resolve();
- }),
- );
+ return Promise.resolve();
+ });
}
export { preRenderCompilationWorker, preRenderCompilationCustom, staticRenderCompilation };
diff --git a/packages/cli/src/lifecycles/serve.js b/packages/cli/src/lifecycles/serve.js
index 227b51fc0..ea5a1711d 100644
--- a/packages/cli/src/lifecycles/serve.js
+++ b/packages/cli/src/lifecycles/serve.js
@@ -40,13 +40,13 @@ async function getDevServer(compilation) {
try {
const url = new URL(`http://localhost:${compilation.config.port}${ctx.url}`);
const initRequest = transformKoaRequestIntoStandardRequest(url, ctx.request);
- const request = await resourcePlugins.reduce(async (requestPromise, plugin) => {
- const intermediateRequest = await requestPromise;
- return plugin.shouldResolve &&
- (await plugin.shouldResolve(url, intermediateRequest.clone()))
- ? Promise.resolve(await plugin.resolve(url, intermediateRequest.clone()))
- : Promise.resolve(await requestPromise);
- }, Promise.resolve(initRequest));
+
+ let request = initRequest;
+ for (const plugin of resourcePlugins) {
+ if (plugin.shouldResolve && (await plugin.shouldResolve(url, request.clone()))) {
+ request = await plugin.resolve(url, request.clone());
+ }
+ }
ctx.url = request.url;
} catch (e) {
@@ -100,24 +100,18 @@ async function getDevServer(compilation) {
status,
headers: new Headers(header),
});
- const response = await resourcePlugins.reduce(async (responsePromise, plugin) => {
- const intermediateResponse = await responsePromise;
+
+ let response = initResponse;
+ for (const plugin of resourcePlugins) {
if (
plugin.shouldPreIntercept &&
- (await plugin.shouldPreIntercept(url, request, intermediateResponse.clone()))
+ (await plugin.shouldPreIntercept(url, request, response.clone()))
) {
- const current = await plugin.preIntercept(
- url,
- request,
- await intermediateResponse.clone(),
- );
- const merged = mergeResponse(intermediateResponse.clone(), current);
-
- return Promise.resolve(merged);
- } else {
- return Promise.resolve(await responsePromise);
+ const current = await plugin.preIntercept(url, request, response.clone());
+
+ response = mergeResponse(response.clone(), current.clone());
}
- }, Promise.resolve(initResponse.clone()));
+ }
ctx.body = response.body ? Readable.from(response.body) : "";
ctx.message = response.statusText;
@@ -143,20 +137,18 @@ async function getDevServer(compilation) {
status,
headers: new Headers(header),
});
- const response = await resourcePlugins.reduce(async (responsePromise, plugin) => {
- const intermediateResponse = await responsePromise;
+
+ let response = initResponse;
+ for (const plugin of resourcePlugins) {
if (
plugin.shouldIntercept &&
- (await plugin.shouldIntercept(url, request, intermediateResponse.clone()))
+ (await plugin.shouldIntercept(url, request, response.clone()))
) {
- const current = await plugin.intercept(url, request, await intermediateResponse.clone());
- const merged = mergeResponse(intermediateResponse.clone(), current);
+ const current = await plugin.intercept(url, request, response.clone());
- return Promise.resolve(merged);
- } else {
- return Promise.resolve(await responsePromise);
+ response = mergeResponse(response.clone(), current.clone());
}
- }, Promise.resolve(initResponse.clone()));
+ }
ctx.body = response.body ? Readable.from(response.body) : "";
ctx.message = response.statusText;
@@ -240,11 +232,13 @@ async function getStaticServer(compilation, composable) {
status: ctx.response.status,
headers: new Headers(ctx.response.header),
});
- const response = await resourcePlugins.reduce(async (responsePromise, plugin) => {
- return plugin.shouldServe && (await plugin.shouldServe(url, request))
- ? Promise.resolve(await plugin.serve(url, request))
- : responsePromise;
- }, Promise.resolve(initResponse));
+
+ let response = initResponse;
+ for (const plugin of resourcePlugins) {
+ if (plugin.shouldServe && (await plugin.shouldServe(url, request))) {
+ response = await plugin.serve(url, request);
+ }
+ }
if (response.ok) {
ctx.body = Readable.from(response.body);
diff --git a/packages/plugin-renderer-puppeteer/src/puppeteer-handler.js b/packages/plugin-renderer-puppeteer/src/puppeteer-handler.js
index fcc729b44..ca2fc3d8e 100644
--- a/packages/plugin-renderer-puppeteer/src/puppeteer-handler.js
+++ b/packages/plugin-renderer-puppeteer/src/puppeteer-handler.js
@@ -1,24 +1,24 @@
+import { asyncMap } from "../../cli/src/lib/async-utils.js";
+
export default async function (compilation, callback) {
const BrowserRunner = (await import("./lib/browser.js")).BrowserRunner;
const browserRunner = new BrowserRunner();
const runBrowser = async (serverUrl, pages) => {
try {
- return Promise.all(
- pages.map(async (page) => {
- const { route } = page;
- console.info("prerendering page...", route);
+ return asyncMap(pages, async (page) => {
+ const { route } = page;
+ console.info("prerendering page...", route);
- return await browserRunner.serialize(`${serverUrl}${route}`).then(async (html) => {
- console.info(`prerendering complete for page ${route}.`);
+ return await browserRunner.serialize(`${serverUrl}${route}`).then(async (html) => {
+ console.info(`prerendering complete for page ${route}.`);
- // clean this up here to avoid sending webcomponents-bundle to rollup
- html = html.replace(/