mirror of
https://github.com/svemagie/blog-eleventy-indiekit.git
synced 2026-04-02 16:44:56 +02:00
fix: use eleventyComputed for OG slug to avoid Nunjucks race condition
Eleventy 3.x renders Nunjucks templates in parallel, causing page.url
to return wrong values in {% set %} tags. This caused OG images to be
mismatched between pages (e.g., bookmark showed note's OG image).
Move ogSlug and hasOgImage computation to eleventyComputed, which runs
during the sequential data cascade phase before parallel rendering.
The computed values are then available as plain template variables.
Refs: https://github.com/11ty/eleventy/issues/3183
This commit is contained in:
33
_data/eleventyComputed.js
Normal file
33
_data/eleventyComputed.js
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Computed data resolved during the data cascade (sequential, per-page).
|
||||
*
|
||||
* Eleventy 3.x renders Nunjucks templates in parallel, which causes
|
||||
* `page.url` and `page.fileSlug` to return wrong values when read
|
||||
* via {% set %} in templates. By computing OG-related values here,
|
||||
* they are resolved before parallel rendering begins.
|
||||
*
|
||||
* See: https://github.com/11ty/eleventy/issues/3183
|
||||
*/
|
||||
|
||||
import { existsSync } from "node:fs";
|
||||
import { resolve, dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export default {
|
||||
ogSlug: (data) => {
|
||||
const url = data.page?.url;
|
||||
if (!url) return "";
|
||||
return url.replace(/\/$/, "").split("/").pop();
|
||||
},
|
||||
|
||||
hasOgImage: (data) => {
|
||||
const url = data.page?.url;
|
||||
if (!url) return false;
|
||||
const slug = url.replace(/\/$/, "").split("/").pop();
|
||||
if (!slug) return false;
|
||||
const ogPath = resolve(__dirname, "..", ".cache", "og", `${slug}.png`);
|
||||
return existsSync(ogPath);
|
||||
},
|
||||
};
|
||||
@@ -23,16 +23,15 @@
|
||||
<meta property="og:type" content="{% if page.url == '/' %}website{% else %}article{% endif %}">
|
||||
<meta property="og:description" content="{{ ogDesc }}">
|
||||
<meta name="description" content="{{ ogDesc }}">
|
||||
{% set ogFileSlug = page.url | ogSlug %}
|
||||
{% set hasGeneratedOg = ogFileSlug | hasOgImage %}
|
||||
{# ogSlug and hasOgImage are pre-computed via eleventyComputed (race-condition safe) #}
|
||||
{% if ogPhoto and ogPhoto != "" and (ogPhoto | length) > 10 %}
|
||||
<meta property="og:image" content="{% if 'http' in ogPhoto %}{{ ogPhoto }}{% else %}{{ site.url }}{% if ogPhoto[0] != '/' %}/{% endif %}{{ ogPhoto }}{% endif %}">
|
||||
{% elif image and image != "" and (image | length) > 10 %}
|
||||
<meta property="og:image" content="{% if 'http' in image %}{{ image }}{% else %}{{ site.url }}{% if image[0] != '/' %}/{% endif %}{{ image }}{% endif %}">
|
||||
{% elif contentImage and contentImage != "" and (contentImage | length) > 10 %}
|
||||
<meta property="og:image" content="{% if 'http' in contentImage %}{{ contentImage }}{% else %}{{ site.url }}{% if contentImage[0] != '/' %}/{% endif %}{{ contentImage }}{% endif %}">
|
||||
{% elif hasGeneratedOg %}
|
||||
<meta property="og:image" content="{{ site.url }}/og/{{ ogFileSlug }}.png">
|
||||
{% elif hasOgImage %}
|
||||
<meta property="og:image" content="{{ site.url }}/og/{{ ogSlug }}.png">
|
||||
{% else %}
|
||||
<meta property="og:image" content="{{ site.url }}/images/og-default.png">
|
||||
{% endif %}
|
||||
@@ -41,7 +40,7 @@
|
||||
<meta property="og:locale" content="{{ site.locale | default('en_US') }}">
|
||||
|
||||
{# Twitter Card meta tags #}
|
||||
{% set hasImage = hasGeneratedOg or (ogPhoto and ogPhoto != "" and (ogPhoto | length) > 10) or (image and image != "" and (image | length) > 10) or (contentImage and contentImage != "" and (contentImage | length) > 10) %}
|
||||
{% set hasImage = hasOgImage or (ogPhoto and ogPhoto != "" and (ogPhoto | length) > 10) or (image and image != "" and (image | length) > 10) or (contentImage and contentImage != "" and (contentImage | length) > 10) %}
|
||||
<meta name="twitter:card" content="{% if hasImage %}summary_large_image{% else %}summary{% endif %}">
|
||||
<meta name="twitter:title" content="{{ ogTitle }}">
|
||||
<meta name="twitter:description" content="{{ ogDesc }}">
|
||||
@@ -51,8 +50,8 @@
|
||||
<meta name="twitter:image" content="{% if 'http' in image %}{{ image }}{% else %}{{ site.url }}/{{ image }}{% endif %}">
|
||||
{% elif contentImage and contentImage != "" and (contentImage | length) > 10 %}
|
||||
<meta name="twitter:image" content="{% if 'http' in contentImage %}{{ contentImage }}{% else %}{{ site.url }}/{{ contentImage }}{% endif %}">
|
||||
{% elif hasGeneratedOg %}
|
||||
<meta name="twitter:image" content="{{ site.url }}/og/{{ ogFileSlug }}.png">
|
||||
{% elif hasOgImage %}
|
||||
<meta name="twitter:image" content="{{ site.url }}/og/{{ ogSlug }}.png">
|
||||
{% endif %}
|
||||
|
||||
{# Favicon #}
|
||||
|
||||
Reference in New Issue
Block a user