Ship the frontend runtime JavaScript as an installable npm package
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 35/100
- Tipo de issue
- Nueva funcionalidad
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- bun, javascript, python, react, vite
- Área
- backend, build-system, devtools, frontend
Línea de trabajo
Start by reading the pending-work checklist and the implementation branch claude/reflex-frontend-js-package-ockox9, then compare its install-flow changes with #7235 and #7451. Rebase the branch onto current main, open a PR, and review the breaking-change fragment and local-packages documentation. Done means the PR is ready and the release pipeline confirms the tarball is bundled in a pre-release wheel.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Problem
The JavaScript Reflex ships to every app (state.js, react-theme.js, upload.js, the helpers and components under utils/, style-reset.css, the vite plugins) lives in packages/reflex-base/src/reflex_base/.templates/web/ and is copied verbatim into each app's .web/ directory. That design has several costs:
- Compiler/runtime drift. Compiled output and the copied runtime are only guaranteed to match by wiping and re-initializing
.webon every Reflex version change, which also throws awaynode_modulesand lockfiles. - Untestable runtime. The shipped modules import per-app generated artifacts (
$/env.json,$/reflex.json,$/utils/context.js), so they cannot be loaded outside a compiled app, let alone unit-tested.state.jsimportingreflex.jsonis also one of the two causes of non-reproducible builds in #7562. - Dependency versions live in Python. react, react-dom, react-router, socket.io-client, universal-cookie and the build toolchain are maintained as
PackageJson.DEPENDENCIES/DEV_DEPENDENCIESconstants and pinned at the top level of the app'spackage.json; theREACT_VERSION/REACT_ROUTER_VERSIONenv vars are the only override.json5is used but never declared. - Path-coupled imports. Component packages and user custom code reference the runtime through
$/utils/...specifiers tied to the.weblayout.
Proposal
Ship the non-generated frontend runtime as a real npm package, @reflex-dev/reflex-base, at packages/reflex-base/src/reflex_base/frontend/, bundled inside the reflex-base wheel.
Packaging
- A stdlib-only hatch build hook packs a deterministic npm-format tarball into the wheel. The release build has no JS toolchain, and byte-stable tarballs keep the
file:integrity hashes in committedreflex.locklockfiles valid across rebuilds. The sdist keeps the JS source so wheels rebuild from it. - The package version derives from reflex-base's own version.
- A
verify-frontend-tgzrelease check asserts the wheel bundles exactly the right tarball and leaks neither source nornode_modules.
Install into .web
- Each run installs the package like any other dependency (
file:./<tarball>). Editable installs of reflex-base link the live source directory instead (link:for bun,file:for npm) so framework JS edits hot-reload without a reinstall. - The install flow writes the package entry itself and reconciles it: an unchanged entry keeps the frozen-lockfile install byte-for-byte; a superseded tarball frozen-installs first and is rewritten after; an unresolvable entry is rewritten up front. Legacy top-level framework pins are swept, superseded tarballs pruned, and the install cache keyed on the package version.
- A Reflex version change no longer wipes
.web:needs_reinit()narrows to missing-directory cases and a newrefresh_web_directory()overwrite-copies the remaining templates, deletes files owned by older versions and re-renders generated configs, keepingnode_modules, lockfiles and the project hash.
Runtime decoupling
- Shipped modules stop importing generated files. A
@reflex-dev/reflex-base/runtimeregistry is populated by the generatedutils/context.jsviaconfigureReflexRuntime()in its module body; the two module-scope reads of app config (EVENTURL, the embed-modelocationRefseed) become lazy. ColorModeContextmoves intoreact-theme.jsand the generated context re-exports it. Compiled components read env values throughgetEnv()instead of importingenv.json.
Compiler and imports
- Generated code and component import declarations reference the package by bare specifier (
@reflex-dev/reflex-base/state,.../react-theme,.../helpers/*,.../components/*,.../style-reset.css).constants.FrontendPackageis the single Python-side source of these specifiers, with a unit test asserting each resolves to a shipped file. - Back-compat for user code is three-layered:
merge_importsnormalizes legacy$/utils/...specifiers in Python import declarations, the generated vite config aliases them for user JS, and the app root keeps thewindow.__reflex["$/utils/state"]registry key for backend-evaluated dynamic components.Dirs.STATE_PATHandResetStylesheetremain as deprecated fallbacks.
Dependencies
- Runtime framework deps resolve transitively through the package manifest; the app-level toolchain is copied from its
devDependencies;shikiand@glideapps/glide-data-gridare optional peer deps deduped to the app root. - User version control moves to
overridesinreflex.lock/package.json.REACT_VERSION/REACT_ROUTER_VERSIONare deprecated (warn now, removed in 1.0).react-helmetis only installed whenrx.helmetis used.
Tests
- Vitest unit tests live inside the package (
frontend/tests/) and run as ajs-unit-testsCI job;state.jsbecomes unit-testable for the first time. The JS test tooling itself is tracked in #7611.
Pending work
The implementation lives on branch claude/reflex-frontend-js-package-ockox9 (7 commits, +4775/-348 across 99 files). It was validated end to end with reflex compile and reflex export of a scratch app in source mode, bun and npm installs of the packed tarball, and the wheel in a clean venv. No PR has been opened for it yet.
- Rebase onto current
main: the branch is based on #6919 (late August) and predates later changes to the install flow (for example #7235 and the open #7451). - Open the PR; re-check the breaking-change fragment (
news/+frontend-npm-package.breaking.md) and thedocs/wrapping-react/local-packages.mdsection describing thefile:/link:entry andoverrides. - Confirm the release pipeline builds the tarball into the wheel (
verify-frontend-tgzinscripts/release.py) on an actual pre-release.
Related
- #7611 JS unit tests for the shipped frontend
- #7562 / #7564 reproducible production builds
- Lenguaje dominante
- Python
- Estrellas
- 29k
- Forks
- 1.8k
- Merge medio
- 2 d 22 h
- PR fusionados (30 d)
- 143
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de reflex-dev/reflex
-
Operations on a list[T] | None var throw when the value is NonePosiblemente ocupada @masenf la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
reflex-dev/reflex#7826 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
A dev run stopped before its backend loads leaves .web/nocompile, so the next run or export skips the compilePosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
reflex-dev/reflex#7825 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
PropsBase nested serialization applies parent include/exclude filters to child fieldsPosiblemente ocupada @harsh21234i la tomó hace 1 día. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
reflex-dev/reflex#7787 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
OTel: add trace_flags to JSON log records so unsampled trace ids are recognizablePosiblemente ocupada @ShaanGS la tomó hace 7 días. Abiertoenhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
reflex-dev/reflex#7729 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
0.9.12 changelog follow-ups: the #7132 "_get_was_touched" entry describes unreachable behaviour, #7115's hasattr/getattr change is undocumented, #7131's wordingQuizá libre de nuevo Un pull request para esta issue se cerró sin fusionarse. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
reflex-dev/reflex#7260 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
Todos los issues de reflex-dev/reflex
Issues similares
-
release
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
MichaelYcJo/SpecSeal#1535 ·
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
valentinfrlch/ha-llmvision#769 ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 1/5 Menos de una hora Aptitud para principiantes 75/100
daniel-ospina/tortoise#11937 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
good first issue help wanted python up-for-grabs
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
andrewsiah/agentswarm-data-tasks#238 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
cadence-workflow/cadence-ai-samples#175 ·
Los mantenedores suelen responder en 1 día