justinmcp / taper

Taper is a React (with SSR) and server-side-redux-like environment for Elixir+Phoenix.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Taper

License Hex.pm [Build Status] [Coverage]

Taper is a React (with SSR) and server-side-redux-like environment for Elixir+Phoenix.

Taper is not ready for production use, currently it's "all the ingredients in a bowl, and looking like it might be a nice cake", but not even mixed properly yet. Still, feel free to experiment.

Installation

Add taper to your mix.exs.

def deps do
  [
    {:taper, "~> 0.1.0"}
  ]
end

Configuration

defmodule AwesomeWeb
...
  def view do
    quote do
      ...
      import Taper.View
    end
  end

  def router do
    quote do
    ...
      import Taper.Router
    end
end
defmodule AwesomeWeb.Endpoint do
  use Phoenix.Endpoint, otp_app: :awesome
  ...
  socket "/taper", Taper.Socket, websocket: true
end
defmodule AwesomeWeb.Router do
  scope "/", AwesomeWeb do
    pipe_through :browser
     # Possible options;
     # - server_only: (true|false); when true will not hydrate on client - renders static page
     # - taper_id: (String); when set will id of taper root component on page
     # Both options can also be set via assigns in the controller
    taper "/", AwesomePage
  end
end
config :phoenix, :template_engines, jsx: Taper.Template.Engine
<head>
  <%= taper_meta_tag(@conn) %>
</head>
<body>
  <main role="main">
    <%= @inner_content %>
  </main>
  <%= taper_script() %>
</body>
  "dependencies": {
    ...
    "taper": "file:../deps/taper",
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },
  "devDependencies": {
    "@babel/core": "^7.0.0",
    "@babel/plugin-proposal-class-properties": "^7.10.4",
    "@babel/plugin-transform-modules-commonjs": "^7.9.6",
    "@babel/plugin-transform-react-jsx": "^7.9.4",
    "@babel/preset-env": "^7.0.0",
    "@babel/preset-react": "^7.9.4",
  }
import { Socket } from "phoenix";
import React from "react";
import ReactDOM from "react-dom";
import { Taper } from "taper";
import App from "./components/App";
import css from "../css/app.scss";

if (window.taperComponent != undefined) {
  let taperToken = document
    .querySelector("meta[name='taper-token']")
    .getAttribute("content");
  let rootComponent = document.getElementById("taper");
  window.taper = new Taper(
    "/taper",
    { Socket, React, ReactDOM },
    { params: { taperToken } }
  );
  window.taper.connect();
  window.taper.render(window.taperComponent, rootComponent);
}

TODO

  • SSR with active store state (not initial store state)
  • [o] Server side routing (with code splitting)
  • Server side rendering with no hydration
  • Setup mix task
  • Flip store ownership to make semi/persistent stores easier
  • Handle errors in JSX templates
  • RPC channel
  • GraphQL channel
  • Cleanup Ecto support
  • Only send store changes to client
  • ...
  • A lot of tests

Examples

Some examples can be found @ taper-examples

License

Copyright (c) 2020 Justin McPherson

This project is licensed under the terms of the MIT license, please see the LICENSE.md file for more details.

About

Taper is a React (with SSR) and server-side-redux-like environment for Elixir+Phoenix.

License:MIT License


Languages

Language:Elixir 67.7%Language:JavaScript 32.3%