diff --git a/build-scripts/social-previews/base.ts b/build-scripts/social-previews/base.ts index 228396c5..3eff4312 100644 --- a/build-scripts/social-previews/base.ts +++ b/build-scripts/social-previews/base.ts @@ -14,3 +14,6 @@ export type Layout = { css: string; Component: React.FunctionComponent; }; + +export const PAGE_WIDTH = 1280; +export const PAGE_HEIGHT = 640; diff --git a/build-scripts/social-previews/index.ts b/build-scripts/social-previews/index.ts index fe72c3e0..93f413a0 100644 --- a/build-scripts/social-previews/index.ts +++ b/build-scripts/social-previews/index.ts @@ -2,17 +2,10 @@ import chromium from "chrome-aws-lambda"; import puppeteer from "puppeteer-core"; import { promises as fsPromises } from "fs"; import { resolve } from "path"; -import { getAllPosts } from "utils/get-all-posts"; +import { getPosts } from "utils/get-all-posts"; import { PostInfo } from "types/index"; -import { - layouts, - heightWidth, - renderPostPreviewToString, -} from "./shared-post-preview-png"; -import { Layout } from "./base"; - -let browser: puppeteer.Browser; -let page: puppeteer.Page; +import { layouts, renderPostPreviewToString } from "./shared-post-preview-png"; +import { Layout, PAGE_HEIGHT, PAGE_WIDTH } from "./base"; const browser_args = [ "--autoplay-policy=user-gesture-required", @@ -53,27 +46,33 @@ const browser_args = [ "--disable-web-security", ]; -const createPostSocialPreviewPng = async (layout: Layout, post: PostInfo) => { - if (!browser) { - browser = await chromium.puppeteer.launch({ - args: [...chromium.args, ...browser_args], - defaultViewport: chromium.defaultViewport, - executablePath: await chromium.executablePath, - headless: true, - ignoreHTTPSErrors: true, - userDataDir: "./.puppeteer", - }); - page = await browser.newPage(); - await page.setViewport(heightWidth); - } +const browser: Promise = chromium.puppeteer.launch({ + args: [...chromium.args, ...browser_args], + defaultViewport: { + width: PAGE_WIDTH, + height: PAGE_HEIGHT, + }, + executablePath: await chromium.executablePath, + headless: true, + ignoreHTTPSErrors: true, + userDataDir: "./.puppeteer", +}); - await page.setContent(await renderPostPreviewToString(layout, post)); - return (await page.screenshot({ type: "jpeg" })) as Buffer; -}; +const page: Promise = browser.then((b) => b.newPage()); + +async function renderPostImage(layout: Layout, post: PostInfo) { + const label = `${post.slug} (${layout.name})`; + console.time(label); + + const browserPage = await page; + await browserPage.setContent(await renderPostPreviewToString(layout, post)); + const buffer = (await browserPage.screenshot({ type: "jpeg" })) as Buffer; + + console.timeEnd(label); + return buffer; +} const build = async () => { - const posts = getAllPosts("en"); - // Relative to root const outDir = resolve(process.cwd(), "./public/generated"); await fsPromises.mkdir(outDir, { recursive: true }); @@ -82,19 +81,17 @@ const build = async () => { * This is done synchronously, in order to prevent more than a single instance * of the browser from running at the same time. */ - for (const post of posts) { + for (const post of getPosts("en")) { for (const layout of layouts) { - const png = await createPostSocialPreviewPng(layout, post); - + const buffer = await renderPostImage(layout, post); await fsPromises.writeFile( resolve(outDir, `${post.slug}.${layout.name}.jpg`), - png + buffer ); } - console.log(post.slug); } - await browser.close(); + await (await browser).close(); }; // For non-prod builds, this isn't needed diff --git a/build-scripts/social-previews/layouts/twitter-preview.css.ts b/build-scripts/social-previews/layouts/twitter-preview.css.ts index 5a5cd279..d11876fd 100644 --- a/build-scripts/social-previews/layouts/twitter-preview.css.ts +++ b/build-scripts/social-previews/layouts/twitter-preview.css.ts @@ -3,7 +3,7 @@ export default ` * { font-family: "Work Sans"; - color: var(--white); + color: #FFF; } .codeScreenOverlay, .codeScreenBg { diff --git a/build-scripts/social-previews/shared-post-preview-png.ts b/build-scripts/social-previews/shared-post-preview-png.ts index 543032de..a4c9e2ab 100644 --- a/build-scripts/social-previews/shared-post-preview-png.ts +++ b/build-scripts/social-previews/shared-post-preview-png.ts @@ -3,7 +3,6 @@ import { PostInfo } from "types/index"; import * as fs from "fs"; import { render } from "preact-render-to-string"; import { createElement } from "preact"; -import { COLORS } from "constants/theme"; import { unified } from "unified"; import remarkParse from "remark-parse"; @@ -14,7 +13,7 @@ import rehypeStringify from "rehype-stringify"; import banner from "./layouts/banner"; import twitterPreview from "./layouts/twitter-preview"; -import { Layout } from "./base"; +import { Layout, PAGE_HEIGHT, PAGE_WIDTH } from "./base"; export const layouts: Layout[] = [banner, twitterPreview]; @@ -63,17 +62,6 @@ async function markdownToHtml(content: string) { return await (await unifiedChain().process(content)).toString(); } -const colorsCSS = (Object.keys(COLORS) as Array).reduce( - (stylesheetStr, colorKey, i, arr) => { - let str = stylesheetStr + `\n--${colorKey}: ${COLORS[colorKey].light};`; - if (i === arr.length - 1) str += "\n}"; - return str; - }, - ":root {\n" -); - -export const heightWidth = { width: 1280, height: 640 }; - const shikiSCSS = fs.readFileSync("src/styles/shiki.scss", "utf8"); export const renderPostPreviewToString = async ( @@ -95,19 +83,14 @@ export const renderPostPreviewToString = async ( - - -