Skip to content

[audit] framer-motion/animation: remove dead code#3733

Open
mattgperry wants to merge 1 commit into
mainfrom
audit/framer-motion-animation
Open

[audit] framer-motion/animation: remove dead code#3733
mattgperry wants to merge 1 commit into
mainfrom
audit/framer-motion-animation

Conversation

@mattgperry
Copy link
Copy Markdown
Collaborator

@mattgperry mattgperry commented May 19, 2026

What this directory does

packages/framer-motion/src/animation is the React-side animation entry layer: the animate() / useAnimate factories, sequence resolution (sequence/), the WAAPI mini animators (animators/waapi/), the legacy animation controls hooks, and the optimized-appear handoff used for SSR/streamed appear animations. It is setup/teardown code — none of it runs inside a per-frame render or update tick (per-frame work lives in motion-dom's JSAnimation/frameloop/projection). Hot-path callers were confirmed by grep: createAnimationsFromSequence runs once at animation start, animateElements once per animate() call, optimized-appear once per value at handoff.

Both lenses (performance and filesize) were applied.

Performance

No per-frame hot path exists in this directory, so there are no frame-loop allocation/closure findings (cold-path micro-optimisation is intentionally not listed). No changes.

(An earlier revision swapped performance.now() to time.now() in optimized-appear/start.ts; this was reverted at the maintainer's request and is no longer part of this PR.)

Filesize

Baseline vs after, minified production bundles, gzip -9all unchanged:

bundle before (gz) after (gz) delta
framer-motion/dist/framer-motion.js 59626 59626 0
framer-motion/dist/dom.js 43692 43692 0
framer-motion/dist/mini.js 3352 3352 0
framer-motion/dist/dom-mini.js 4979 4979 0
motion/dist/motion.js 43692 43692 0

Dead code removal — source cleanup, ~0 bundle impact (stated honestly):

  • utils/is-keyframes-target.tsisKeyframesTarget here is an unused duplicate; the only consumed isKeyframesTarget is motion-dom's own (motion-dom/src/render/utils/is-keyframes-target.ts). No importer anywhere in the repo.
  • utils/variant-resolvers.tsresolveVariantLabels / asDependencyList have zero references repo-wide (packages + dev).

Because neither file was imported anywhere, both were already tree-shaken out of every bundle — deleting them does not shrink the gzipped output (hence the 0 deltas). Framed as maintainability cleanup, not a filesize win.

animation/types.ts (ResolveKeyframes) was flagged as unused internally but is re-exported via export type * from "./animation/types" in the public index — it is public type API, so left untouched (no public API changes).

Testing

  • yarn build — all 8 tasks pass.
  • animation test suites — 16 suites, 167 passed, 1 skipped (pre-existing React act() warning in use-animated-state is unrelated).

🤖 Generated with Claude Code

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 19, 2026

Greptile Summary

This PR makes two targeted changes to packages/framer-motion/src/animation: a correctness fix replacing performance.now() with time.now() in the optimized-appear handoff, and deletion of two dead-code utility files that were already tree-shaken from every bundle.

  • optimized-appear/start.ts: startFrameTime is now seeded via time.now() (motion-dom's eventloop-synchronous, frame-locked clock) instead of a raw performance.now() call. The existing startFrameTime === undefined guard keeps the timestamp stable across the microtask chain triggered by readyAnimation.ready.then(), so all appear animations share one start time as intended. The stale comment referencing a removed handoff.ts call is corrected. Aligns with the repo-wide CLAUDE.md timing rule.
  • utils/is-keyframes-target.ts / utils/variant-resolvers.ts: Both files had zero importers anywhere in the repo and were already fully tree-shaken; deleting them is a pure maintainability cleanup with no bundle impact.

Confidence Score: 5/5

Safe to merge — all three changes are narrow and well-reasoned with no risk of regressions.

The time.now() swap is behaviourally equivalent to the old performance.now() call (both return a performance-clock value) while adding the caching benefit; the module-level startFrameTime guard already handles cross-microtask stability. The two deleted files had zero importers and were already tree-shaken, so removing them carries no runtime risk.

No files require special attention.

Important Files Changed

Filename Overview
packages/framer-motion/src/animation/optimized-appear/start.ts Replaces performance.now() with time.now() (motion-dom frame-synced clock) for startFrameTime; updates stale comment. The module-level startFrameTime guard correctly holds the timestamp stable across the microtasks spawned by readyAnimation.ready.then(), so the behavioural contract is unchanged.
packages/framer-motion/src/animation/utils/is-keyframes-target.ts Deleted unused duplicate of motion-dom's own isKeyframesTarget; confirmed zero importers in the repo.
packages/framer-motion/src/animation/utils/variant-resolvers.ts Deleted dead-code file (resolveVariantLabels, asDependencyList) with zero references repo-wide; safe removal.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["startOptimizedAppearAnimation()"] --> B{readyAnimation exists?}
    B -->|No| C["Create readyAnimation (dummy 10s WAAPI)"]
    C --> D[Register window.Motion handlers]
    D --> E{readyAnimation.ready?}
    B -->|Yes| E
    E -->|Promise| F["readyAnimation.ready.then(startAnimation)"]
    E -->|No promise| G["startAnimation() sync"]
    F --> H["startAnimation() microtask"]
    G --> I{startFrameTime === undefined?}
    H --> I
    I -->|Yes| J["startFrameTime = time.now()"]
    I -->|No| K[Reuse existing startFrameTime]
    J --> L["appearAnimation.startTime = startFrameTime"]
    K --> L
    L --> M[Store in appearAnimationStore]
Loading

Reviews (1): Last reviewed commit: "[audit] framer-motion/animation: time.no..." | Re-trigger Greptile

Filesize / maintainability:
- Remove utils/is-keyframes-target.ts — unused duplicate of motion-dom's
  own is-keyframes-target (the only consumed copy). No importer repo-wide.
- Remove utils/variant-resolvers.ts — resolveVariantLabels /
  asDependencyList have zero references repo-wide.

Both already tree-shaken out of every bundle, so this is a source
cleanup with ~0 gzipped delta, not a filesize win.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@mattgperry mattgperry force-pushed the audit/framer-motion-animation branch from 18caece to 948a01b Compare May 19, 2026 12:10
@mattgperry mattgperry changed the title [audit] framer-motion/animation: time.now() in optimized-appear + dead code removal [audit] framer-motion/animation: remove dead code May 19, 2026
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.

1 participant