fix(astro): register middleware by package subpath, not chunk-relative URL - #254
Merged
Merged
Conversation
…e URL
tastyIntegration() registered its middleware with
new URL('./astro-middleware.js', import.meta.url). That URL resolves
against the emitted chunk, and the v3 build hoists tastyIntegration out
of dist/ssr/astro.js into a shared chunk at the dist/ root — so it
pointed at dist/astro-middleware.js, which does not exist, while the
real file shipped at dist/ssr/astro-middleware.js. Every Astro build on
3.0.0 failed. Astro now gets a package subpath, resolved through the
exports map and immune to chunk layout.
Also fixes islands: false silently keeping the class-list transfer
script. The flag travelled through module-level state in
astro-transfer-cache.ts, written by the integration when the Astro
config loads and read by the middleware at request time — different
module instances, and different processes entirely for built output, so
the middleware always saw the true default. Replaced with two
self-contained entrypoints; addMiddleware() cannot pass options.
Adds ssr/astro-middleware and ssr/astro-middleware-static exports.
They exist so Astro can resolve the middleware by specifier; manual
setups should keep using tastyMiddleware().
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
📦 Snapshot releasePublished |
Merged
tenphi
added a commit
to tenphi/tenphi.me
that referenced
this pull request
Aug 5, 2026
Nothing in the v2 -> v3 rename set applied here: no camelCase at-rule keys,
no renamed or removed exports, no `configure({ funcs })`, no `/next` subpath,
and every directional group was already single-value.
Two substantive changes:
- `flex: '1 1 auto'` -> the flexGrow/flexShrink/flexBasis triple used
everywhere else in the codebase. Caught by eslint-plugin-tasty 1.0.0, which
now detects `styles={{ ... }}` JSX props; the value had been invisible to
every rule until now.
- The output no longer carries Tasty's `window.__TASTY__` class-list script.
`islands: false` never actually took effect before: the flag travelled
through module-level state written when the Astro config loaded and read at
request time, which are different module instances, so the middleware always
saw the default. Fixed upstream in 3.0.1 (tenphi/tasty#254) by splitting the
integration into two self-contained middleware entrypoints. The site ships
no `client:*` directives, so this is dead weight removed from every page.
3.0.0 is unusable with Astro and skipped: tastyIntegration() resolved its
middleware via `new URL('./astro-middleware.js', import.meta.url)`, and the v3
build hoisted the integration into a shared chunk one directory above the file
that shipped, failing the build for every consumer.
Verified by diffing normalized CSS and markup across all 7 pages against a
2.11.0 baseline build: byte-identical apart from the flex longhands and the
removed transfer script. Also confirmed `islands: true` still emits the script,
so both entrypoints resolve.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
tastyIntegration()is broken in the published 3.0.0 and fails the build outright for every Astro consumer.It registered its middleware with:
import.meta.urlpoints at the emitted chunk, not the source file. The v3 build hoiststastyIntegrationout ofdist/ssr/astro.jsinto a shared chunk at thedist/root (dist/astro-B53trJyX.js), one directory up — so the URL resolved todist/astro-middleware.js, which doesn't exist. The real file shipped fine atdist/ssr/astro-middleware.js.Reported downstream; the reporter worked around it with the documented manual-middleware path (
src/middleware.tscallingtastyMiddleware({ transferCache: false }), integration dropped fromastro.config.ts).Second bug found while fixing this
tastyIntegration({ islands: false })silently kept emitting the class-list transfer script — so the "ships zero client JS" promise in the docs did not hold.The flag travelled through module-level state in
astro-transfer-cache.ts: written by the integration when the Astro config is loaded, read by the middleware at request time. Those are different module instances, and for built output different processes entirely, so the middleware always saw thetruedefault. This means the reporter's manual workaround was in fact more correct than the integration it replaced, not merely equivalent.Fix
@tenphi/tasty/ssr/astro-middleware), resolved through theexportsmap. Immune to chunk layout, which is free to change at any time.addMiddleware()cannot pass options.astro-middlewarebakes intransferCache: true,astro-middleware-staticbakes infalse.astro-transfer-cache.tsis deleted../ssr/astro-middlewareand./ssr/astro-middleware-staticexist only so Astro can resolve them by specifier; manual setups should keep usingtastyMiddleware(). Documented as such indocs/ssr.mdandAGENTS.md.Consumers on the manual workaround can revert to
tastyIntegration()once on this release, or keep the manual setup — both are supported.Tests
New
src/ssr/astro-integration.test.ts. The important one asserts the entrypoint is actually reachable — declared inpackage.jsonexportsand produced by atsdownentry — rather than just that some string was passed, which is the class of bug that shipped. Both guards were verified to fail against the broken code before being committed:new URL(...)entrypoint → 4 tests failexportsentry →@tenphi/tasty/ssr/astro-middleware is not declared in package.json "exports"The transfer-cache tests render through each
onRequestwith a collected style chunk and assert the islands variant emitswindow.__TASTY__while the static one emits no<script>at all.Verification
pnpm test— 66 files, 1939 passedpnpm hygiene(lint + format + typecheck),pnpm knip,pnpm size— all cleanonRequestnpm pack, installed the tarball into a clean consumer, ran the integration hook and dynamically imported whatever entrypoint it handed back — resolves and loads for bothislands: trueandislands: false🤖 Generated with Claude Code