bundle chakra in window for CSR (#4042)
* bundle chakra in window for CSR * remove repeated chakra ui reference * use dynamically generated libraries * remove js from it
This commit is contained in:
parent
a66e0f2e11
commit
ad0827c59c
@ -7,10 +7,9 @@ import '/styles/styles.css'
|
||||
{% block declaration %}
|
||||
import { EventLoopProvider, StateProvider, defaultColorMode } from "/utils/context.js";
|
||||
import { ThemeProvider } from 'next-themes'
|
||||
import * as React from "react";
|
||||
import * as utils_context from "/utils/context.js";
|
||||
import * as utils_state from "/utils/state.js";
|
||||
import * as radix from "@radix-ui/themes";
|
||||
{% for library_alias, library_path in window_libraries %}
|
||||
import * as {{library_alias}} from "{{library_path}}";
|
||||
{% endfor %}
|
||||
|
||||
{% for custom_code in custom_codes %}
|
||||
{{custom_code}}
|
||||
@ -33,10 +32,9 @@ export default function MyApp({ Component, pageProps }) {
|
||||
React.useEffect(() => {
|
||||
// Make contexts and state objects available globally for dynamic eval'd components
|
||||
let windowImports = {
|
||||
"react": React,
|
||||
"@radix-ui/themes": radix,
|
||||
"/utils/context": utils_context,
|
||||
"/utils/state": utils_state,
|
||||
{% for library_alias, library_path in window_libraries %}
|
||||
"{{library_path}}": {{library_alias}},
|
||||
{% endfor %}
|
||||
};
|
||||
window["__reflex"] = windowImports;
|
||||
}, []);
|
||||
|
@ -40,6 +40,20 @@ def _compile_document_root(root: Component) -> str:
|
||||
)
|
||||
|
||||
|
||||
def _normalize_library_name(lib: str) -> str:
|
||||
"""Normalize the library name.
|
||||
|
||||
Args:
|
||||
lib: The library name to normalize.
|
||||
|
||||
Returns:
|
||||
The normalized library name.
|
||||
"""
|
||||
if lib == "react":
|
||||
return "React"
|
||||
return lib.replace("@", "").replace("/", "_").replace("-", "_")
|
||||
|
||||
|
||||
def _compile_app(app_root: Component) -> str:
|
||||
"""Compile the app template component.
|
||||
|
||||
@ -49,10 +63,20 @@ def _compile_app(app_root: Component) -> str:
|
||||
Returns:
|
||||
The compiled app.
|
||||
"""
|
||||
from reflex.components.dynamic import bundled_libraries
|
||||
|
||||
window_libraries = [
|
||||
(_normalize_library_name(name), name) for name in bundled_libraries
|
||||
] + [
|
||||
("utils_context", f"/{constants.Dirs.UTILS}/context"),
|
||||
("utils_state", f"/{constants.Dirs.UTILS}/state"),
|
||||
]
|
||||
|
||||
return templates.APP_ROOT.render(
|
||||
imports=utils.compile_imports(app_root._get_all_imports()),
|
||||
custom_codes=app_root._get_all_custom_code(),
|
||||
hooks={**app_root._get_all_hooks_internal(), **app_root._get_all_hooks()},
|
||||
window_libraries=window_libraries,
|
||||
render=app_root.render(),
|
||||
)
|
||||
|
||||
|
@ -1,12 +1,18 @@
|
||||
"""Components that are dynamically generated on the backend."""
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from reflex import constants
|
||||
from reflex.utils import imports
|
||||
from reflex.utils.exceptions import DynamicComponentMissingLibrary
|
||||
from reflex.utils.format import format_library_name
|
||||
from reflex.utils.serializers import serializer
|
||||
from reflex.vars import Var, get_unique_variable_name
|
||||
from reflex.vars.base import VarData, transform
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from reflex.components.component import Component
|
||||
|
||||
|
||||
def get_cdn_url(lib: str) -> str:
|
||||
"""Get the CDN URL for a library.
|
||||
@ -20,6 +26,23 @@ def get_cdn_url(lib: str) -> str:
|
||||
return f"https://cdn.jsdelivr.net/npm/{lib}" + "/+esm"
|
||||
|
||||
|
||||
bundled_libraries = {"react", "@radix-ui/themes"}
|
||||
|
||||
|
||||
def bundle_library(component: "Component"):
|
||||
"""Bundle a library with the component.
|
||||
|
||||
Args:
|
||||
component: The component to bundle the library with.
|
||||
|
||||
Raises:
|
||||
DynamicComponentMissingLibrary: Raised when a dynamic component is missing a library.
|
||||
"""
|
||||
if component.library is None:
|
||||
raise DynamicComponentMissingLibrary("Component must have a library to bundle.")
|
||||
bundled_libraries.add(format_library_name(component.library))
|
||||
|
||||
|
||||
def load_dynamic_serializer():
|
||||
"""Load the serializer for dynamic components."""
|
||||
# Causes a circular import, so we import here.
|
||||
@ -58,10 +81,7 @@ def load_dynamic_serializer():
|
||||
)
|
||||
] = None
|
||||
|
||||
libs_in_window = [
|
||||
"react",
|
||||
"@radix-ui/themes",
|
||||
]
|
||||
libs_in_window = bundled_libraries
|
||||
|
||||
imports = {}
|
||||
for lib, names in component._get_all_imports().items():
|
||||
@ -69,10 +89,7 @@ def load_dynamic_serializer():
|
||||
if (
|
||||
not lib.startswith((".", "/"))
|
||||
and not lib.startswith("http")
|
||||
and all(
|
||||
formatted_lib_name != lib_in_window
|
||||
for lib_in_window in libs_in_window
|
||||
)
|
||||
and formatted_lib_name not in libs_in_window
|
||||
):
|
||||
imports[get_cdn_url(lib)] = names
|
||||
else:
|
||||
|
@ -117,5 +117,9 @@ class InvalidLifespanTaskType(ReflexError, TypeError):
|
||||
"""Raised when an invalid task type is registered as a lifespan task."""
|
||||
|
||||
|
||||
class DynamicComponentMissingLibrary(ReflexError, ValueError):
|
||||
"""Raised when a dynamic component is missing a library."""
|
||||
|
||||
|
||||
class SetUndefinedStateVarError(ReflexError, AttributeError):
|
||||
"""Raised when setting the value of a var without first declaring it."""
|
||||
|
Loading…
Reference in New Issue
Block a user