Skip to content

Commit 9f6c05f

Browse files
fix: Avoid prerender duplicate calls for same calLink that could arise with faulty implementation (calcom#21982)
* fix: Avoid prerender duplicate calls * Update README * Ensure "noAction" action occurs if nothing changes * fix bug * Introduce connect method for reliable re-use --------- Co-authored-by: Alex van Andel <me@alexvanandel.com>
1 parent f8a1bd7 commit 9f6c05f

6 files changed

Lines changed: 445 additions & 718 deletions

File tree

packages/embeds/README.md

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ For example, if your page is `https.example.com/contact`, you can enable logging
166166
#### Routing Prerendering System
167167
The prerendering system optimizes the initial load:
168168
```typescript
169-
Cal.prerender({
170-
calLink: "organization/event-type",
169+
Cal("prerender", {
170+
calLink,
171171
type: "modal"
172172
});
173173
```
@@ -178,24 +178,63 @@ Key aspects:
178178
- Loads the booking page but doesn't send the slots availability request
179179
- Tries to reuse whenever it makes sense and do a fresh load otherwise
180180

181-
Iframe Reuse and Reload Conditions. There could be three situations:
181+
Modal's Iframe Reuse and Reload Conditions. There could be four situations:
182182

183-
1. Reuse
184-
2. Reuse the iframe but refetch the slots
185-
3. Do a fresh load in iframe
183+
1. Show modal as is. No connect and no requests happen - Corresponding action is "noAction"
184+
2. Connect but don't fetch the slots- Corresponding action is "connect-no-slots-fetch"
185+
3. Connect and fetch the slots - Corresponding action is "connect"
186+
4. Do a fresh load in iframe. Corresponding action is "fullReload"
186187

187-
- **Reuse**:
188-
- Modal opens when
189-
- Modal is not in a failed state
190-
- config, params are same as the last time
191-
- No threshold violations
188+
- **Show modal as is**:
189+
- Modal is not in a failed state
190+
- config, params are same as the last time
191+
- No time threshold violations
192192

193-
- **Reuse the iframe but refetch the slots**:
193+
- **Connect but don't fetch the slots**:
194194
- Only embed `config` changes (handled via "connect" flow)
195195
- Query query params changes (handled via "connect" flow)
196196
- Crossed slots stale time threshold (EMBED_MODAL_IFRAME_SLOT_STALE_TIME)
197197

198-
- **Fresh Reload Conditions**:
198+
- **Connect and fetch the slots**:
199+
- Slots are stale
200+
- Crossed slots stale time threshold (EMBED_MODAL_IFRAME_SLOT_STALE_TIME)
201+
202+
- **Do a fresh load in iframe**:
199203
- Different path being loaded(i.e. /pro vs /free)
200204
- Modal is in a failed state
201205
- Time since last render exceeds EMBED_MODAL_IFRAME_FORCE_RELOAD_THRESHOLD_MS
206+
207+
208+
#### Prerendering headless router
209+
210+
**Without namespace:**
211+
Prerender when there are high chances of user clicking the CTA.
212+
```js
213+
Cal('prerender', {
214+
calLink: "router?formId=123&ONLY_THOSE_FIELDS_THAT_ARE_REQUIRED_BY_ROUTING_RULES_SHOULD_BE_PRESENT_HERE",
215+
// Prerender right now works only with "modal", so 'element click' embed is able to reuse this prerendered iframe
216+
type: "modal",
217+
// Shows skeleton loader for a Team Event's booking slots page
218+
pageType: "team.event.booking.slots"
219+
});
220+
```
221+
Using the prerendered iframe with a CTA:
222+
```js
223+
<button data-cal-link="router?formId=123&ALL_FIELDS_HERE">Demo</button>
224+
```
225+
226+
**With namespace:**
227+
Prerender when there are high changes of user clicking the CTA.
228+
```js
229+
Cal.ns.myNamespace('prerender', {
230+
calLink: "router?formId=123&ONLY_THOSE_FIELDS_THAT_ARE_REQUIRED_BY_ROUTING_RULES_SHOULD_BE_PRESENT_HERE",
231+
// Prerender right now works only with "modal", so 'element click' embed is able to reuse this prerendered iframe
232+
type: "modal"
233+
// Shows skeleton loader for a Team Event's booking slots page
234+
pageType: "team.event.booking.slots"
235+
});
236+
```
237+
Using the prerendered iframe with a CTA:
238+
```js
239+
<button data-cal-namespace="myNamespace" data-cal-link="router?formId=123&ALL_FIELDS_HERE">Demo</button>
240+
```

packages/embeds/embed-core/src/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ export const EMBED_MODAL_IFRAME_SLOT_STALE_TIME = 60 * 1000; // 1 minute
44
// Keep it high by default to avoid impact on loading time as it would cause a full reload of the iframe user can configure it via options.iframeForceReloadThresholdMs
55
// Also full reload means that response would be resubmitted.
66
export const EMBED_MODAL_IFRAME_FORCE_RELOAD_THRESHOLD_MS = 15 * 60 * 1000; // 15 minutes
7+
// Ensures that prerender instruction would never re-prerender within one minute as long as the link is the same.
8+
export const EMBED_MODAL_PRERENDER_PREVENT_THRESHOLD_MS = 1 * 60 * 1000; // 1 minute
79

810
if (EMBED_MODAL_IFRAME_SLOT_STALE_TIME > EMBED_MODAL_IFRAME_FORCE_RELOAD_THRESHOLD_MS) {
911
throw new Error(

0 commit comments

Comments
 (0)