Skip to content
Open
Show file tree
Hide file tree
Changes from 82 commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
2656ee5
feat: Add explicit state ID minification for states
benedikt-bartscher Jan 24, 2026
1c5114d
drop uploaded_files, don't allow state_id for mixins
benedikt-bartscher Jan 24, 2026
62bf127
Update reflex/state.py
benedikt-bartscher Jan 24, 2026
0858c9e
ruffing
benedikt-bartscher Jan 24, 2026
be13be5
minify event names as well
benedikt-bartscher Jan 24, 2026
e53c76a
wip fixing minifed state names + add cli
benedikt-bartscher Jan 24, 2026
fc4c5e1
wip cli
benedikt-bartscher Jan 25, 2026
6d13bec
wtf prettier
benedikt-bartscher Jan 25, 2026
b2c3f58
Merge remote-tracking branch 'upstream' into explicit-event-id-minifi…
benedikt-bartscher Jan 27, 2026
f2f1ac7
Merge remote-tracking branch 'upstream' into explicit-event-id-minifi…
benedikt-bartscher Jan 28, 2026
db97e3a
update pyi_hashes
benedikt-bartscher Jan 28, 2026
6b4c5fa
unique per sibling
benedikt-bartscher Jan 28, 2026
a230be2
Merge remote-tracking branch 'upstream/main' into explicit-event-id-m…
benedikt-bartscher Feb 1, 2026
1647c1e
fix test state ids
benedikt-bartscher Feb 1, 2026
e375b7e
add best-effort mode for event ids
benedikt-bartscher Feb 1, 2026
a94c98b
minify json poc
benedikt-bartscher Feb 1, 2026
ee4c7f1
fix codespell
benedikt-bartscher Feb 1, 2026
bcc4b49
add support for dynamic event handlers, streamline event handler form…
benedikt-bartscher Feb 1, 2026
fc787e6
forgot to remove this state prefix
benedikt-bartscher Feb 1, 2026
5b6e124
more streamline with format event handler
benedikt-bartscher Feb 1, 2026
ae477ae
allow to enable/disable state and event ID minification independently…
benedikt-bartscher Feb 4, 2026
e13073b
fix: prevent parent-child minified name collision in substate resolution
benedikt-bartscher Feb 4, 2026
d669571
fix: consistent plural naming for state minification env vars
benedikt-bartscher Feb 4, 2026
ed085c0
make integration tests use our typed env helpers
benedikt-bartscher Feb 4, 2026
b2c2ff0
prefer assert isinstance over cast.
benedikt-bartscher Feb 4, 2026
8f44d49
drop old state_id parameter from BaseStateMeta
benedikt-bartscher Feb 4, 2026
cf7b614
fix: drop unused EVENT_ID_MARKER constant
benedikt-bartscher Feb 4, 2026
3074c84
fix: correctly count events in minification cli
benedikt-bartscher Feb 4, 2026
ca73b45
fix: adjust minify lookup cli for new minify.json, add tests
benedikt-bartscher Feb 6, 2026
d5f159c
fix: reflex minify validate - warn and exit 1 if missing entries
benedikt-bartscher Feb 6, 2026
f964c7a
fix: use get_event_handler in upload
benedikt-bartscher Feb 7, 2026
1aac145
Merge remote-tracking branch 'upstream' into explicit-event-id-minifi…
benedikt-bartscher Feb 12, 2026
019e6f3
fix: avoid assertion in runtime, prefer raising TypeError
benedikt-bartscher Feb 12, 2026
5f57707
Merge remote-tracking branch 'upstream/main' into explicit-event-id-m…
benedikt-bartscher Feb 13, 2026
dbb1fb6
Merge remote-tracking branch 'upstream/main' into explicit-event-id-m…
benedikt-bartscher Feb 14, 2026
e713b5b
Merge remote-tracking branch 'upstream/main' into explicit-event-id-m…
benedikt-bartscher Feb 24, 2026
e2ca73e
bump packaging upper-bound to <27 (#6102)
masenf Jan 27, 2026
9201f0e
Bump python-multipart in the uv group across 1 directory (#6103)
dependabot[bot] Jan 27, 2026
f2e4e5a
fix: Preserve event_actions from @rx.event decorator in mixin event h…
benedikt-bartscher Jan 27, 2026
e2e6d14
Fix socket reference shape mismatch in queueEvents (#6094)
Dadzemovic Jan 27, 2026
b132303
fix: Preserve object identity when pickling MutableProxy (#6097)
benedikt-bartscher Jan 28, 2026
413901b
fix: Copy ID even when it is a var. (#6105)
abulvenz Jan 29, 2026
8d9ed97
Origin/matthew collins nz/adddataeditorrowcheckboxvisible (#6082)
MatthewCollinsNZ Feb 12, 2026
29965cf
Catch all exceptions in health checks (#6089)
masenf Feb 12, 2026
73901cd
Run external servers with `sys.executable -m` (#6095)
masenf Feb 12, 2026
3934bc4
Use homogenous tuple annotation in BaseStateMeta.__new__ (#6096)
masenf Feb 12, 2026
087c024
adding row selection mode (#6090)
MatthewCollinsNZ Feb 12, 2026
0580d84
use get_event_handler in upload, cherry-pick from #6100 (#6130)
benedikt-bartscher Feb 12, 2026
7405808
Data editor search props (#6113)
MatthewCollinsNZ Feb 12, 2026
7c0b6c2
Bump pillow from 12.1.0 to 12.1.1 in the uv group across 1 directory …
dependabot[bot] Feb 12, 2026
64da061
Allow granian log level to be set (#6131)
masenf Feb 12, 2026
63121f6
cache get_type_hints for heavy init subclass stuff - improve import p…
benedikt-bartscher Feb 13, 2026
c8c2ab1
0828dev (#6136)
adhami3310 Feb 23, 2026
ca28a6e
Unlink broken symlinks in the assets folder (#6140)
masenf Mar 5, 2026
5cd8397
feat: add vite_allowed_hosts config option for Vite dev server (#6147)
milochen0418 Mar 6, 2026
129b904
fix: include frontend_path in sirv prod command for correct 404.html …
masenf Mar 6, 2026
b89c80b
fix: make disable_plugins accept Plugin types instead of strings (#6155)
masenf Mar 6, 2026
5716a9e
bump devcontainer to python:3.14-trixie (#6158)
masenf Mar 6, 2026
9bd6ad1
Merge branch 'main', remote-tracking branch 'upstream' into explicit-…
benedikt-bartscher Mar 12, 2026
e8b5724
fix: use actual parent class for sibling grouping in minify sync/vali…
benedikt-bartscher Mar 12, 2026
30bf7a3
Merge remote-tracking branch 'upstream/main' into explicit-event-id-m…
benedikt-bartscher Mar 23, 2026
43815c0
Merge remote-tracking branch 'upstream' into explicit-event-id-minifi…
benedikt-bartscher Mar 26, 2026
10434bd
Merge remote-tracking branch 'upstream/main' into explicit-event-id-m…
benedikt-bartscher Apr 25, 2026
9e73376
ruff format
benedikt-bartscher Apr 25, 2026
79b735d
pre-commit
benedikt-bartscher Apr 25, 2026
052beca
test adjustments
benedikt-bartscher Apr 25, 2026
1cc98a8
migrate minify to registry name resolver
benedikt-bartscher Apr 25, 2026
bd63210
pre-commit
benedikt-bartscher Apr 25, 2026
5ad6e3e
add support for dynamic states in minification
benedikt-bartscher Apr 25, 2026
66dcbe5
cleanup
benedikt-bartscher Apr 25, 2026
673243c
wip
benedikt-bartscher Apr 26, 2026
6cdf383
cleanup
benedikt-bartscher Apr 26, 2026
050727a
dry it up
benedikt-bartscher Apr 26, 2026
de1804a
dry up the tests
benedikt-bartscher Apr 26, 2026
c99b450
typing improvements and cleanup
benedikt-bartscher Apr 26, 2026
05fde77
cleanup
benedikt-bartscher Apr 26, 2026
9b57ec1
wip
benedikt-bartscher Apr 26, 2026
fc0ba15
Merge remote-tracking branch 'upstream/main' into explicit-event-id-m…
benedikt-bartscher Apr 28, 2026
b0983ed
Merge remote-tracking branch 'upstream/main' into explicit-event-id-m…
benedikt-bartscher May 6, 2026
bc3890a
try to improve benchmark
benedikt-bartscher May 6, 2026
aa32843
cache event handler names
benedikt-bartscher May 6, 2026
f83afad
Merge remote-tracking branch 'upstream/main' into explicit-event-id-m…
benedikt-bartscher Jul 9, 2026
228b8ed
fix: record parent path in minify.json state entries so orphaned ids …
benedikt-bartscher Jul 9, 2026
af4219f
fix codespell
benedikt-bartscher Jul 9, 2026
d378a59
Merge remote-tracking branch 'upstream/main' into explicit-event-id-m…
benedikt-bartscher Jul 17, 2026
c5cceb6
fix: prevent state definition before minify is active
benedikt-bartscher Jul 20, 2026
1bafa2d
fix ruff
benedikt-bartscher Jul 20, 2026
c3e0f1c
greptile
benedikt-bartscher Jul 20, 2026
44fefa1
cleanup
benedikt-bartscher Jul 20, 2026
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ node_modules
package-lock.json
*.pyi
.pre-commit-config.yaml
uploaded_files/*
.claude/.worktrees
.claude/settings.local.json
CLAUDE.local.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import {
initialState,
onLoadInternalEvent,
state_name,
exception_state_name,
handle_frontend_exception,
main_state_name,
update_vars_internal,
} from "$/utils/context";
import debounce from "$/utils/helpers/debounce";
import throttle from "$/utils/helpers/throttle";
Expand Down Expand Up @@ -142,7 +144,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 @@ -1007,7 +1009,7 @@ export const useEventLoop = (

window.onerror = function (msg, url, lineNo, columnNo, error) {
addEvents([
ReflexEvent(`${exception_state_name}.handle_frontend_exception`, {
ReflexEvent(handle_frontend_exception, {
info: error.name + ": " + error.message + "\n" + error.stack,
component_stack: "",
}),
Expand All @@ -1019,7 +1021,7 @@ export const useEventLoop = (
//https://github.com/mknichel/javascript-errors?tab=readme-ov-file#promise-rejection-events
window.onunhandledrejection = function (event) {
addEvents([
ReflexEvent(`${exception_state_name}.handle_frontend_exception`, {
ReflexEvent(handle_frontend_exception, {
info:
event.reason?.name +
": " +
Expand Down Expand Up @@ -1084,10 +1086,9 @@ export const useEventLoop = (
if (storage_to_state_map[e.key]) {
const vars = {};
vars[storage_to_state_map[e.key]] = e.newValue;
const event = ReflexEvent(
`${state_name}.reflex___state____update_vars_internal_state.update_vars_internal`,
{ vars: vars },
);
const event = ReflexEvent(update_vars_internal, {
vars: vars,
});
addEvents([event], e);
}
};
Expand Down Expand Up @@ -1122,7 +1123,7 @@ export const useEventLoop = (
}

// Equivalent to routeChangeStart - runs when navigation begins
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_rx_state_: false });
}
Expand Down
35 changes: 30 additions & 5 deletions packages/reflex-base/src/reflex_base/compiler/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from reflex_base import constants
from reflex_base.constants import Hooks
from reflex_base.utils import memo_paths
from reflex_base.utils.format import format_state_name, json_dumps
from reflex_base.utils.format import format_event_handler, format_state_name, json_dumps
from reflex_base.vars.base import VarData

if TYPE_CHECKING:
Expand Down Expand Up @@ -288,6 +288,23 @@ def context_template(
Returns:
Rendered context file content as string.
"""
# Import state classes to get dynamic names (supports minification)
from reflex.state import (
FrontendEventExceptionState,
OnLoadInternalState,
State,
UpdateVarsInternalState,
)

main_state_name = State.get_name()
on_load_internal = format_event_handler(OnLoadInternalState.on_load_internal)
update_vars_internal = format_event_handler(
UpdateVarsInternalState.update_vars_internal
)
handle_frontend_exception = format_event_handler(
FrontendEventExceptionState.handle_frontend_exception
)

initial_state = initial_state or {}
state_contexts_str = "".join([
f"{format_state_name(state_name)}: createContext(null),"
Expand All @@ -298,7 +315,11 @@ def context_template(
rf"""
export const state_name = "{state_name}"

export const exception_state_name = "{constants.CompileVars.FRONTEND_EXCEPTION_STATE_FULL}"
export const main_state_name = "{main_state_name}"

export const update_vars_internal = "{update_vars_internal}"

export const handle_frontend_exception = "{handle_frontend_exception}"

// These events are triggered on initial load and each page navigation.
export const onLoadInternalEvent = () => {{
Expand All @@ -310,15 +331,15 @@ def context_template(
if (client_storage_vars && Object.keys(client_storage_vars).length !== 0) {{
internal_events.push(
ReflexEvent(
'{state_name}.{constants.CompileVars.UPDATE_VARS_INTERNAL}',
'{update_vars_internal}',
{{vars: client_storage_vars}},
),
);
}}

// `on_load_internal` triggers the correct on_load event(s) for the current page.
// If the page does not define any on_load event, this will just set `is_hydrated = true`.
internal_events.push(ReflexEvent('{state_name}.{constants.CompileVars.ON_LOAD_INTERNAL}'));
internal_events.push(ReflexEvent('{on_load_internal}'));

return internal_events;
}}
Expand All @@ -333,7 +354,11 @@ def context_template(
else """
export const state_name = undefined

export const exception_state_name = undefined
export const main_state_name = undefined

export const update_vars_internal = undefined

export const handle_frontend_exception = undefined

export const onLoadInternalEvent = () => []

Expand Down
12 changes: 0 additions & 12 deletions packages/reflex-base/src/reflex_base/constants/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,6 @@ class CompileVars(SimpleNamespace):
CONNECT_ERROR = "connectErrors"
# The name of the function for converting a dict to an event.
TO_EVENT = "ReflexEvent"
# The name of the internal on_load event.
ON_LOAD_INTERNAL = "reflex___state____on_load_internal_state.on_load_internal"
# The name of the internal event to update generic state vars.
UPDATE_VARS_INTERNAL = (
"reflex___state____update_vars_internal_state.update_vars_internal"
)
# The name of the frontend event exception state
FRONTEND_EXCEPTION_STATE = "reflex___state____frontend_event_exception_state"
# The full name of the frontend exception state
FRONTEND_EXCEPTION_STATE_FULL = (
f"reflex___state____state.{FRONTEND_EXCEPTION_STATE}"
)


class PageNames(SimpleNamespace):
Expand Down
3 changes: 3 additions & 0 deletions packages/reflex-base/src/reflex_base/constants/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
from enum import Enum
from types import SimpleNamespace

# The name of the setvar event handler.
SETVAR = "setvar"


class Endpoint(Enum):
"""Endpoints for the reflex backend API."""
Expand Down
13 changes: 13 additions & 0 deletions packages/reflex-base/src/reflex_base/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,13 @@ class PathExistsFlag:
ExistingPath = Annotated[Path, PathExistsFlag]


class MinifyMode(enum.Enum):
"""Mode for minification of state/event IDs."""

ENABLED = "enabled"
DISABLED = "disabled"


class PerformanceMode(enum.Enum):
"""Performance mode for the app."""

Expand Down Expand Up @@ -741,6 +748,12 @@ class EnvironmentVariables:
# How long to opportunistically hold the redis lock in milliseconds (must be less than the token expiration).
REFLEX_OPLOCK_HOLD_TIME_MS: EnvVar[int] = env_var(0)

# Whether to enable state ID minification (requires minify.json).
REFLEX_MINIFY_STATES: EnvVar[MinifyMode] = env_var(MinifyMode.DISABLED)

# Whether to enable event ID minification (requires minify.json).
REFLEX_MINIFY_EVENTS: EnvVar[MinifyMode] = env_var(MinifyMode.DISABLED)

# Extra plugins to append to the config's plugins list.
REFLEX_EXTRA_PLUGINS: EnvVar[list[type[Plugin]]] = env_var([])

Expand Down
21 changes: 21 additions & 0 deletions packages/reflex-base/src/reflex_base/event/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,26 @@ def __call__(self, *args: Any, **kwargs: Any) -> "EventSpec":
)


if TYPE_CHECKING:

def typing_event(fn: Callable[..., Any]) -> EventHandler:
"""Mark ``fn`` so pyright sees it as the ``EventHandler`` that
``BaseState.__init_subclass__`` will rewrite it into. No-op at runtime.

Args:
fn: The method to mark.

Returns:
``fn`` typed as :class:`EventHandler`.
"""
...

else:

def typing_event(fn: Callable[..., Any]) -> Callable[..., Any]: # noqa: D103
return fn


@dataclasses.dataclass(
init=True,
frozen=True,
Expand Down Expand Up @@ -3004,6 +3024,7 @@ def BaseState(self) -> "type[BaseState]": # noqa: N802

event = EventNamespace
event.event = event # pyright: ignore[reportAttributeAccessIssue]
event.typing_event = staticmethod(typing_event) # pyright: ignore[reportAttributeAccessIssue]
_this = sys.modules[__name__]
event.__path__ = _this.__path__ # pyright: ignore[reportAttributeAccessIssue]
event.__spec__ = _this.__spec__ # pyright: ignore[reportAttributeAccessIssue]
Expand Down
Loading
Loading