Skip to content

🍕 Fix scoped-style data-v mismatch between clay vite and clay compile - #265

Merged
jjpaulino merged 1 commit into
masterfrom
jordan/fix-vite-compile-scopeid-mismatch
Sep 15, 2026
Merged

jjpaulino merged 1 commit into
masterfrom
jordan/fix-vite-compile-scopeid-mismatch

Conversation

@jjpaulino

Copy link
Copy Markdown
Member

TL;DR — for reviewers short on time

  • Outcome and scope: Found by live-testing 6.0.0-rc.6 on stg.curbed.com's Agora Kiln plugin, at the user's request, right after the rc.6 sites bump landed on stg. Every <style scoped> rule in every Kiln plugin was silently failing to match on this staged-rollout site — Agora rendered as a plain, unstyled list instead of its designed card/table layout. clay vite's scope-id hash and clay compile's (@nymag/vueify) scope-id hash were computing different values for the same file (verified: 40406d57 vs 0dbbeed6 for one real Agora component) — a pre-existing mismatch that predates this whole pass of fixes, unmasked specifically by 🍕 Share and validate the Kiln-plugin PostCSS chain across both pipelines #258 removing the runtime <style> injection that had been accidentally compensating for it.
  • Risk: Medium — this is a correctness fix for an actively-broken staging site, but it changes every Kiln plugin's scope-id hash algorithm. Sites relying on the OLD (djb2) hash for anything beyond CSS-to-DOM matching (nothing should, but flagging the surface area) would need to re-verify. Fully reversible.
  • Validation: npm test (lint + all 456 tests) green. Verified live against the actual regression: recomputed both algorithms directly for the real Agora file path and confirmed they previously diverged; after the fix, a live transform() + closeBundle() cycle against a real fixture confirms the JS component's _scopeId and the written CSS's [data-v-XXXXXXXX] selector now match exactly — including for a template-less scoped SFC (composes correctly with the earlier _scopeId fix). No test files added.
  • If you only review one thing: lib/cmd/vite/plugins/vue2.js L524–L551computeScopeId(), now delegating to hash-sum, with the full mechanism documented inline.
  • Changes, in logical review order:
    1. lib/cmd/vite/plugins/vue2.js L524–L551 — the fix itself.
    2. package.json / package-lock.json — adds hash-sum as a direct dependency (previously only available transitively via @nymag/vueify).

Feature Info

Description

This surfaced from real-environment testing on nymag/sites' stg deployment of 6.0.0-rc.6, immediately after that bump — see the linked repro data in the commit message. Recommend fast-tracking this given it's an active regression on a live staging site right now.

QA Testing Notes

Re-verify on stg.curbed.com's Agora Kiln plugin (?edit=true#kiln~agora~~) once this ships in a new rc and sites re-bumps: the product list should render with its designed flex/card layout (image + text side-by-side per row) rather than a plain stacked list.

🤖 Generated with Claude Code

Found by live-testing 6.0.0-rc.6 on stg.curbed.com's Agora Kiln plugin
(#258 landed correctly -- verified the exact autoprefixer bug it fixed is
gone in the live _kiln-plugins.css -- but every `<style scoped>` rule in
Agora was silently failing to match, rendering a plain, unstyled UI).

Root cause: clay vite's computeScopeId() used a hand-rolled djb2 hash of
the file path, self-consistent within this plugin but never actually
verified against clay compile's algorithm. clay compile's
@nymag/vueify computes scope ids via hash-sum(filePath) (lib/gen-id.js).
For the SAME file, these produce COMPLETELY DIFFERENT ids (verified:
40406d57 vs 0dbbeed6 for one real Agora component).

nymag/sites' staged Vite rollout (CLAYCLI_VITE_SITES=grubstreet,curbed)
builds `build:both` -- both pipelines run, and both write
public/css/_kiln-plugins.css; whichever runs last (clay compile) wins on
disk. The Vue component actually MOUNTED in the browser during edit mode
comes from clay vite's kiln-edit bundle and carries vite's scope id
(data-v-40406d57). The CSS file on disk, last written by clay compile,
only has selectors for compile's scope id (data-v-0dbbeed6). These never
match, so every scoped rule for every Kiln plugin silently fails to apply
-- with no error anywhere, on either pipeline.

This mismatch is not new -- it predates this whole pass of fixes. It was
masked the entire time by clay vite's runtime <style> injection (removed
by #258's "stop double-applying" fix): that injection delivered clay
vite's OWN compiled CSS -- with vite's OWN (self-consistent) scope id --
directly into <head>, independent of whatever ended up in the linked
file. Removing the double-delivery bug removed the thing that had been
accidentally compensating for this separate, pre-existing bug, surfacing
it for the first time.

Fix: computeScopeId() now calls the SAME hash-sum(filepath) both
pipelines already use for the compile side, so both compute IDENTICAL
scope ids for the same file regardless of which pipeline runs last.
Verified: hash-sum output for the affected file now matches what
@nymag/vueify's genId() produces for the same path; a live transform+
closeBundle cycle confirms the JS's _scopeId and the written CSS's
[data-v-XXXXXXXX] selector now match exactly, including for a
template-less scoped SFC (interacting correctly with the earlier
_scopeId fix).

Adds hash-sum as a direct dependency (previously only available
transitively via @nymag/vueify).

npm test (lint + all 456 tests) green.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 83.002% (-0.02%) from 83.02% — jordan/fix-vite-compile-scopeid-mismatch into master

@jjpaulino
jjpaulino merged commit da8e346 into master Sep 15, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants