1.5.9 • Published 6 years ago

serverside v1.5.9

Weekly downloads
11
License
MIT
Repository
github
Last release
6 years ago

serverside

Server-side rendering for apps based on inferno-scripts, react-scripts or react-scripts-ts without ejecting.

Usage

create-react-app my-app
cd my-app
yarn add serverside

Develop with yarn start as usual. When you are done, run yarn serverside to build and serve. Open http://localhost:3000 to view the resulting build in the browser.

Interesting usage

Typically features MobX and routing. Save a Servable.js (or Servable.tsx if using react-scripts-ts) near your index:

import { autorun, isObservableProp } from "mobx";

// Inferno app? Just import its respective implementations.
import { Provider, useStaticRendering } from "mobx-react";
import { createElement } from "react";
import { renderToString } from "react-dom/server";
import { renderStatic } from "react-helmet";
import { matchPath, StaticRouter } from "react-router";

import { ClientServable } from "serverside";
import { App } from "./app/App";
import { Services } from "./app/Services";

export const Servable = new ClientServable({
  // Your app component.
  App,

  Dom: {
    createElement,
    renderToString
  },

  // Optional.
  Helmet: { renderStatic },

  Mobx: {
    Provider,
    Services, // Your data and fetch logic, keep reading.
    autorun,
    isObservableProp,
    useStaticRendering
  },

  Router: {
    StaticRouter,
    matchPath,
    routes: App.routes // Your routes should receive services as props.
  }
});

Load data with MobX

You need a Services class to store your state. Constructor must receive a Fetch API. The server passes an isomorphic-fetch, configured like a proxy, taking care of cookies etc.

import { decorate, observable } from "mobx";
import { ClientObservable } from "serverside";

export class Services {
  constructor(fetch, initialState = {}) {
    this.userService = new UserService(fetch);

    new ClientObservable(this).copyFrom(initialState);
  }
}

export class UserService {
  constructor(fetch) {
    this.fetch = fetch;

    this.ip = "";
  }

  getIp = async () => {
    const { origin } = await this.fetch("https://httpbin.org/ip");

    this.ip = origin;
  }
}

decorate(UserService, {
  ip: observable
});

Put a Provider in your index.js:

const services = new Services(
  fetch.bind(window),
  window.__INITIAL_STATE__
);

ReactDOM.render(
  <Provider {...services}>
    <App />
  </Provider>,
  document.getElementById("root") // Make sure index.html has same id.
);

Create routes

Serverside supports react-helmet and react-router. Top-level route components can have loadData.

// Item.js

import { inject, obsever } from "mobx-react";
import { ClientFetch } from "serverside";

class ItemView extends React.Component {
  // Server
  static async loadData({ match, itemService }) {
    await itemService.getOne(match.params.id);
  }
  
  // Browser.
  async componentDidMount() {
    if (!this.props.itemService.items[this.props.match.params.id]) {
      /**
       * Same as ItemView.loadData(this.props), but all fetches happen on
       * your server, so the client makes only one roundtrip.
       */
      await new ClientFetch(this.props).askServer(Item);
    }
  }

  render() {
    const { items } = this.props.itemService;
    const { params } = this.props.match;

    const item = items[params.id] || { id: "Loading..." };

    return <h1>{item.id}</h1>;
  }
}

export const Item = inject("itemService")(observer(ItemView));
// App.js

import { Route, Switch } from "react-router";

export default class App extends React.Component {
  render() {
    return (
      <Switch>
        {App.routes.map((route, i) => <Route {...route} key={i} />)}
      </Switch>
    );
  }
}

App.routes = [
  { path: "/items/:id", component: Item },
  // ...
];

Further help

Also check out the Create React App README.

License

MIT

1.5.9

6 years ago

1.5.8

6 years ago

1.5.7

6 years ago

1.5.6

6 years ago

1.5.5

6 years ago

1.5.4

6 years ago

1.5.3

6 years ago

1.5.2

6 years ago

1.5.1

6 years ago

1.5.0

6 years ago

1.4.1

6 years ago

1.4.0

6 years ago

1.3.0

6 years ago

1.2.0

7 years ago

1.1.2

7 years ago

1.1.0

7 years ago

1.0.2

7 years ago

1.0.1

7 years ago

1.0.0

7 years ago