{"id":10917,"library":"framesync","title":"Framesync","description":"Framesync is a JavaScript library designed for scheduling functions into a synchronized render loop, primarily to prevent layout thrashing and ensure predictable execution order within a browser frame. It provides discrete steps for `read`, `update`, `preRender`, `render`, and `postRender` operations, allowing developers to organize DOM interactions efficiently. The current stable version is 6.1.2, and as part of the Popmotion ecosystem, it maintains a steady, mature release cadence focusing on stability and performance. Its primary differentiator is the explicit segregation of frame steps, which is crucial for high-performance animations and UI updates, notably used by libraries like Framer Motion to manage complex transform animations independently. Functions scheduled with Framesync receive frame data including `delta` (time since last frame) and `timestamp`.","status":"active","version":"6.1.2","language":"javascript","source_language":"en","source_url":"https://github.com/Popmotion/popmotion","tags":["javascript","animation","raf","typescript"],"install":[{"cmd":"npm install framesync","lang":"bash","label":"npm"},{"cmd":"yarn add framesync","lang":"bash","label":"yarn"},{"cmd":"pnpm add framesync","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Framesync uses an ESM default export for the main `sync` object. CommonJS `require` will result in accessing `sync.default` if supported by your build system, or an error in a pure ESM environment.","wrong":"const sync = require('framesync');","symbol":"sync","correct":"import sync from 'framesync';"},{"note":"Named exports like `cancelSync` are provided. CommonJS `require` for named exports will fail in pure ESM environments and may behave unexpectedly in others.","wrong":"const { cancelSync } = require('framesync');","symbol":"cancelSync","correct":"import { cancelSync } from 'framesync';"},{"note":"Use a type import for the `FrameData` interface (containing `delta` and `timestamp`) when working with TypeScript.","symbol":"FrameData","correct":"import type { FrameData } from 'framesync';"}],"quickstart":{"code":"import sync, { cancelSync } from 'framesync';\n\nlet animationProgress = 0;\nconst targetProgress = 100;\n\nconsole.log('Starting framesync animation...');\n\nconst updateFunction = ({ delta, timestamp }) => {\n  // In a real app, 'delta' would be used to calculate frame-rate independent updates.\n  // For this example, we'll just increment.\n  animationProgress += 1; \n\n  // Simulate some DOM read operation (e.g., getBoundingClientRect)\n  const elementWidth = document.body?.clientWidth || 0; \n  console.log(`[Frame ${timestamp.toFixed(2)}] Delta: ${delta.toFixed(2)}ms, Progress: ${animationProgress}, Width: ${elementWidth}`);\n\n  if (animationProgress >= targetProgress) {\n    cancelSync.update(updateFunction);\n    console.log('Animation complete!');\n  }\n};\n\nsync.update(updateFunction, true); // Schedule to run indefinitely on the update step\n\n// Simulate an immediate render call for some initial setup\nsync.render(() => {\n  // This would typically update DOM properties\n  // For example: document.body.style.transform = `translateX(${animationProgress}px)`;\n  console.log('Initial render step executed immediately.');\n}, false, true);\n","lang":"typescript","description":"Demonstrates scheduling a function to run on the `update` step of the render loop, accessing frame data, and canceling the process once a condition is met. It also shows an immediate render call."},"warnings":[{"fix":"Destructure the `FrameData` object immediately: `sync.update(({ delta, timestamp }) => { const currentDelta = delta; // use currentDelta asynchronously })`","message":"The `FrameData` object (containing `delta` and `timestamp`) passed to scheduled functions is recycled across frames for performance. If you need to use `delta` or `timestamp` asynchronously (e.g., in a `setTimeout` or `Promise`), you must destructure or copy its values, otherwise, they may change unexpectedly.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Use `sync.step(callback, keepAlive, true)` to run on the current frame step. For example: `sync.update(() => console.log('now!'), false, true);`","message":"By default, `sync` functions schedule execution for the *next* time that frame step is fired. To execute a function on the *current* frame step, you must explicitly pass `true` as the third parameter for `immediate` execution.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always ensure there's a clear condition to call `cancelSync.step(yourProcessFunction)` when using `keepAlive: true`.","message":"When using the `keepAlive: true` option, a scheduled function will run indefinitely on every frame until it is explicitly cancelled using `cancelSync.<step>(process)`. Forgetting to cancel can lead to memory leaks and unnecessary CPU usage.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"search_vec":"'6.1.2':54 'allow':42 'anim':91,106,124 'browser':28 'cadenc':68 'complex':104 'crucial':86 'current':50 'data':114 'delta':116 'design':7 'develop':43 'differenti':76 'discret':32 'dom':46 'ecosystem':61 'effici':48 'ensur':22 'execut':24 'explicit':79 'focus':69 'frame':29,82,113,120 'framer':100 'framesync':1,2,111 'function':10,108 'high':89 'high-perform':88 'includ':115 'independ':107 'interact':47 'javascript':5,123 'last':119 'layout':19 'librari':6,98 'like':99 'loop':15 'maintain':63 'manag':103 'matur':66 'motion':101 'notabl':95 'oper':41 'order':25 'organ':45 'part':57 'perform':73,90 'popmot':60 'postrend':40 'predict':23 'prerend':37 'prevent':18 'primari':75 'primarili':16 'provid':31 'raf':125 'read':35 'receiv':112 'releas':67 'render':14,38 'schedul':9,109 'segreg':80 'sinc':118 'stabil':71 'stabl':51 'steadi':65 'step':33,83 'synchron':13 'thrash':20 'time':117 'timestamp':122 'transform':105 'typescript':126 'ui':93 'updat':36,94 'use':96 'version':52 'within':26","created_at":"2026-04-19T13:35:18.030655+00:00","updated_at":"2026-04-19T13:35:18.030655+00:00","problems":[{"fix":"Ensure you are using `import sync from 'framesync';` for the default export. If using CommonJS, try `const sync = require('framesync').default;` (though this is not recommended for pure ESM libraries).","cause":"Attempting to use CommonJS `require` or an incorrect import statement with a bundler that doesn't handle ESM default exports properly, leading to `sync` being an object with a `default` property, not the `sync` object itself.","error":"TypeError: framesync__WEBPACK_IMPORTED_MODULE_0__.default.update is not a function"},{"fix":"Ensure `cancelSync` is imported as a named export: `import { cancelSync } from 'framesync';`","cause":"`cancelSync` is a named export, and its methods (`.read`, `.update`, `.render`, etc.) are functions. This error often occurs if `cancelSync` itself is not correctly imported as a named export.","error":"Uncaught TypeError: cancelSync.render is not a function"}],"ecosystem":"npm","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":"","cli_version":null,"type":"library","homepage":"https://popmotion.io/","github":"https://github.com/Popmotion/popmotion","docs":null,"changelog":null,"pypi":null,"npm":"https://www.npmjs.com/package/framesync","openapi_spec":null,"status_page":null,"smithery":null,"categories":["web-framework"],"base_url":null,"auth_type":null,"provenance":{"verified_status":null,"verified_at":null,"last_verified":"2026-06-17","next_check":"2026-07-18","install_tag":null}}