Umajs-react-ssr: An Isomorphic Server‑Side Rendering Solution for React on the Umajs Node Framework

Umajs-react-ssr is a lightweight isomorphic SSR solution built on the Umajs Node.js framework that enables React page components to be rendered on both server and client, offering flexible routing, server‑side data fetching, custom HTML templates, CSS‑module support, and easy configuration for improved performance and developer experience.

58 Tech
58 Tech
58 Tech
Umajs-react-ssr: An Isomorphic Server‑Side Rendering Solution for React on the Umajs Node Framework

Introduction

Server‑Side Rendering (SSR) has become essential for improving first‑page load speed and SEO. Traditional template‑engine SSR is less common today; modern libraries such as React and Vue use component‑based development, but still face challenges like white‑screen rendering and SEO.

Next.js and Nuxt.js provide SSR for React and Vue respectively, yet integrating them with enterprise‑level Node frameworks can be cumbersome. This motivated the exploration of an isomorphic solution based on Umajs.

Why Adopt Isomorphism

Node.js’s popularity and the rise of SSR mean that many projects now use Node both for front‑end rendering (SEO) and as a backend gateway for data aggregation. Maintaining separate front‑end and Node projects increases maintenance cost. An isomorphic approach allows developers to run a single Node project that serves both front‑end and back‑end, simplifying development and deployment.

SEO support

Reduced engineering maintenance cost

Improved development and deployment efficiency

Popular SSR Solutions

Next.js / Nuxt.js : Highly packaged SSR, file‑system routing.

egg‑react‑ssr / Easy‑team : Tailored for the Egg ecosystem, supports plugins and multi‑process.

ykfe/ssr (egg‑react‑ssr upgrade) : Lightweight, supports serverless deployment on Alibaba/Tencent Cloud.

Problems with Existing Solutions

Component development experience deviates from standard React/Vue workflows.

Routing is tightly coupled to the file system, making multi‑environment deployment difficult.

Static routing limits flexibility for A/B testing and complex route scenarios.

Data fetching via static getInitialProps mixes server and client logic, hampers debugging, and struggles with non‑HTTP data sources.

Umajs‑react‑ssr Overview

Umajs is an enterprise‑grade Node.js web framework used internally at 58.com. To address the mismatches of existing SSR approaches, Umajs‑react‑ssr was created as a seamless companion to Umajs.

Directory Structure

\- src (umajs)
   \- web (frontend)
       \- pages
           \- list (page component)
               \- index.tsx (entry)
               \- index.scss
       \- component (shared components)
           \- ...

Each page component lives under pages and is compiled into bundles for both client and server.

Routing Rules

Unlike Next.js, Umajs‑react‑ssr disables automatic file‑system routing. Routes are defined in server controllers, allowing one component to be mapped to multiple URLs, which is useful for A/B testing and complex routing needs.

import { BaseController, Path, Query } from '@umajs/core';
import { Result } from '@umajs/plugin-react-ssr';

export default class Index extends BaseController {
    @Path('/', '/list')
    index() {
        return Result.reactView('list');
    }

    @Path('/', '/ABlist')
    index(@Query('abtest') abtest: string) {
        const viewName = 'list' + abtest;
        return Result.reactView(viewName);
    }
}

Dynamic routes can be expressed directly in the decorator, e.g., @Path('/detail:id').

Data Fetching

Two approaches are supported:

Static getInitialProps : Called on the server during rendering, returns props for the component. Works for HTTP APIs but is limited for RPC or database sources.

Server‑side injection : Controllers fetch data via services (RPC, DB) and pass it to Result.reactView, keeping data logic out of the component.

export default class Index extends BaseController {
    @Path('/list')
    index() {
        const ListData = ['item1','item2','item3','item4'];
        return Result.reactView('list', { title: 'List', ListData }, { cache: true });
    }
}

State Management

Umajs‑react‑ssr does not enforce a state library. Simple sharing can use React.useContext + useReducer; complex apps may adopt Redux or MobX.

import React, { useContext } from 'react';
import Context from '../../context';

function Recommend() {
    const { state, dispatch } = useContext(Context);
    return (
        <div>
            {state.RecommendList.map(item => <List key={item.id} {...item} />)}
        </div>
    );
}

Custom HTML & SEO

Instead of an “all‑in‑JS” head, traditional HTML templates are used via html-webpack-plugin with Nunjucks syntax, allowing easy SEO meta injection.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1.0, width=device-width">
    <meta name="keywords" content="{{keywords}}">
    <title>{{title}}</title>
</head>
<body>
    <div id="app"></div>
</body>
</html>

CSS‑Module Support

CSS modules are enabled automatically for files named *.module.css|scss|less, avoiding conflicts with third‑party libraries.

import React from 'react';
import style from './index.module.css';

export default function (props) {
    return (
        <div className={style.home}>
            <p className={style.title}>css modules</p>
            <p>{props.des}</p>
        </div>
    );
}

Application Configuration

// src/config/plugin.config.ts
export default {
    'react-ssr': {
        enable: true,
        options: {
            rootDir: 'web',
            rootNode: 'app',
            ssr: true,
            cache: false,
            prefixCDN: '/'
        }
    }
};

Configuration is minimal; adding the plugin automatically sets up webpack, Babel, and loaders.

Production Deployment

Build the client bundle with npx srejs build. Individual pages can be rebuilt with npx srejs build ${pageName}. Serverless deployment via SFF (Serverless For Frontend) is recommended.

Performance Comparison & Benefits

No default routing – full control over backend routes.

Unified rendering without __isBrowser__ guards.

HTML templates via html-webpack-plugin give higher response speed.

Nunjucks enables easy SEO meta injection.

Retains native React development experience.

Server‑side data handling separates view from business logic.

Dynamic SSR/CSR switching and caching improve availability.

Compatible with other Koa‑based frameworks and supports MPA with per‑page builds.

How to Use

Install the CLI: npm i @umajs/cli -g, then create a project with uma project umajs-react-demo and select the React template.

Future Plans

Umajs‑vue‑ssr support.

Custom webpack rule optimizations.

Development‑time build improvements, Vite support.

Hot‑reload of page components without restarting Node.

Resources

GitHub: https://github.com/Umajs

Plugin: https://github.com/Umajs/plugin-react-ssr

Srejs repo: https://github.com/dazjean/Srejs

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontend developmentReactNode.jsSSRIsomorphic
58 Tech
Written by

58 Tech

Official tech channel of 58, a platform for tech innovation, sharing, and communication.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.