perf: simpler/faster preload header computation
We parse entire response to find preload headers, instead just use include_style and include_script to include assets directly into preload headers. This shaves off ~13% overhead in response.
This commit is contained in:
parent
48869d506f
commit
4241f8c8c0
3 changed files with 33 additions and 22 deletions
|
|
@ -240,6 +240,7 @@ def init(site: str, sites_path: str = ".", new_site: bool = False) -> None:
|
|||
local.document_cache = {}
|
||||
local.meta_cache = {}
|
||||
local.form_dict = _dict()
|
||||
local.preload_assets = {"style": [], "script": []}
|
||||
local.session = _dict()
|
||||
local.dev_server = _dev_server
|
||||
local.qb = get_query_builder(local.conf.db_type or "mariadb")
|
||||
|
|
|
|||
|
|
@ -95,13 +95,33 @@ def get_dom_id(seed=None):
|
|||
return "id-" + generate_hash(seed, 12)
|
||||
|
||||
|
||||
def include_script(path):
|
||||
def include_script(path, preload=True):
|
||||
"""Get path of bundled script files.
|
||||
|
||||
If preload is specified the path will be added to preload headers so browsers can prefetch
|
||||
assets."""
|
||||
path = bundled_asset(path)
|
||||
|
||||
if preload:
|
||||
import frappe
|
||||
|
||||
frappe.local.preload_assets["script"].append(path)
|
||||
|
||||
return f'<script type="text/javascript" src="{path}"></script>'
|
||||
|
||||
|
||||
def include_style(path, rtl=None):
|
||||
def include_style(path, rtl=None, preload=True):
|
||||
"""Get path of bundled style files.
|
||||
|
||||
If preload is specified the path will be added to preload headers so browsers can prefetch
|
||||
assets."""
|
||||
path = bundled_asset(path)
|
||||
|
||||
if preload:
|
||||
import frappe
|
||||
|
||||
frappe.local.preload_assets["style"].append(path)
|
||||
|
||||
return f'<link type="text/css" rel="stylesheet" href="{path}">'
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -527,7 +527,8 @@ def build_response(path, data, http_status_code, headers: dict | None = None):
|
|||
response.headers["X-Page-Name"] = path.encode("ascii", errors="xmlcharrefreplace")
|
||||
response.headers["X-From-Cache"] = frappe.local.response.from_cache or False
|
||||
|
||||
add_preload_headers(response)
|
||||
add_preload_for_bundled_assets(response)
|
||||
|
||||
if headers:
|
||||
for key, val in headers.items():
|
||||
response.headers[key] = val.encode("ascii", errors="xmlcharrefreplace")
|
||||
|
|
@ -557,29 +558,18 @@ def set_content_type(response, data, path):
|
|||
return data
|
||||
|
||||
|
||||
def add_preload_headers(response):
|
||||
from bs4 import BeautifulSoup, SoupStrainer
|
||||
def add_preload_for_bundled_assets(response):
|
||||
|
||||
try:
|
||||
preload = []
|
||||
strainer = SoupStrainer(re.compile("script|link"))
|
||||
soup = BeautifulSoup(response.data, "html.parser", parse_only=strainer)
|
||||
for elem in soup.find_all("script", src=re.compile(".*")):
|
||||
preload.append(("script", elem.get("src")))
|
||||
links = []
|
||||
|
||||
for elem in soup.find_all("link", rel="stylesheet"):
|
||||
preload.append(("style", elem.get("href")))
|
||||
for css in frappe.local.preload_assets["style"]:
|
||||
links.append(f"<{css}>; rel=preload; as=style")
|
||||
|
||||
links = []
|
||||
for _type, link in preload:
|
||||
links.append(f"<{link}>; rel=preload; as={_type}")
|
||||
for js in frappe.local.preload_assets["script"]:
|
||||
links.append(f"<{js}>; rel=preload; as=script")
|
||||
|
||||
if links:
|
||||
response.headers["Link"] = ",".join(links)
|
||||
except Exception:
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
if links:
|
||||
response.headers["Link"] = ",".join(links)
|
||||
|
||||
|
||||
@lru_cache
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue