Skip to content

Removing a component's last style leaves the old CSS applied until a full reload #457

Description

@Brooooooklyn

Split out of a Codex review finding on #455. Pre-existing on main — the transition behaves identically there.

Symptom

A component has styles, then loses them — its last inline styles entry is deleted, its array becomes [], or its external stylesheet becomes empty. HMR updates the component, but the old CSS stays applied. Only a full reload clears it.

Cause

The HMR module spreads the existing Class.ɵcmp, so a property it does not emit keeps its previous value. The generator omits styles for BOTH null and an empty array:

compileForHmrSync(styles = null)        →  no styles property emitted
compileForHmrSync(styles = [])          →  no styles property emitted
compileForHmrSync(styles = ['.a{}'])    →  styles: [ … ]

So there is no way for the plugin to express "this component now has no styles" — the distinction is erased on the Rust side.

Why the obvious fix is not enough

The review that surfaced this recommended preserving a definitive empty state through compileForHmrSync and emitting styles: []. The first half is a plugin change; the second half is a Rust generator change, and without it the plugin cannot express the state no matter what it passes. Both halves are needed.

Suggested fix

  1. Make the HMR generator emit styles: [] when it is given an empty array, so the spread is overridden, while continuing to omit the property for null (meaning "unknown, leave as-is").
  2. Have the plugin pass [] rather than null when it knows the component is definitively styleless — fix(vite): resolve @ng/component styles per class #455 already computes that state and currently collapses it to null.

Worth adding endpoint regressions for both transitions, non-empty to empty external and non-empty to empty inline. #455's tests only cover components that were already styleless, so they cannot catch this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions