All Projects → AlexSergey → issr

AlexSergey / issr

Licence: other
The easiest way to move your React application to Server-Side Rendering. Handles Side Effects and synchronizes State.

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to issr

React Jobs
Asynchronously resolve data for your components, with support for server side rendering.
Stars: ✭ 167 (+98.81%)
Mutual labels:  ssr, server-side-rendering
Crate
👕 👖 📦 A sample web and mobile application built with Node, Express, React, React Native, Redux and GraphQL. Very basic replica of stitchfix.com / krate.in (allows users to get monthly subscription of trendy clothes and accessories).
Stars: ✭ 2,281 (+2615.48%)
Mutual labels:  ssr, server-side-rendering
React Core Boilerplate
Powerful ASP.NET Core 3 templates with React, true server-side rendering and Docker support
Stars: ✭ 169 (+101.19%)
Mutual labels:  ssr, server-side-rendering
core
🚀Fast, 💎Lightweight Angular alternative with the same modern API thats compile directly to WebComponents
Stars: ✭ 49 (-41.67%)
Mutual labels:  ssr, server-side-rendering
Beidou
🌌 Isomorphic framework for server-rendered React apps
Stars: ✭ 2,726 (+3145.24%)
Mutual labels:  ssr, server-side-rendering
Rendora
dynamic server-side rendering using headless Chrome to effortlessly solve the SEO problem for modern javascript websites
Stars: ✭ 1,853 (+2105.95%)
Mutual labels:  ssr, server-side-rendering
React Ssr Boilerplate
Boilerplate for React apps with routing, code splitting, & server side rendering
Stars: ✭ 183 (+117.86%)
Mutual labels:  ssr, server-side-rendering
React Async Bootstrapper
Execute a bootstrap method on your React/Preact components. Useful for data prefetching and other activities.
Stars: ✭ 113 (+34.52%)
Mutual labels:  ssr, server-side-rendering
Use Ssr
☯️ React hook to determine if you are on the server, browser, or react native
Stars: ✭ 230 (+173.81%)
Mutual labels:  ssr, server-side-rendering
React Rendering Strategies
Improve your React ⚛️ app performance by using Dynamic Rendering, Progressive Rendering or Static Rendering
Stars: ✭ 217 (+158.33%)
Mutual labels:  ssr, server-side-rendering
Surmon.me
🆒 My personal website and blog, powered by @vuejs (3)
Stars: ✭ 1,767 (+2003.57%)
Mutual labels:  ssr, server-side-rendering
angular-ssr
Angular 14 Example SSR (Server side rendering)
Stars: ✭ 92 (+9.52%)
Mutual labels:  ssr, server-side-rendering
Universal Router
A simple middleware-style router for isomorphic JavaScript web apps
Stars: ✭ 1,598 (+1802.38%)
Mutual labels:  ssr, server-side-rendering
Reactql
Universal React+GraphQL starter kit: React 16, Apollo 2, MobX, Emotion, Webpack 4, GraphQL Code Generator, React Router 4, PostCSS, SSR
Stars: ✭ 1,833 (+2082.14%)
Mutual labels:  ssr, server-side-rendering
Razzle Material Ui Styled Example
Razzle Material-UI example with Styled Components using Express with compression
Stars: ✭ 117 (+39.29%)
Mutual labels:  ssr, server-side-rendering
Mmf Blog Vue2 Ssr
mmf-blog-vue2 ssr(The service side rendering)
Stars: ✭ 174 (+107.14%)
Mutual labels:  ssr, server-side-rendering
Hyperapp Render
Render Hyperapp to an HTML string with SSR and Node.js streaming support.
Stars: ✭ 93 (+10.71%)
Mutual labels:  ssr, server-side-rendering
Coren
React offline server-rendered framework
Stars: ✭ 102 (+21.43%)
Mutual labels:  ssr, server-side-rendering
Blog Frontend Project
Web frontend code for my blogs, develop with Vue.
Stars: ✭ 206 (+145.24%)
Mutual labels:  ssr, server-side-rendering
Feliz.ViewEngine
Feliz DSL and engine for HTML generation and server side rendering (SSR)
Stars: ✭ 53 (-36.9%)
Mutual labels:  ssr, server-side-rendering

iSSR

The easiest way to move your React application to Server-Side Rendering. Handles Side Effects and synchronizes State.

Table of Contents

Articles

Features

  • iSSR supports native setState, Redux (thunk, sagas), Mobx, Apollo and other state management libraries
  • TypeScript support
  • Small size (5kb)
  • No dependencies

Getting Started

Modern JS applications are divided into 2 types:

  • CSR - Client-Side rendering. The application will be displayed only after downloading and executing all the necessary JS code. Until then, the user will see a blank page. It degrades the UX and is bad for SEO.
  • SSR - Server-Side rendering. The auxiliary server doesn't send a blank page, but a page with data. Thus, the user can immediately start working with the application, and search engine bots will index the page.

SSR

Schematically, the SSR application looks like this:

iSSR

  • SSR application consists of two sub-applications - frontend and backend with common logic.
  • NodeJS app runs React app.
  • iSSR handles all asynchronous operations.
  • After receiving data from asynchronous operations, the React application is rendered.
  • NodeJS application serves HTML to the user.

Problems

One of the key problems with SSR applications are asynchronous operations. JS is an asynchronous language, all requests to the server, on which our application data depends, are asynchronous. They affect the state of the system - these are side effects. Since content availability is critical for search engines, we must handle this asynchronous behavior. The React Server Renderer is designed as a synchronous operation that steps through our React-DOM step by step and turns it into HTML.

The second problem is hydration. A process that allows us to associate the received HTML and the state of the application from the server with what will be built in the user's browser.

