Why do component HTML files have no-cache headers? 500ms latency per interaction

TL;DR: custom components take too long to load, and Streamlit wants to set CDN cache control to no-cache. Why? What can I do?


I noticed that loading third-party components (specifically streamlit-keyup and streamlit-shadcn-ui) adds about 500ms of latency per page load. This accounts for half of my 1s page load time.

I was going to opt these files into my CDN cache, but the component responses have a Cache-Control: no-cache header. I think this comes from Streamlit’s component request handler:

    def set_extra_headers(self, path: str) -> None:
        """Disable cache for HTML files.

        Other assets like JS and CSS are suffixed with their hash, so they can
        be cached indefinitely.
        """
        is_index_url = len(path) == 0

        if is_index_url or path.endswith(".html"):
            self.set_header("Cache-Control", "no-cache")
        else:
            self.set_header("Cache-Control", "public")

Defined here: streamlit/lib/streamlit/web/server/component_request_handler.py at develop · streamlit/streamlit · GitHub

Questions:

  1. Why are component HTML files set to no-cache while other assets can be cached?
  2. Is there a supported way to optimize component loading times?
  3. What are the risks if we were to override this caching behavior (e.g., via CloudFront)?

Thanks!

I’ve asked around on the Streamlit team, and the consensus seems to be:

  • This is a hard problem because you could change the component (e.g. upgrade to a new version), and the file would still be called index.html, so by default the browser would use the old version.
  • This is something that could (and should) probably be improved.

Would you be interested in creating a github request for this?