Serve Preact from the site: the components rendered nothing
All checks were successful
deploy / image (push) Successful in 5m17s

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 <noreply@anthropic.com>
This commit is contained in:
Philip Peterson 2026-11-02 06:08:05 -09:00
parent c53247a943
commit dcb58bbb3a
8 changed files with 21 additions and 19 deletions

3
.gitignore vendored
View file

@ -7,3 +7,6 @@ web/sites/default/files/*
.env
node_modules/
# Downloaded at image build (Dockerfile)
web/modules/custom/riverside_pt/js/vendor/

View file

@ -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

View file

@ -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" },

View file

@ -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" },

View file

@ -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' },

View file

@ -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 = [
{

View file

@ -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 = [
{

View file

@ -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);