From 0f4037de89ac0bc1af1a83638982939d0f942efe Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 11 May 2026 08:34:10 -0400 Subject: [PATCH] fix(astro): treat 'astro' vite environment as a server environment The internal 'astro' environment is used as a Node.js fallback when the 'ssr' environment is not runnable (e.g. Cloudflare adapter with workerd). It was not included in isAstroServerEnvironment(), causing Vite plugins to serve client-side script content in this environment. On HMR reload, this evaluated browser-only code (HTMLElement) in Node.js, crashing the dev server. Closes #16626 --- .changeset/astro-env-treated-as-server.md | 5 +++ packages/astro/src/environments.ts | 3 +- .../astro/test/units/environments.test.ts | 39 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 .changeset/astro-env-treated-as-server.md create mode 100644 packages/astro/test/units/environments.test.ts diff --git a/.changeset/astro-env-treated-as-server.md b/.changeset/astro-env-treated-as-server.md new file mode 100644 index 000000000000..67c90950e6eb --- /dev/null +++ b/.changeset/astro-env-treated-as-server.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes `HTMLElement is not defined` error during HMR when using components with client-side scripts (e.g. Starlight ``) and the Cloudflare adapter diff --git a/packages/astro/src/environments.ts b/packages/astro/src/environments.ts index 9aa1180c8802..796b5bc43b13 100644 --- a/packages/astro/src/environments.ts +++ b/packages/astro/src/environments.ts @@ -4,7 +4,8 @@ import { ASTRO_VITE_ENVIRONMENT_NAMES } from './core/constants.js'; export function isAstroServerEnvironment(environment: Environment) { return ( environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || - environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender + environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender || + environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.astro ); } diff --git a/packages/astro/test/units/environments.test.ts b/packages/astro/test/units/environments.test.ts new file mode 100644 index 000000000000..b885e4f6499a --- /dev/null +++ b/packages/astro/test/units/environments.test.ts @@ -0,0 +1,39 @@ +import * as assert from 'node:assert/strict'; +import { describe, it } from 'node:test'; +import type { Environment } from 'vite'; +import { isAstroClientEnvironment, isAstroServerEnvironment } from '../../dist/environments.js'; + +/** Create a minimal mock Environment with only the `name` property. */ +function env(name: string) { + return { name } as unknown as Environment; +} + +describe('isAstroServerEnvironment', () => { + it('should return true for the ssr environment', () => { + assert.equal(isAstroServerEnvironment(env('ssr')), true); + }); + + it('should return true for the prerender environment', () => { + assert.equal(isAstroServerEnvironment(env('prerender')), true); + }); + + it('should return true for the astro environment', () => { + assert.equal(isAstroServerEnvironment(env('astro')), true); + }); + + it('should return false for the client environment', () => { + assert.equal(isAstroServerEnvironment(env('client')), false); + }); +}); + +describe('isAstroClientEnvironment', () => { + it('should return true for the client environment', () => { + assert.equal(isAstroClientEnvironment(env('client')), true); + }); + + it('should return false for server environments', () => { + assert.equal(isAstroClientEnvironment(env('ssr')), false); + assert.equal(isAstroClientEnvironment(env('prerender')), false); + assert.equal(isAstroClientEnvironment(env('astro')), false); + }); +});