congzhangzh / react-native-remote-web

Server-side execution for React 🌋
https://www.npmjs.com/package/caldera
1 stars 0 forks source link

🌋

Caldera is a server-side execution environment for React. Think of it as the Node.js analog to Phoenix LiveView — all of the application logic (including rendering) runs on the server, and DOM updates are sent to the client in real-time.

This allows developers to rapidly build interactive and multiplayer applications without developing boilerplate around RPC layers (REST/GraphQL/gRPC) and messaging primitives (WebSockets/subscriptions/etc).

Because it's built on top of the React reconciler, it's compatible with (currently, a reasonably useful subset of) the existing React API. See what's currently included and what's to come for updates.

Screenshot

https://user-images.githubusercontent.com/13283869/153917842-a286add1-a141-4f39-81c3-76aa22ba4d34.mp4

Installation

Run npm install caldera to install Caldera.

Examples

A simple example (chat room) to get started:

import React, { useState } from "react";
import { renderCalderaApp, makeSharedResource, useSharedState } from "caldera";
import fs from "fs";

const DATA_PATH = "messages.json";
const messagesResource = makeSharedResource(
  // Load initial messages
  fs.existsSync(DATA_PATH)
    ? JSON.parse(fs.readFileSync(DATA_PATH, "utf-8"))
    : []
);

const usePersistedMessages = () => {
  // Basic shared state, synced with all clients
  const [messages, setMessages] = useSharedState(messagesResource);
  return [
    messages,
    // Persist to disk (in prod, use a database)
    (newMessages) => {
      setMessages(newMessages);
      fs.writeFileSync(DATA_PATH, JSON.stringify(newMessages));
    },
  ];
};

const App = () => {
  const [messages, setMessages] = usePersistedMessages();
  // local state, persisted across client reconnects
  const [draftMsg, setDraftMsg] = useState("");

  return (
    <>
      <h1>Chat Room!</h1>
      {messages.map((message, i) => (
        <div key={i}>{message}</div>
      ))}
      <form
        onSubmit={(e) => {
          e.preventDefault();
          setMessages([...messages, draftMsg]);
          setDraftMsg("");
        }}
      >
        <input
          type="text"
          value={draftMsg}
          onChange={(e) => setDraftMsg(e.target.value)}
        />
        <button type="submit">Submit</button>
      </form>
    </>
  );
};

renderCalderaApp(<App />, { port: 4000 });

Install Babel by running npm install @babel/core @babel/node @babel/preset-react.

Then, run the app using babel-node --presets @babel/preset-react index.jsx. For a runnable version, check the basic-example folder.

A few other examples here demonstrate features like shared state, database usage, and session persistence.

Possible Usage

  1. GUI for linux server utility application driven by zx https://github.com/google/zx
  2. GUI for some web helper system driven by https://github.com/puppeteer/puppeteer

API/Documentation

[Work in progress]

The caldera package provides the following top-level exports:

What works

What's being worked on

Future plans

Development flow

package publishing

npm run build
npm version minor # major | minor | patch
npm publish
git push
git push --tags

Sample apps

  1. basic-example
  2. electron-example
  3. zx-example(wip)
  4. puppeteer-example(wip)