1.11.3 • Published 5 months ago

@ethicdevs/fastify-stream-react-views v1.11.3

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

@ethicdevs/fastify-stream-react-views

Built-in TypeScript definitions NPM MIT License

What started as a fastify reply decorator to renderToMarkupStream a React component as a view/template (plain-old fashioned SSR/monolith/PHP way, without CSR/hydration) is becoming a full-featured framework to build SSR/Islands based applications without the usual pain! 🚀


Looking for an SSR+Island ready solution?

Discover the React Monolith framework which is a framework we built on-top of this library so you don't have to! ⚡️

Sample usage for getting started quickly can be found in the the React Monolith samples repository


Installation

$ yarn add @ethicdevs/fastify-stream-react-views
# or
$ npm i @ethicdevs/fastify-stream-react-views

Usage

First create a server.ts file that will act as the application entry point.

// src/server.ts
import { join, resolve} from "path";
import fastify from "fastify";
import streamReactViews from "@ethicdevs/fastify-stream-react-views";

function main() {
  const app = fastify();

  // ... more fastify server setup ...

  app.register(streamReactViews, {
    appName: "YourAppName", // optional
    titleSeparatorChar: "∙", // optional
    commonProps: { // optional
      foo: 'bar',
      baz: 1,
    }
    islandsFolder: resolve(join(__dirname, 'islands'), // optional
    viewsFolder: resolve(join(__dirname, 'views'), // required
    viewContext: { // optional
      html: {
        dir: "ltr",
      },
      head: [
        { kind: "meta", charset: "utf-8" },
        {
          kind: "meta",
          name: "viewport",
          content: "width=device-width, initial-scale=1",
        },
        {
          kind: "link",
          rel: "icon",
          type: "image/x-icon",
          href: "/public/favicon.ico",
        },
      ],
    },
    withStyledSSR: true, // optional, set to true for styled-component usage
  });

  app.get('/', (_, reply) => {
    return reply.streamReactView('home', {
      title: "This will set the page title in tab bar!",
      hello: 'world',
      punctuation: '!'
    });
  });

  app.listen(...); // as usual
}

main();

Add an HomeView to test things works like this:

// src/views/HomeView.tsx
import type { ReactView } from "@ethicdevs/fastify-stream-react-views";
import React, { VFC } from "react";

import Counter from "../islands/Counter";

type HomeViewProps = {
  hello: string;
  punctuation?: "." | "!" | "?";
};

const HomeView: ReactView = ({ hello, punctuation }) => {
  return (
    <>
      <h1>{`Hello, ${hello}${punctuation || "!"}`}</h1>
      <Counter defaultValue={42} />
    </>
  );
};

export default HomeView;

Then the Counter Island so this component becomes interactive when page has loaded on the client-side (i.e. browser):

// src/islands/Counter.tsx
import type { ReactIsland } from "@ethicdevs/fastify-stream-react-views";
import React, { useState } from "react";

type CounterProps = {
  defaultValue?: number;
};

const Counter: ReactIsland<CounterProps> = ({ defaultValue = 0 }) => {
  const [counter, setCounter] = useState(defaultValue);
  const incrementCounter = () => setCounter((prev) => prev + 1);
  const decrementCounter = () => setCounter((prev) => prev - 1);
  return (
    <div>
      <strong aria-description={"Counter value"}>{`${counter}`}</strong>
      <button onClick={decrementCounter} title={"Decrement counter"}>
        -
      </button>
      <button onClick={incrementCounter} title={"Increment counter"}>
        +
      </button>
    </div>
  );
};

export default Counter;

Then navigate to the ip:port you listen to, and see the magic by inspecting both at the page source code level, as well as devtools/page inspector. Look how the generated HTML is neat and contains everything needed for the client to start being interactive in no-time (~6ms to be interactive in this example). Enjoy ;)

License

MIT

1.11.3

5 months ago

1.11.2

1 year ago

1.11.1

1 year ago

1.11.0

1 year ago

1.10.2

2 years ago

1.9.1

2 years ago

1.9.0

2 years ago

1.10.1

2 years ago

1.10.0

2 years ago

1.9.9

2 years ago

1.9.8

2 years ago

1.9.7

2 years ago

1.9.6

2 years ago

1.9.5

2 years ago

1.9.4

2 years ago

1.9.3

2 years ago

1.9.2

2 years ago

1.8.9

2 years ago

1.8.7

2 years ago

1.8.6

2 years ago

1.8.5

2 years ago

1.8.4

2 years ago

1.8.3

2 years ago

1.2.0

2 years ago

0.9.12

2 years ago

0.9.13

2 years ago

1.0.0

2 years ago

0.9.14

2 years ago

0.9.10

2 years ago

0.9.11

2 years ago

1.8.2

2 years ago

1.8.1

2 years ago

1.6.3

2 years ago

1.8.0

2 years ago

1.6.2

2 years ago

1.6.1

2 years ago

1.6.0

2 years ago

1.4.0

2 years ago

1.2.2

2 years ago

1.2.1

2 years ago

1.7.9

2 years ago

1.7.8

2 years ago

1.7.7

2 years ago

1.7.6

2 years ago

1.7.5

2 years ago

1.7.4

2 years ago

0.9.0

2 years ago

0.9.2

2 years ago

0.9.1

2 years ago

0.7.0

2 years ago

1.1.1

2 years ago

1.1.0

2 years ago

0.9.7

2 years ago

0.9.9

2 years ago

0.9.4

2 years ago

0.9.3

2 years ago

0.9.6

2 years ago

0.9.5

2 years ago

1.7.3

2 years ago

1.7.2

2 years ago

1.5.4

2 years ago

1.3.6

2 years ago

1.7.1

2 years ago

1.5.3

2 years ago

1.3.5

2 years ago

1.7.0

2 years ago

1.5.2

2 years ago

1.3.4

2 years ago

1.5.1

2 years ago

1.3.3

2 years ago

1.5.0

2 years ago

1.3.2

2 years ago

1.3.1

2 years ago

1.3.0

2 years ago

1.1.2

2 years ago

0.8.1

2 years ago

0.8.0

2 years ago

0.6.1

2 years ago

0.6.0

2 years ago

0.3.0-rc3

2 years ago

0.3.0-rc2

2 years ago

0.3.0-rc1

2 years ago

0.3.0

2 years ago

0.5.0

2 years ago

0.4.1

2 years ago

0.4.0

2 years ago

0.3.1

2 years ago

0.2.12

2 years ago

0.2.11

2 years ago

0.2.10

2 years ago

0.2.9

2 years ago

0.2.8

2 years ago

0.2.7

2 years ago

0.2.6

2 years ago

0.2.5

2 years ago

0.2.4

2 years ago

0.2.3

2 years ago

0.2.2

2 years ago

0.2.1

2 years ago

0.2.0

2 years ago

0.1.2

2 years ago

0.1.1

2 years ago

0.1.0

2 years ago