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

Better compatibility with ReactJS Packages #786

Open
Archmonger opened this issue Jul 10, 2022 · 0 comments
Open

Better compatibility with ReactJS Packages #786

Archmonger opened this issue Jul 10, 2022 · 0 comments
Labels
priority-1-high Should be resolved ASAP. type-feature About new capabilities type-investigation About research and gathering information

Comments

@Archmonger
Copy link
Contributor

Archmonger commented Jul 10, 2022

TLDR

We want users to be able to use ReactJS components from NPM in a similar level of complexity to a pip install. This will require developing ReactPy Package Manager. This tool will pull packages down using NPM, statically build/analyze them, then auto-generate a Python file containing the usable interface.

For users that really want to dive into the nitty-gritty of writing their components in JavaScript (ReactJS), we will re-engineer the JavaScript API to leverage any standard JavaScript tooling. Ideally, it should feel exactly like writing a normal ReactJS component.


Current Situation

Right now there's a few factors that make using ReactJS components a bit awkward/infeasible

  • It's not reasonable manually translate every ReactJS component to a Python.
  • module_from_template can cause ReactJS version mismatches resulting in the imported library not working
  • JavaScript Module API feels awkward to use.

Proposed Actions

We need to investigate how to best automatically interface with, let's say, the top 100 React libraries on NPM.

The main question is, how do we make sure things written for ReactJS are compatible with ReactPy? This will involve is having to rethink our compatibility layer for the following:

  • Hooks
  • Events
  • Components

Design Concept

Create a ReactPy build step can automatically generate Python wrappers of JavaScript functionality. Ideally, this machine generated Python would also include type hints that are automatically inferred from the JavaScript code. We can potentially deduce type hints using a JavaScript AST parser.

A generated Python file for a react-bootstrap Card could potentially look something like this:

_Card = module_from_file("path/to/built/src/react-bootstrap.js", imports="Card")

@component
def Card(bsPrefix=None, className=None, bg=None, text=None, border=None, body=None, children=None, as='div', body=False):
    return _Card(bsPrefix, className, bg, text, border, body, children, as, body)

How to handle JavaScript

We have a few ways we can handle JS modules:

  1. Run JavaScript client side, and figure out how to communicate info back to the server
  2. Run JavaScript client side, but have the user only be able to interact with that code with other client-side code
  3. Run JavaScript server side. This will likely be transpiled into WASM and run within python.

The NPM Dependency Issue

For ease of use, we should bundle precompiled NPM binaries within this PyPI package. It's far less janky than requiring the user to externally install NPM.

We should probably follow the same precedence as Playwright/Selenium. If the user tries to use reactpy build, we should first check if our NPM binary has been installed. If it hasn't, we will tell the user to run a reactpy download-npm command.

The "children as props" issue

As mentioned in #989, we need to spend some additional thought on how to convert JavaScript components to Python components.

This is due to libraries like MaterialUI existing that have components as props. This might involve inventing some way to serialize React components in a reproducible way.

react-serialize could potentially work for this.

Command Line Interface

The CLI should be accessible within the reactpy <command> namespace. All package manager commands will print out an error if reactpy-package-manager is not installed.

build command

  1. User generated packages will need a package.json, formatted in NPM parseable format
  2. Users must declare their own dependencies within a package.json
  3. reactpy build --all will auto discover all package.json files that have a reactpy attribute within them.
  4. reactpy build <DIR> will build a single package.
  5. Docs will show custom components using ReactJS, not Preact
  6. If we see workspaces in package.json, throw an error.
  7. We will output a __init__.py into the given directory, unless a different output file is specified (in package.json)
  8. Use npm and automatically create node_modules/.gitignore containing *
  9. Always recreate node_modules/.gitignore if it does not exist
  10. We should hide our output in node_modules/@reactpy/_build/output.js
  11. Add settings within package.json:reactpy such as output_path, node_modules_gitignore
  12. The two mandatory package.json fields are main and reactpy

install command

  1. Should have a --target-dir option (we should make sure to name it the same as the pip's equivalent)
  2. Should have a --exports=... option to limit what gets built
  3. Should create a python module via cookiecutter.
  4. Installed modules are accessible within Python via reactjs.pkg_name
  5. Should automatically create a top level package.json and start populate it for every installed package

uninstall command

  1. uninstall command should have an --all option

npm command

  1. npm command is a direct passthrough of our local node npm instance

download-npm command

  1. Downloads node to the current environment, similar to how selenium downloads Chromium.
  2. If called a second time, will prompt the user if they want to delete then redownload
@Archmonger Archmonger added type-investigation About research and gathering information priority-1-high Should be resolved ASAP. labels Jul 10, 2022
@Archmonger Archmonger added this to the 2.0 milestone Aug 5, 2022
@Archmonger Archmonger changed the title Better compatibility with React modules Implement an IDOM build step (better compatibility with React modules) Aug 17, 2022
@Archmonger Archmonger added the type-feature About new capabilities label Sep 25, 2022
@Archmonger Archmonger modified the milestones: Luxury, Essential Jan 29, 2023
@rmorshea rmorshea removed this from the Essential milestone Feb 21, 2023
@rmorshea rmorshea changed the title Implement an IDOM build step (better compatibility with React modules) Implement a ReactPy build tool (better compatibility with React modules) May 24, 2023
@Archmonger Archmonger changed the title Implement a ReactPy build tool (better compatibility with React modules) Better compatibility with ReactJS Packages Jun 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority-1-high Should be resolved ASAP. type-feature About new capabilities type-investigation About research and gathering information
Projects
None yet
Development

No branches or pull requests

2 participants