From 0a068e28f78d098696747f36074a121fbb1e5f7f Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 24 Jan 2025 17:49:20 +0530 Subject: [PATCH] perf: proxy-cache website_script.js --- frappe/www/website_script.py | 39 ++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/frappe/www/website_script.py b/frappe/www/website_script.py index 5ab92626da..08ecb78075 100644 --- a/frappe/www/website_script.py +++ b/frappe/www/website_script.py @@ -3,26 +3,53 @@ import frappe from frappe.utils import strip +from frappe.utils.data import add_to_date, get_datetime from frappe.website.doctype.website_theme.website_theme import get_active_theme base_template_path = "www/website_script.js" +# NOTE: This is misleading. +# We want to avoid Redis cache and instead use proxy cache as website_script.js gets loaded on +# every website page and never really changes. +# If we don't avoid redis cache then we can't set appropirate headers every time. +no_cache = True + +# 5 minutes public cache, SWR after that to avoid hard "misses". +cache_headers = {"Cache-Control": "public,max-age=300,stale-while-revalidate=10800"} + def get_context(context): - context.javascript = frappe.db.get_single_value("Website Script", "javascript") or "" + should_cache = not_modified_recently(frappe.get_website_settings("modified")) - theme = get_active_theme() - js = strip((theme and theme.js) or "") - if js: - context.javascript += "\n" + js + website_script = frappe.get_cached_doc("Website Script") + context.javascript = website_script.javascript or "" + should_cache &= not_modified_recently(website_script.modified) + + if theme := get_active_theme(): + js = strip(theme.js or "") + if js: + context.javascript += "\n" + js + should_cache &= not_modified_recently(theme.modified) if not frappe.conf.developer_mode: context["google_analytics_id"] = get_setting("google_analytics_id") context["google_analytics_anonymize_ip"] = get_setting("google_analytics_anonymize_ip") + # Heuristics/DX: + # If none of the documents are being modified right now then we can cache this page. + # Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching#heuristic_caching + if should_cache: + frappe.local.response_headers.update(cache_headers) + + +def not_modified_recently(timestamp): + ten_minutes_ago = add_to_date(minutes=-10, as_datetime=True, as_string=False) + + return ten_minutes_ago > get_datetime(timestamp) + def get_setting(field_name): """Return value of field_name frok Website Settings or Site Config.""" - website_settings = frappe.db.get_single_value("Website Settings", field_name) + website_settings = frappe.get_website_settings(field_name) conf = frappe.conf.get(field_name) return website_settings or conf