Nearly Pooped Myself

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

    1.11.2 • 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

    Install

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

    DownloadsWeekly Downloads

    161

    Version

    1.11.2

    License

    MIT

    Unpacked Size

    1.03 MB

    Total Files

    227

    Last publish

    Collaborators

    • wnemencha