From dcb58bbb3af480d180b1d3c809809d9f51aa8966 Mon Sep 17 00:00:00 2001 From: Philip Peterson Date: Mon, 2 Nov 2026 06:08:05 -0900 Subject: [PATCH] Serve Preact from the site: the components rendered nothing Every component imported Preact, its hooks and htm/preact from esm.sh separately. htm/preact imports Preact unversioned, which esm.sh now resolves to Preact 11, while the components asked for preact@10: two Preacts on one page, so render() drew nothing, silently. Booking, FAQ, testimonials, carousel, toggle and appointment type were all blank. Use htm's single-file standalone build instead (Preact 10, its hooks and html in one module, no further imports), downloaded at image build pinned by version and checksum, like FullCalendar, and imported from ../vendor/preact-standalone.js. Checked on the live page: the booking component renders again with it. Co-Authored-By: Claude Opus 5.5 --- .gitignore | 3 +++ Dockerfile | 13 ++++++++++++- .../riverside_pt/js/components/rpt-appt-type.js | 4 +--- .../riverside_pt/js/components/rpt-booking.js | 4 +--- .../riverside_pt/js/components/rpt-carousel.js | 4 +--- .../custom/riverside_pt/js/components/rpt-faq.js | 4 +--- .../riverside_pt/js/components/rpt-testimonials.js | 4 +--- .../custom/riverside_pt/js/components/rpt-toggle.js | 4 +--- 8 files changed, 21 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 6da9605..b20d04d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ web/sites/default/files/* .env node_modules/ + +# Downloaded at image build (Dockerfile) +web/modules/custom/riverside_pt/js/vendor/ diff --git a/Dockerfile b/Dockerfile index 7ef7702..7636c9d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -113,10 +113,21 @@ COPY --from=node-build /build/web/modules/custom/riverside_pt/css/app.css \ web/modules/custom/riverside_pt/css/app.css COPY config/sync/ config/sync/ -# Download FullCalendar and lock settings.php in one layer +# Download FullCalendar and Preact, and lock settings.php in one layer. +# Preact (with its hooks and htm's html``) is htm's single-file standalone +# build, served from the site: the components used to import Preact, its +# hooks and htm/preact from esm.sh separately, and when htm/preact started +# resolving to Preact 11 while the rest stayed on 10, every component +# rendered nothing. Pinned by version and checksum. ARG FULLCALENDAR_VERSION=6.1.15 +ARG HTM_VERSION=3.1.1 +ARG HTM_PREACT_STANDALONE_SHA256=72284e8e9079c87817145df1110f74e8a2aa040b2fc384922e18dfcb46fc1fd7 RUN curl -fsSL "https://cdn.jsdelivr.net/npm/fullcalendar@${FULLCALENDAR_VERSION}/index.global.min.js" \ -o web/modules/custom/riverside_pt/js/fullcalendar.min.js \ + && mkdir -p web/modules/custom/riverside_pt/js/vendor \ + && curl -fsSL "https://cdn.jsdelivr.net/npm/htm@${HTM_VERSION}/preact/standalone.module.js" \ + -o web/modules/custom/riverside_pt/js/vendor/preact-standalone.js \ + && echo "${HTM_PREACT_STANDALONE_SHA256} web/modules/custom/riverside_pt/js/vendor/preact-standalone.js" | sha256sum -c - \ && chmod 444 web/sites/default/settings.php EXPOSE 80 diff --git a/web/modules/custom/riverside_pt/js/components/rpt-appt-type.js b/web/modules/custom/riverside_pt/js/components/rpt-appt-type.js index 27fd45b..4d327d3 100644 --- a/web/modules/custom/riverside_pt/js/components/rpt-appt-type.js +++ b/web/modules/custom/riverside_pt/js/components/rpt-appt-type.js @@ -1,6 +1,4 @@ -import { h, render } from "https://esm.sh/preact@10"; -import { useState } from "https://esm.sh/preact@10/hooks"; -import { html } from "https://esm.sh/htm@3/preact"; +import { h, render, useState, html } from "../vendor/preact-standalone.js"; const TYPES = [ { id: "diagnostic", label: "Diagnostic Assessment", duration: "60 MINS" }, diff --git a/web/modules/custom/riverside_pt/js/components/rpt-booking.js b/web/modules/custom/riverside_pt/js/components/rpt-booking.js index 07d8982..2f309a7 100644 --- a/web/modules/custom/riverside_pt/js/components/rpt-booking.js +++ b/web/modules/custom/riverside_pt/js/components/rpt-booking.js @@ -1,6 +1,4 @@ -import { h, render } from "https://esm.sh/preact@10"; -import { useState, useEffect, useRef, useMemo } from "https://esm.sh/preact@10/hooks"; -import { html } from "https://esm.sh/htm@3/preact"; +import { h, render, useState, useEffect, useRef, useMemo, html } from "../vendor/preact-standalone.js"; const TYPES = [ { id: "diagnostic", label: "Diagnostic Assessment", duration: "60 MINS" }, diff --git a/web/modules/custom/riverside_pt/js/components/rpt-carousel.js b/web/modules/custom/riverside_pt/js/components/rpt-carousel.js index 74d4aa8..d1d4ef5 100644 --- a/web/modules/custom/riverside_pt/js/components/rpt-carousel.js +++ b/web/modules/custom/riverside_pt/js/components/rpt-carousel.js @@ -1,6 +1,4 @@ -import { h, render } from 'https://esm.sh/preact@10'; -import { useState, useLayoutEffect, useRef } from 'https://esm.sh/preact@10/hooks'; -import { html } from 'https://esm.sh/htm@3/preact'; +import { h, render, useState, useLayoutEffect, useRef, html } from '../vendor/preact-standalone.js'; const IMAGES = [ { src: '/modules/custom/riverside_pt/images/hero.jpg', alt: 'Physical therapy session' }, diff --git a/web/modules/custom/riverside_pt/js/components/rpt-faq.js b/web/modules/custom/riverside_pt/js/components/rpt-faq.js index b02d124..1ba3d0c 100644 --- a/web/modules/custom/riverside_pt/js/components/rpt-faq.js +++ b/web/modules/custom/riverside_pt/js/components/rpt-faq.js @@ -1,6 +1,4 @@ -import { h, render } from "https://esm.sh/preact@10"; -import { useState } from "https://esm.sh/preact@10/hooks"; -import { html } from "https://esm.sh/htm@3/preact"; +import { h, render, useState, html } from "../vendor/preact-standalone.js"; const FAQS = [ { diff --git a/web/modules/custom/riverside_pt/js/components/rpt-testimonials.js b/web/modules/custom/riverside_pt/js/components/rpt-testimonials.js index e97a1fc..1c72e0c 100644 --- a/web/modules/custom/riverside_pt/js/components/rpt-testimonials.js +++ b/web/modules/custom/riverside_pt/js/components/rpt-testimonials.js @@ -1,6 +1,4 @@ -import { h, render } from "https://esm.sh/preact@10"; -import { useState, useEffect, useReducer, useRef } from "https://esm.sh/preact@10/hooks"; -import { html } from "https://esm.sh/htm@3/preact"; +import { h, render, useState, useEffect, useReducer, useRef, html } from "../vendor/preact-standalone.js"; const TESTIMONIALS = [ { diff --git a/web/modules/custom/riverside_pt/js/components/rpt-toggle.js b/web/modules/custom/riverside_pt/js/components/rpt-toggle.js index b1acd7f..ba72944 100644 --- a/web/modules/custom/riverside_pt/js/components/rpt-toggle.js +++ b/web/modules/custom/riverside_pt/js/components/rpt-toggle.js @@ -1,6 +1,4 @@ -import { h, render } from 'https://esm.sh/preact@10'; -import { useState } from 'https://esm.sh/preact@10/hooks'; -import { html } from 'https://esm.sh/htm@3/preact'; +import { h, render, useState, html } from '../vendor/preact-standalone.js'; function Toggle({ label = 'Toggle' }) { const [checked, setChecked] = useState(false);