iSSR handles asynchronous operations and synchronizes state on the client.

Motivation

React currently has many solutions for building SSR applications. The most popular solution is Next.JS. This is a great framework with many possibilities, iSSR cannot replace it. But, Next.JS requires rewriting your existing application completely. Next.JS is a framework, which means you have to use its approaches. iSSR is just a small library that handles side effects and synchronizes state.

  • You can very quickly migrate your existing application to SSR using iSSR without major changes.
  • You can use any build system.
  • You can use any state management solution like Redux, Apollo, Mobx or native setState.
  • You can use any other SSR libraries (for example @loadable, react-helmet, etc).

Using

The simplest example of an SSR application using an asynchronous function via setState

Example:

Here is a simple Todo List Application without SSR. It uses jsonplaceholder for mocking the data:

import React, { useState, useEffect } from 'react';
import { render } from 'react-dom';

const getTodos = () => {
  return fetch('https://jsonplaceholder.typicode.com/todos')
   .then(data => data.json())
};

const TodoList = () => {
  const [todos, setTodos] = useState([]);

  useEffect(() => {
    getTodos()
      .then(todos => setTodos(todos))
  }, []);

  return (
    <div>
      <h1>Hi</h1>
      <ul>
        {todos.map(todo => (
          <li key={todo.id} style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>{todo.title}</li>
        ))}
      </ul>
    </div>
  )
}

render(
  <TodoList />,
  document.getElementById('root')
);

It's very simple, when we open the application it will load the todo list data from the server and render it.

Let's change this app to SSR:

Step 1. Installation:

npm install @issr/core --save
npm install @issr/babel-plugin --save-dev

Basic webpack configuration for SSR:

npm install @babel/core @babel/preset-react babel-loader webpack webpack-cli nodemon-webpack-plugin --save-dev

For this example we should install node-fetch because native fetch does not support node.js. Also, for the server we will use express, but you can use any module

npm install node-fetch express --save

Step 2. Make webpack.config.js in the root of project

const path = require('path');
const NodemonPlugin = require('nodemon-webpack-plugin');

const commonConfig = {
  module: {
    rules: [
      {
        test: /\.jsx$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                '@babel/preset-react'
              ],
              plugins: [
                '@issr/babel-plugin'
              ]
            }
          }
        ]
      }
    ]
  },
  resolve: {
    extensions: [
      '.js',
      '.jsx'
    ]
  }
}

module.exports = [
  {
    ...commonConfig,
    target: 'node',
    entry: './src/server.jsx',
    output: {
      path: path.resolve(__dirname, './dist'),
      filename: 'index.js',
    },
    plugins: [
      new NodemonPlugin({
        watch: path.resolve(__dirname, './dist'),
      })
    ]
  },
  {
    ...commonConfig,
    entry: './src/client.jsx',
    output: {
      path: path.resolve(__dirname, './public'),
      filename: 'index.js',
    }
  }
];

The main goal is to create 2 applications client and server with common logic.

Step 3. Let's separate the general logic from rendering. Let's create App.jsx, and take out the common part for both Frontend and Backend:

import React from 'react';
import fetch from 'node-fetch';
import { useSsrState, useSsrEffect } from '@issr/core';

const getTodos = () => {
  return fetch('https://jsonplaceholder.typicode.com/todos')
   .then(data => data.json())
};

export const App = () => {
  const [todos, setTodos] = useSsrState([]);

  useSsrEffect(async () => {
    const todos = await getTodos()
    setTodos(todos);
  });

  return (
    <div>
      <h1>Hi</h1>
      <ul>
        {todos.map(todo => (
          <li key={todo.id} style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>{todo.title}</li>
        ))}
      </ul>
    </div>
  );
};

In this code, getTodos is an asynchronous operation that makes call to the jsonplaceholder server and gets the todo list data.

  • useSsrState is analogue of useState only with SSR support

  • useSsrEffect is analogue useEffect (() => {}, []); for SSR. It works with any async logic.

Step 4. client.jsx should contain part of the application for Frontend

import React from 'react';
import { hydrate } from 'react-dom';
import createSsr from '@issr/core';
import { App } from './App';

const SSR = createSsr(window.SSR_DATA);

hydrate(
  <SSR>
    <App />
  </SSR>,
  document.getElementById('root')
);

The code:

const SSR = createSsr(window.SSR_DATA);

Associates the state executed on the server with the application on the client side. For correct work useSsrState on the client

Step 5. server.jsx should contain the logic of the NodeJS application, it is convenient to use the koa/express framework or similar for this:

import React from 'react';
import express from 'express';
import { serverRender } from '@issr/core';
import serialize from 'serialize-javascript';
import { App } from './App';

const app = express();

app.use(express.static('public'));

app.get('/*', async (req, res) => {
  const { html, state } = await serverRender(() => <App />);

  res.send(`
  <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
      window.SSR_DATA = ${serialize(state, { isJSON: true })}
    </script>
</head>
<body>
    <div id="root">${html}</div>
    <script src="https://github.com/index.js"></script>
</body>
</html>
`);
});

app.listen(4000, () => {
  console.log('Example app listening on port 4000!');
});

There are 2 important points in this code:

app.use(express.static('public'));

The server should serve the folder where frontend part of application is built.

<script>
  window.SSR_DATA = ${serialize(state, { isJSON: true })}
</script>

This code saves the executed state on the server to use it on the client side later .

Step 6 The final step is webpack's scripts for development mode and building. Add to your package.json:

"scripts": {
  "start": "webpack -w --mode development",
  "build": "webpack"
},

  • Please see Articles to learn how implement SSR for Redux/Sagas/Thunks and other.
  • Please see "examples" folder to learn other cases - here

The MIT License

Copyright (c) Aleksandrov Sergey

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].