Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minify state names #3728

Open
wants to merge 38 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
673c488
wip minified state names
benedikt-bartscher May 4, 2024
0c406f4
cleanup
benedikt-bartscher Jul 24, 2024
1b0577a
all _state_names should be classvars
benedikt-bartscher Jul 24, 2024
bae98e8
fix hardcoded event handlers and states
benedikt-bartscher Jul 25, 2024
8fc8fd9
fix state name init for substates, thanks @masenf
benedikt-bartscher Jul 25, 2024
51aef9f
enable minified state names by default in prod
benedikt-bartscher Jul 25, 2024
7bf15b4
add simple test that minified state names are unique
benedikt-bartscher Jul 25, 2024
e9cedd2
fix default state names
benedikt-bartscher Jul 27, 2024
7287c3a
fix typo
benedikt-bartscher Jul 27, 2024
215a834
wip minified state integration test
benedikt-bartscher Jul 27, 2024
dadfb56
wip: more dynamic jinja contexts, tests for minification
benedikt-bartscher Jul 30, 2024
4e76e4d
fix type ignore comment
benedikt-bartscher Aug 4, 2024
79fc109
move state.js to jinja, related to #3738
benedikt-bartscher Aug 4, 2024
c26d626
Revert "move state.js to jinja, related to #3738"
benedikt-bartscher Aug 5, 2024
f163d41
pass constants via js consts to state.js
benedikt-bartscher Aug 5, 2024
4bbd988
test_minified_states: remove skip -- things seem to be working as-is
masenf Oct 8, 2024
6eb808c
state.js: more reliable isStateful detection
masenf Oct 8, 2024
db2b5b0
AppHarness: handle `get_state_name` for minified names
masenf Oct 8, 2024
d326047
implement default_factory for EnvVar, improve env_var typing
benedikt-bartscher Nov 1, 2024
4116ab9
do not set appharness env twice, already done in AppHarnessProd
benedikt-bartscher Nov 5, 2024
84c14a1
cleanup conflicts
benedikt-bartscher Nov 5, 2024
bcd0cf8
Merge remote-tracking branch 'upstream/main' into minify-state-names-v2
benedikt-bartscher Nov 5, 2024
24caf5f
cleanup unnecessary or False
benedikt-bartscher Nov 6, 2024
46fefcf
Merge remote-tracking branch 'upstream/main' into minify-state-names-v2
benedikt-bartscher Nov 6, 2024
f94328f
delete unused function, add cleanup fixture for test_is_prod_mode
benedikt-bartscher Nov 6, 2024
6ce9471
set env mode before importing modules that contain rx.State subclasses
benedikt-bartscher Nov 6, 2024
74c336f
forgot ruffing
benedikt-bartscher Nov 7, 2024
2e12feb
darglinting it
benedikt-bartscher Nov 8, 2024
1ef54ec
Merge remote-tracking branch 'upstream/main' into minify-state-names-v2
benedikt-bartscher Nov 8, 2024
3dd6e9c
Merge remote-tracking branch 'upstream/main' into minify-state-names-v2
benedikt-bartscher Nov 12, 2024
a639f52
add typing to function vars (#4372)
adhami3310 Nov 13, 2024
a154a7d
Add template name to reflex init success msg (#4349)
ElijahAhianyo Nov 13, 2024
1e45a8e
Update bug_report.md (#4382)
Alek99 Nov 14, 2024
5840c0a
Merge remote-tracking branch 'upstream/main' into minify-state-names-v2
benedikt-bartscher Nov 20, 2024
0be2c3e
fix: properly cleanup env vars with pytest fixtures
benedikt-bartscher Nov 21, 2024
d8def13
Merge remote-tracking branch 'upstream/main' into minify-state-names-v2
benedikt-bartscher Nov 22, 2024
0262143
prevent env api breaking change
benedikt-bartscher Nov 22, 2024
5c9839e
Merge remote-tracking branch 'upstream/main' into minify-state-names-v2
benedikt-bartscher Nov 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions reflex/.templates/jinja/web/utils/context.js.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export const clientStorage = {{ client_storage|json_dumps }}
export const clientStorage = {}
{% endif %}

export const main_state_name = "{{const.main_state_name}}"
benedikt-bartscher marked this conversation as resolved.
Show resolved Hide resolved
export const update_vars_internal = "{{const.update_vars_internal}}"
{% if state_name %}
export const state_name = "{{state_name}}"

Expand Down
8 changes: 5 additions & 3 deletions reflex/.templates/web/utils/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
onLoadInternalEvent,
state_name,
exception_state_name,
main_state_name,
update_vars_internal,
} from "$/utils/context.js";
import debounce from "$/utils/helpers/debounce";
import throttle from "$/utils/helpers/throttle";
Expand Down Expand Up @@ -117,7 +119,7 @@ export const isStateful = () => {
if (event_queue.length === 0) {
return false;
}
return event_queue.some((event) => event.name.startsWith("reflex___state"));
return event_queue.some(event => event.name.startsWith(main_state_name));
};

/**
Expand Down Expand Up @@ -822,7 +824,7 @@ export const useEventLoop = (
const vars = {};
vars[storage_to_state_map[e.key]] = e.newValue;
const event = Event(
`${state_name}.reflex___state____update_vars_internal_state.update_vars_internal`,
`${state_name}.${update_vars_internal}`,
{ vars: vars }
);
addEvents([event], e);
Expand All @@ -836,7 +838,7 @@ export const useEventLoop = (
// Route after the initial page hydration.
useEffect(() => {
const change_start = () => {
const main_state_dispatch = dispatch["reflex___state____state"];
const main_state_dispatch = dispatch[main_state_name];
if (main_state_dispatch !== undefined) {
main_state_dispatch({ is_hydrated: false });
}
Expand Down
22 changes: 11 additions & 11 deletions reflex/compiler/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def _compile_document_root(root: Component) -> str:
Returns:
The compiled document root.
"""
return templates.DOCUMENT_ROOT.render(
return templates.document_root().render(
imports=utils.compile_imports(root._get_all_imports()),
document=root.render(),
)
Expand Down Expand Up @@ -72,7 +72,7 @@ def _compile_app(app_root: Component) -> str:
("utils_state", f"$/{constants.Dirs.UTILS}/state"),
]

return templates.APP_ROOT.render(
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()},
Expand All @@ -90,7 +90,7 @@ def _compile_theme(theme: str) -> str:
Returns:
The compiled theme.
"""
return templates.THEME.render(theme=theme)
return templates.theme().render(theme=theme)


def _compile_contexts(state: Optional[Type[BaseState]], theme: Component | None) -> str:
Expand All @@ -109,7 +109,7 @@ def _compile_contexts(state: Optional[Type[BaseState]], theme: Component | None)

last_compiled_time = str(datetime.now())
return (
templates.CONTEXT.render(
templates.context().render(
initial_state=utils.compile_state(state),
state_name=state.get_name(),
client_storage=utils.compile_client_storage(state),
Expand All @@ -118,7 +118,7 @@ def _compile_contexts(state: Optional[Type[BaseState]], theme: Component | None)
default_color_mode=appearance,
)
if state
else templates.CONTEXT.render(
else templates.context().render(
is_dev_mode=not is_prod_mode(),
default_color_mode=appearance,
last_compiled_time=last_compiled_time,
Expand All @@ -145,7 +145,7 @@ def _compile_page(
# Compile the code to render the component.
kwargs = {"state_name": state.get_name()} if state is not None else {}

return templates.PAGE.render(
return templates.page().render(
imports=imports,
dynamic_imports=component._get_all_dynamic_imports(),
custom_codes=component._get_all_custom_code(),
Expand Down Expand Up @@ -201,7 +201,7 @@ def _compile_root_stylesheet(stylesheets: list[str]) -> str:
)
stylesheet = f"../{constants.Dirs.PUBLIC}/{stylesheet.strip('/')}"
sheets.append(stylesheet) if stylesheet not in sheets else None
return templates.STYLE.render(stylesheets=sheets)
return templates.style().render(stylesheets=sheets)


def _compile_component(component: Component | StatefulComponent) -> str:
Expand All @@ -213,7 +213,7 @@ def _compile_component(component: Component | StatefulComponent) -> str:
Returns:
The compiled component.
"""
return templates.COMPONENT.render(component=component)
return templates.component().render(component=component)


def _compile_components(
Expand Down Expand Up @@ -241,7 +241,7 @@ def _compile_components(

# Compile the components page.
return (
templates.COMPONENTS.render(
templates.components().render(
imports=utils.compile_imports(imports),
components=component_renders,
),
Expand Down Expand Up @@ -319,7 +319,7 @@ def get_shared_components_recursive(component: BaseComponent):
f"$/{constants.Dirs.UTILS}/{constants.PageNames.STATEFUL_COMPONENTS}", None
)

return templates.STATEFUL_COMPONENTS.render(
return templates.stateful_components().render(
imports=utils.compile_imports(all_imports),
memoized_code="\n".join(rendered_components),
)
Expand All @@ -336,7 +336,7 @@ def _compile_tailwind(
Returns:
The compiled Tailwind config.
"""
return templates.TAILWIND_CONFIG.render(
return templates.tailwind_config().render(
**config,
)

Expand Down
205 changes: 162 additions & 43 deletions reflex/compiler/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ class ReflexJinjaEnvironment(Environment):

def __init__(self) -> None:
"""Set default environment."""
from reflex.state import (
FrontendEventExceptionState,
OnLoadInternalState,
State,
UpdateVarsInternalState,
)

extensions = ["jinja2.ext.debug"]
super().__init__(
extensions=extensions,
Expand Down Expand Up @@ -42,9 +49,10 @@ def __init__(self) -> None:
"set_color_mode": constants.ColorMode.SET,
"use_color_mode": constants.ColorMode.USE,
"hydrate": constants.CompileVars.HYDRATE,
"on_load_internal": constants.CompileVars.ON_LOAD_INTERNAL,
"update_vars_internal": constants.CompileVars.UPDATE_VARS_INTERNAL,
"frontend_exception_state": constants.CompileVars.FRONTEND_EXCEPTION_STATE_FULL,
"main_state_name": State.get_name(),
"on_load_internal": f"{OnLoadInternalState.get_name()}.on_load_internal",
"update_vars_internal": f"{UpdateVarsInternalState.get_name()}.update_vars_internal",
"frontend_exception_state": FrontendEventExceptionState.get_full_name(),
}


Expand All @@ -60,61 +68,172 @@ def get_template(name: str) -> Template:
return ReflexJinjaEnvironment().get_template(name=name)


# Template for the Reflex config file.
RXCONFIG = get_template("app/rxconfig.py.jinja2")
def rxconfig():
"""Template for the Reflex config file.

Returns:
Template: The template for the Reflex config file.
"""
return get_template("app/rxconfig.py.jinja2")


def document_root():
"""Code to render a NextJS Document root.

Returns:
Template: The template for the NextJS Document root.
"""
return get_template("web/pages/_document.js.jinja2")

# Code to render a NextJS Document root.
DOCUMENT_ROOT = get_template("web/pages/_document.js.jinja2")

# Code to render NextJS App root.
APP_ROOT = get_template("web/pages/_app.js.jinja2")
def app_root():
"""Code to render NextJS App root.

# Template for the theme file.
THEME = get_template("web/utils/theme.js.jinja2")
Returns:
Template: The template for the NextJS App root.
"""
return get_template("web/pages/_app.js.jinja2")

# Template for the context file.
CONTEXT = get_template("web/utils/context.js.jinja2")

# Template for Tailwind config.
TAILWIND_CONFIG = get_template("web/tailwind.config.js.jinja2")
def theme():
"""Template for the theme file.

# Template to render a component tag.
COMPONENT = get_template("web/pages/component.js.jinja2")
Returns:
Template: The template for the theme file.
"""
return get_template("web/utils/theme.js.jinja2")

# Code to render a single NextJS page.
PAGE = get_template("web/pages/index.js.jinja2")

# Code to render the custom components page.
COMPONENTS = get_template("web/pages/custom_component.js.jinja2")
def context():
"""Template for the context file.

# Code to render Component instances as part of StatefulComponent
STATEFUL_COMPONENT = get_template("web/pages/stateful_component.js.jinja2")
Returns:
Template: The template for the context file.
"""
return get_template("web/utils/context.js.jinja2")

# Code to render StatefulComponent to an external file to be shared
STATEFUL_COMPONENTS = get_template("web/pages/stateful_components.js.jinja2")

# Sitemap config file.
SITEMAP_CONFIG = "module.exports = {config}".format
def tailwind_config():
"""Template for Tailwind config.

# Code to render the root stylesheet.
STYLE = get_template("web/styles/styles.css.jinja2")
Returns:
Template: The template for the Tailwind config
"""
return get_template("web/tailwind.config.js.jinja2")

# Code that generate the package json file
PACKAGE_JSON = get_template("web/package.json.jinja2")

# Code that generate the pyproject.toml file for custom components.
CUSTOM_COMPONENTS_PYPROJECT_TOML = get_template(
"custom_components/pyproject.toml.jinja2"
)
def component():
"""Template to render a component tag.

# Code that generates the README file for custom components.
CUSTOM_COMPONENTS_README = get_template("custom_components/README.md.jinja2")
Returns:
Template: The template for the component tag.
"""
return get_template("web/pages/component.js.jinja2")

# Code that generates the source file for custom components.
CUSTOM_COMPONENTS_SOURCE = get_template("custom_components/src.py.jinja2")

# Code that generates the init file for custom components.
CUSTOM_COMPONENTS_INIT_FILE = get_template("custom_components/__init__.py.jinja2")
def page():
"""Code to render a single NextJS page.

Returns:
Template: The template for the NextJS page.
"""
return get_template("web/pages/index.js.jinja2")


def components():
"""Code to render the custom components page.

Returns:
Template: The template for the custom components page.
"""
return get_template("web/pages/custom_component.js.jinja2")


def stateful_component():
"""Code to render Component instances as part of StatefulComponent.

Returns:
Template: The template for the StatefulComponent.
"""
return get_template("web/pages/stateful_component.js.jinja2")


def stateful_components():
"""Code to render StatefulComponent to an external file to be shared.

Returns:
Template: The template for the StatefulComponent.
"""
return get_template("web/pages/stateful_components.js.jinja2")


# Code that generates the demo app main py file for testing custom components.
CUSTOM_COMPONENTS_DEMO_APP = get_template("custom_components/demo_app.py.jinja2")
def sitemap_config():
"""Sitemap config file.

Returns:
Template: The template for the sitemap config file.
"""
return "module.exports = {config}".format


def style():
"""Code to render the root stylesheet.

Returns:
Template: The template for the root stylesheet
"""
return get_template("web/styles/styles.css.jinja2")


def package_json():
"""Code that generate the package json file.

Returns:
Template: The template for the package json file
"""
return get_template("web/package.json.jinja2")


def custom_components_pyproject_toml():
"""Code that generate the pyproject.toml file for custom components.

Returns:
Template: The template for the pyproject.toml file
"""
return get_template("custom_components/pyproject.toml.jinja2")


def custom_components_readme():
"""Code that generates the README file for custom components.

Returns:
Template: The template for the README file
"""
return get_template("custom_components/README.md.jinja2")


def custom_components_source():
"""Code that generates the source file for custom components.

Returns:
Template: The template for the source file
"""
return get_template("custom_components/src.py.jinja2")


def custom_components_init():
"""Code that generates the init file for custom components.

Returns:
Template: The template for the init file
"""
return get_template("custom_components/__init__.py.jinja2")


def custom_components_demo_app():
"""Code that generates the demo app main py file for testing custom components.

Returns:
Template: The template for the demo app main py file
"""
return get_template("custom_components/demo_app.py.jinja2")
Loading
Loading