From 5c99656ca94e036ea93867b6111a33a14b651e44 Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Wed, 23 Oct 2024 18:12:22 -0700 Subject: [PATCH] upgrade to next js 15 and remove babel and enable turbo --- .../.templates/jinja/web/pages/_app.js.jinja2 | 4 ++-- .../jinja/web/utils/context.js.jinja2 | 2 +- .../radix_themes_color_mode_provider.js | 2 +- reflex/.templates/web/jsconfig.json | 3 ++- reflex/.templates/web/utils/state.js | 10 ++++---- reflex/app.py | 2 +- reflex/compiler/compiler.py | 6 ++--- reflex/components/base/bare.py | 4 +++- reflex/components/component.py | 24 ++++++++----------- reflex/components/core/banner.py | 4 ++-- reflex/components/core/client_side_routing.py | 2 +- reflex/components/core/clipboard.py | 2 +- reflex/components/core/cond.py | 2 +- reflex/components/core/upload.py | 8 +++---- reflex/components/datadisplay/dataeditor.py | 2 +- reflex/components/dynamic.py | 10 +++++--- reflex/components/el/elements/forms.py | 2 +- reflex/components/radix/themes/base.py | 4 ++-- reflex/components/sonner/toast.py | 2 +- reflex/constants/compiler.py | 4 ++-- reflex/constants/installer.py | 5 ++-- reflex/experimental/client_state.py | 2 +- reflex/style.py | 2 +- reflex/vars/base.py | 6 ++--- reflex/vars/number.py | 2 +- tests/units/components/core/test_banner.py | 14 +++++------ 26 files changed, 65 insertions(+), 65 deletions(-) diff --git a/reflex/.templates/jinja/web/pages/_app.js.jinja2 b/reflex/.templates/jinja/web/pages/_app.js.jinja2 index c893e19e2..21cfd921a 100644 --- a/reflex/.templates/jinja/web/pages/_app.js.jinja2 +++ b/reflex/.templates/jinja/web/pages/_app.js.jinja2 @@ -1,11 +1,11 @@ {% extends "web/pages/base_page.js.jinja2" %} {% block early_imports %} -import '/styles/styles.css' +import '$/styles/styles.css' {% endblock %} {% block declaration %} -import { EventLoopProvider, StateProvider, defaultColorMode } from "/utils/context.js"; +import { EventLoopProvider, StateProvider, defaultColorMode } from "$/utils/context.js"; import { ThemeProvider } from 'next-themes' {% for library_alias, library_path in window_libraries %} import * as {{library_alias}} from "{{library_path}}"; diff --git a/reflex/.templates/jinja/web/utils/context.js.jinja2 b/reflex/.templates/jinja/web/utils/context.js.jinja2 index 8faecd9d2..29328cca5 100644 --- a/reflex/.templates/jinja/web/utils/context.js.jinja2 +++ b/reflex/.templates/jinja/web/utils/context.js.jinja2 @@ -1,5 +1,5 @@ import { createContext, useContext, useMemo, useReducer, useState } from "react" -import { applyDelta, Event, hydrateClientStorage, useEventLoop, refs } from "/utils/state.js" +import { applyDelta, Event, hydrateClientStorage, useEventLoop, refs } from "$/utils/state.js" {% if initial_state %} export const initialState = {{ initial_state|json_dumps }} diff --git a/reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js b/reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js index 04df06059..1e6ea1a56 100644 --- a/reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +++ b/reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js @@ -5,7 +5,7 @@ import { defaultColorMode, isDevMode, lastCompiledTimeStamp -} from "/utils/context.js"; +} from "$/utils/context.js"; export default function RadixThemesColorModeProvider({ children }) { const { theme, resolvedTheme, setTheme } = useTheme(); diff --git a/reflex/.templates/web/jsconfig.json b/reflex/.templates/web/jsconfig.json index 3c8a3257f..3fcb35ba6 100644 --- a/reflex/.templates/web/jsconfig.json +++ b/reflex/.templates/web/jsconfig.json @@ -2,7 +2,8 @@ "compilerOptions": { "baseUrl": ".", "paths": { + "$/*": ["*"], "@/*": ["public/*"] } } -} \ No newline at end of file +} diff --git a/reflex/.templates/web/utils/state.js b/reflex/.templates/web/utils/state.js index 24092f235..5d62aab14 100644 --- a/reflex/.templates/web/utils/state.js +++ b/reflex/.templates/web/utils/state.js @@ -2,7 +2,7 @@ import axios from "axios"; import io from "socket.io-client"; import JSON5 from "json5"; -import env from "/env.json"; +import env from "$/env.json"; import Cookies from "universal-cookie"; import { useEffect, useRef, useState } from "react"; import Router, { useRouter } from "next/router"; @@ -13,9 +13,8 @@ import { state_name, exception_state_name, } from "utils/context.js"; -import debounce from "/utils/helpers/debounce"; -import throttle from "/utils/helpers/throttle"; -import * as Babel from "@babel/standalone"; +import debounce from "$/utils/helpers/debounce"; +import throttle from "$/utils/helpers/throttle"; // Endpoint URLs. const EVENTURL = env.EVENT; @@ -139,8 +138,7 @@ export const evalReactComponent = async (component) => { if (!window.React && window.__reflex) { window.React = window.__reflex.react; } - const output = Babel.transform(component, { presets: ["react"] }).code; - const encodedJs = encodeURIComponent(output); + const encodedJs = encodeURIComponent(component); const dataUri = "data:text/javascript;charset=utf-8," + encodedJs; const module = await eval(`import(dataUri)`); return module.default; diff --git a/reflex/app.py b/reflex/app.py index abf0b5d41..e524d40ad 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -679,7 +679,7 @@ class App(MiddlewareMixin, LifespanMixin, Base): for i, tags in imports.items() if i not in constants.PackageJson.DEPENDENCIES and i not in constants.PackageJson.DEV_DEPENDENCIES - and not any(i.startswith(prefix) for prefix in ["/", ".", "next/"]) + and not any(i.startswith(prefix) for prefix in ["/", "$/", ".", "next/"]) and i != "" and any(tag.install for tag in tags) } diff --git a/reflex/compiler/compiler.py b/reflex/compiler/compiler.py index 909299635..21b83af9f 100644 --- a/reflex/compiler/compiler.py +++ b/reflex/compiler/compiler.py @@ -67,8 +67,8 @@ def _compile_app(app_root: Component) -> str: 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"), + ("utils_context", f"$/{constants.Dirs.UTILS}/context"), + ("utils_state", f"$/{constants.Dirs.UTILS}/state"), ] return templates.APP_ROOT.render( @@ -228,7 +228,7 @@ def _compile_components( """ imports = { "react": [ImportVar(tag="memo")], - f"/{constants.Dirs.STATE_PATH}": [ImportVar(tag="E"), ImportVar(tag="isTrue")], + f"$/{constants.Dirs.STATE_PATH}": [ImportVar(tag="E"), ImportVar(tag="isTrue")], } component_renders = [] diff --git a/reflex/components/base/bare.py b/reflex/components/base/bare.py index d2c5a1f6c..c70b4c844 100644 --- a/reflex/components/base/bare.py +++ b/reflex/components/base/bare.py @@ -62,7 +62,9 @@ class Bare(Component): """ imports = super()._get_all_imports() if isinstance(self.contents, LiteralComponentVar): - imports |= self.contents._var_value._get_all_imports() + var_data = self.contents._get_all_var_data() + if var_data: + imports |= {k: list(v) for k, v in var_data.imports} return imports def _get_all_dynamic_imports(self) -> set[str]: diff --git a/reflex/components/component.py b/reflex/components/component.py index f85fb8ee4..7407080ef 100644 --- a/reflex/components/component.py +++ b/reflex/components/component.py @@ -1314,7 +1314,9 @@ class Component(BaseComponent, ABC): if self._get_ref_hook(): # Handle hooks needed for attaching react refs to DOM nodes. _imports.setdefault("react", set()).add(ImportVar(tag="useRef")) - _imports.setdefault(f"/{Dirs.STATE_PATH}", set()).add(ImportVar(tag="refs")) + _imports.setdefault(f"$/{Dirs.STATE_PATH}", set()).add( + ImportVar(tag="refs") + ) if self._get_mount_lifecycle_hook(): # Handle hooks for `on_mount` / `on_unmount`. @@ -1671,7 +1673,7 @@ class CustomComponent(Component): """A custom user-defined component.""" # Use the components library. - library = f"/{Dirs.COMPONENTS_PATH}" + library = f"$/{Dirs.COMPONENTS_PATH}" # The function that creates the component. component_fn: Callable[..., Component] = Component.create @@ -2511,18 +2513,12 @@ class LiteralComponentVar(CachedVarOperation, LiteralVar, ComponentVar): VarData( imports=self._var_value._get_all_imports(), ), - *( - [ - VarData( - imports={ - "react": [ - ImportVar(tag="Fragment"), - ], - } - ) - ] - if not self._var_value.tag - else [] + VarData( + imports={ + "react": [ + ImportVar(tag="Fragment"), + ], + } ), ) diff --git a/reflex/components/core/banner.py b/reflex/components/core/banner.py index 29897cffa..8a37b0bf7 100644 --- a/reflex/components/core/banner.py +++ b/reflex/components/core/banner.py @@ -66,8 +66,8 @@ class WebsocketTargetURL(Var): _js_expr="getBackendURL(env.EVENT).href", _var_data=VarData( imports={ - "/env.json": [ImportVar(tag="env", is_default=True)], - f"/{Dirs.STATE_PATH}": [ImportVar(tag="getBackendURL")], + "$/env.json": [ImportVar(tag="env", is_default=True)], + f"$/{Dirs.STATE_PATH}": [ImportVar(tag="getBackendURL")], }, ), _var_type=WebsocketTargetURL, diff --git a/reflex/components/core/client_side_routing.py b/reflex/components/core/client_side_routing.py index efa622f81..342c69632 100644 --- a/reflex/components/core/client_side_routing.py +++ b/reflex/components/core/client_side_routing.py @@ -21,7 +21,7 @@ route_not_found: Var = Var(_js_expr=constants.ROUTE_NOT_FOUND) class ClientSideRouting(Component): """The client-side routing component.""" - library = "/utils/client_side_routing" + library = "$/utils/client_side_routing" tag = "useClientSideRouting" def add_hooks(self) -> list[str]: diff --git a/reflex/components/core/clipboard.py b/reflex/components/core/clipboard.py index 88aa2d145..cce0af4a7 100644 --- a/reflex/components/core/clipboard.py +++ b/reflex/components/core/clipboard.py @@ -67,7 +67,7 @@ class Clipboard(Fragment): The import dict for the component. """ return { - "/utils/helpers/paste.js": ImportVar( + "$/utils/helpers/paste.js": ImportVar( tag="usePasteHandler", is_default=True ), } diff --git a/reflex/components/core/cond.py b/reflex/components/core/cond.py index 1590875d3..e0c47f0fe 100644 --- a/reflex/components/core/cond.py +++ b/reflex/components/core/cond.py @@ -15,7 +15,7 @@ from reflex.vars.base import LiteralVar, Var from reflex.vars.number import ternary_operation _IS_TRUE_IMPORT: ImportDict = { - f"/{Dirs.STATE_PATH}": [ImportVar(tag="isTrue")], + f"$/{Dirs.STATE_PATH}": [ImportVar(tag="isTrue")], } diff --git a/reflex/components/core/upload.py b/reflex/components/core/upload.py index 718e266b8..787cca9d0 100644 --- a/reflex/components/core/upload.py +++ b/reflex/components/core/upload.py @@ -36,7 +36,7 @@ DEFAULT_UPLOAD_ID: str = "default" upload_files_context_var_data: VarData = VarData( imports={ "react": "useContext", - f"/{Dirs.CONTEXTS_PATH}": "UploadFilesContext", + f"$/{Dirs.CONTEXTS_PATH}": "UploadFilesContext", }, hooks={ "const [filesById, setFilesById] = useContext(UploadFilesContext);": None, @@ -141,8 +141,8 @@ uploaded_files_url_prefix = Var( _js_expr="getBackendURL(env.UPLOAD)", _var_data=VarData( imports={ - f"/{Dirs.STATE_PATH}": "getBackendURL", - "/env.json": ImportVar(tag="env", is_default=True), + f"$/{Dirs.STATE_PATH}": "getBackendURL", + "$/env.json": ImportVar(tag="env", is_default=True), } ), ).to(str) @@ -177,7 +177,7 @@ def _on_drop_spec(files: Var) -> Tuple[Var[Any]]: class UploadFilesProvider(Component): """AppWrap component that provides a dict of selected files by ID via useContext.""" - library = f"/{Dirs.CONTEXTS_PATH}" + library = f"$/{Dirs.CONTEXTS_PATH}" tag = "UploadFilesProvider" diff --git a/reflex/components/datadisplay/dataeditor.py b/reflex/components/datadisplay/dataeditor.py index b9bd4cebf..1caf053b5 100644 --- a/reflex/components/datadisplay/dataeditor.py +++ b/reflex/components/datadisplay/dataeditor.py @@ -344,7 +344,7 @@ class DataEditor(NoSSRComponent): return { "": f"{format.format_library_name(self.library)}/dist/index.css", self.library: "GridCellKind", - "/utils/helpers/dataeditor.js": ImportVar( + "$/utils/helpers/dataeditor.js": ImportVar( tag="formatDataEditorCells", is_default=False, install=False ), } diff --git a/reflex/components/dynamic.py b/reflex/components/dynamic.py index 9c498fb61..a133db5a1 100644 --- a/reflex/components/dynamic.py +++ b/reflex/components/dynamic.py @@ -63,6 +63,9 @@ def load_dynamic_serializer(): """ # Causes a circular import, so we import here. from reflex.compiler import templates, utils + from reflex.components.base.bare import Bare + + component = Bare.create(Var.create(component)) rendered_components = {} # Include dynamic imports in the shared component. @@ -127,14 +130,15 @@ def load_dynamic_serializer(): module_code_lines[ix] = line.replace( "export function", "export default function", 1 ) + line_stripped = line.strip() + if line_stripped.startswith("{") and line_stripped.endswith("}"): + module_code_lines[ix] = line_stripped[1:-1] module_code_lines.insert(0, "const React = window.__reflex.react;") return "\n".join( [ "//__reflex_evaluate", - "/** @jsx jsx */", - "const { jsx } = window.__reflex['@emotion/react']", *module_code_lines, ] ) @@ -157,7 +161,7 @@ def load_dynamic_serializer(): merge_var_data=VarData.merge( VarData( imports={ - f"/{constants.Dirs.STATE_PATH}": [ + f"$/{constants.Dirs.STATE_PATH}": [ imports.ImportVar(tag="evalReactComponent"), ], "react": [ diff --git a/reflex/components/el/elements/forms.py b/reflex/components/el/elements/forms.py index a343991d5..084aa8f8e 100644 --- a/reflex/components/el/elements/forms.py +++ b/reflex/components/el/elements/forms.py @@ -187,7 +187,7 @@ class Form(BaseHTML): """ return { "react": "useCallback", - f"/{Dirs.STATE_PATH}": ["getRefValue", "getRefValues"], + f"$/{Dirs.STATE_PATH}": ["getRefValue", "getRefValues"], } def add_hooks(self) -> list[str]: diff --git a/reflex/components/radix/themes/base.py b/reflex/components/radix/themes/base.py index e41c5e7b0..acca1dce8 100644 --- a/reflex/components/radix/themes/base.py +++ b/reflex/components/radix/themes/base.py @@ -221,7 +221,7 @@ class Theme(RadixThemesComponent): The import dict. """ _imports: ImportDict = { - "/utils/theme.js": [ImportVar(tag="theme", is_default=True)], + "$/utils/theme.js": [ImportVar(tag="theme", is_default=True)], } if get_config().tailwind is None: # When tailwind is disabled, import the radix-ui styles directly because they will @@ -265,7 +265,7 @@ class ThemePanel(RadixThemesComponent): class RadixThemesColorModeProvider(Component): """Next-themes integration for radix themes components.""" - library = "/components/reflex/radix_themes_color_mode_provider.js" + library = "$/components/reflex/radix_themes_color_mode_provider.js" tag = "RadixThemesColorModeProvider" is_default = True diff --git a/reflex/components/sonner/toast.py b/reflex/components/sonner/toast.py index 02c320ac6..65f1157d3 100644 --- a/reflex/components/sonner/toast.py +++ b/reflex/components/sonner/toast.py @@ -251,7 +251,7 @@ class Toaster(Component): _js_expr=f"{toast_ref} = toast", _var_data=VarData( imports={ - "/utils/state": [ImportVar(tag="refs")], + "$/utils/state": [ImportVar(tag="refs")], self.library: [ImportVar(tag="toast", install=False)], } ), diff --git a/reflex/constants/compiler.py b/reflex/constants/compiler.py index 318a93783..b7ffef161 100644 --- a/reflex/constants/compiler.py +++ b/reflex/constants/compiler.py @@ -114,8 +114,8 @@ class Imports(SimpleNamespace): EVENTS = { "react": [ImportVar(tag="useContext")], - f"/{Dirs.CONTEXTS_PATH}": [ImportVar(tag="EventLoopContext")], - f"/{Dirs.STATE_PATH}": [ImportVar(tag=CompileVars.TO_EVENT)], + f"$/{Dirs.CONTEXTS_PATH}": [ImportVar(tag="EventLoopContext")], + f"$/{Dirs.STATE_PATH}": [ImportVar(tag=CompileVars.TO_EVENT)], } diff --git a/reflex/constants/installer.py b/reflex/constants/installer.py index 766dcf5be..ae7105506 100644 --- a/reflex/constants/installer.py +++ b/reflex/constants/installer.py @@ -165,7 +165,7 @@ class PackageJson(SimpleNamespace): class Commands(SimpleNamespace): """The commands to define in package.json.""" - DEV = "next dev" + DEV = "next dev --turbo" EXPORT = "next build" EXPORT_SITEMAP = "next build && next-sitemap" PROD = "next start" @@ -173,11 +173,10 @@ class PackageJson(SimpleNamespace): PATH = "package.json" DEPENDENCIES = { - "@babel/standalone": "7.25.8", "@emotion/react": "11.13.3", "axios": "1.7.7", "json5": "2.2.3", - "next": "14.2.15", + "next": "15.0.1", "next-sitemap": "4.2.3", "next-themes": "0.3.0", "react": "18.3.1", diff --git a/reflex/experimental/client_state.py b/reflex/experimental/client_state.py index c7b2260a1..698829d33 100644 --- a/reflex/experimental/client_state.py +++ b/reflex/experimental/client_state.py @@ -21,7 +21,7 @@ NoValue = object() _refs_import = { - f"/{constants.Dirs.STATE_PATH}": [ImportVar(tag="refs")], + f"$/{constants.Dirs.STATE_PATH}": [ImportVar(tag="refs")], } diff --git a/reflex/style.py b/reflex/style.py index 8e24e9b6b..f0ee8c6a7 100644 --- a/reflex/style.py +++ b/reflex/style.py @@ -23,7 +23,7 @@ LiteralColorMode = Literal["system", "light", "dark"] # Reference the global ColorModeContext color_mode_imports = { - f"/{constants.Dirs.CONTEXTS_PATH}": [ImportVar(tag="ColorModeContext")], + f"$/{constants.Dirs.CONTEXTS_PATH}": [ImportVar(tag="ColorModeContext")], "react": [ImportVar(tag="useContext")], } diff --git a/reflex/vars/base.py b/reflex/vars/base.py index 6df8eec6f..2007bc091 100644 --- a/reflex/vars/base.py +++ b/reflex/vars/base.py @@ -217,7 +217,7 @@ class VarData: ): None }, imports={ - f"/{constants.Dirs.CONTEXTS_PATH}": [ImportVar(tag="StateContexts")], + f"$/{constants.Dirs.CONTEXTS_PATH}": [ImportVar(tag="StateContexts")], "react": [ImportVar(tag="useContext")], }, ) @@ -956,7 +956,7 @@ class Var(Generic[VAR_TYPE]): _js_expr="refs", _var_data=VarData( imports={ - f"/{constants.Dirs.STATE_PATH}": [imports.ImportVar(tag="refs")] + f"$/{constants.Dirs.STATE_PATH}": [imports.ImportVar(tag="refs")] } ), ).to(ObjectVar, Dict[str, str]) @@ -2530,7 +2530,7 @@ def get_uuid_string_var() -> Var: unique_uuid_var = get_unique_variable_name() unique_uuid_var_data = VarData( imports={ - f"/{constants.Dirs.STATE_PATH}": {ImportVar(tag="generateUUID")}, # type: ignore + f"$/{constants.Dirs.STATE_PATH}": {ImportVar(tag="generateUUID")}, # type: ignore "react": "useMemo", }, hooks={f"const {unique_uuid_var} = useMemo(generateUUID, [])": None}, diff --git a/reflex/vars/number.py b/reflex/vars/number.py index 77c728d13..e403e63e4 100644 --- a/reflex/vars/number.py +++ b/reflex/vars/number.py @@ -1090,7 +1090,7 @@ boolean_types = Union[BooleanVar, bool] _IS_TRUE_IMPORT: ImportDict = { - f"/{Dirs.STATE_PATH}": [ImportVar(tag="isTrue")], + f"$/{Dirs.STATE_PATH}": [ImportVar(tag="isTrue")], } diff --git a/tests/units/components/core/test_banner.py b/tests/units/components/core/test_banner.py index 02b030902..7add913ea 100644 --- a/tests/units/components/core/test_banner.py +++ b/tests/units/components/core/test_banner.py @@ -12,7 +12,7 @@ def test_websocket_target_url(): var_data = url._get_all_var_data() assert var_data is not None assert sorted(tuple((key for key, _ in var_data.imports))) == sorted( - ("/utils/state", "/env.json") + ("$/utils/state", "$/env.json") ) @@ -22,10 +22,10 @@ def test_connection_banner(): assert sorted(tuple(_imports)) == sorted( ( "react", - "/utils/context", - "/utils/state", + "$/utils/context", + "$/utils/state", "@radix-ui/themes@^3.0.0", - "/env.json", + "$/env.json", ) ) @@ -40,10 +40,10 @@ def test_connection_modal(): assert sorted(tuple(_imports)) == sorted( ( "react", - "/utils/context", - "/utils/state", + "$/utils/context", + "$/utils/state", "@radix-ui/themes@^3.0.0", - "/env.json", + "$/env.json", ) )