@ethicdevs/fastify-stream-react-views
TypeScript icon, indicating that this package has built-in type declarations

1.11.3 • Public • Published

@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

Package Sidebar

Install

npm i @ethicdevs/fastify-stream-react-views

Weekly Downloads

370

Version

1.11.3

License

MIT

Unpacked Size

1.04 MB

Total Files

228

Last publish

Collaborators

  • wnemencha