DEV Community

loading...
Cover image for Express in React! React Backend! Whut?! 🤯

Express in React! React Backend! Whut?! 🤯

orkhanjafarovr profile image Orkhan Jafarov ・3 min read

Hey there! One more implemented crazy idea for React

Idea

So, long time ago when I was researching react custom renderer, I had a crazy idea to use it for Node.js server/backend. Finally, I've decided to try.

Disclaimer ⚠️

  • It's not fully-ready solution (in process)
  • Don't use it for production
  • Yes, I know about scalability, architecture and etc. This is just an experimental project. Relax 🛀

How it works?

It works with express.js framework to run Node.js server. Custom renderer is building express-structured app based on React Components.

How it looks like ?

Base code example

import React from "react";
import ReactExpress from "./renderer";

const HomePage = () => <h1>Welcome to home page</h1>;
const AboutPage = () => <><h1>About Company</h1><p>Bla bla</p></>;

const ExpressApp = () => (
  <app port={8080}>
    <router path="/">
      <get content={<HomePage />} />
      <get path="*" content="Not Found" status={404} />
    </router>
    <router path="/company">
      <get path="/about" content={<AboutPage />} />
    </router>
    <router path="/api">
      <post path="/status" content={{ msg: "It is okay, bro" }} />
    </router>
  </app>
);

ReactExpress.render(<ExpressApp />);
Enter fullscreen mode Exit fullscreen mode

Instances

There're components for express.js instances like router, static, get, post and etc.

Components

<app /> - App Instance (props: port)

<static /> - Static route (props: publicPath, path, options)

<router /> - Router-Provider (props: path)

<get />, <post /> and ... - Route component (props: path, content, handler, status)

...still in process

Let's go deep into Route Component

Our route components are <get />, <post />, <delete /> and etc.

They have the same structure.

Examples:

// Response json
<get path="/status" content={{ msg: "I\'m okay" }} />

// Response SSR React-Component
<get path="/homepage" content={() => <h1>Welcome to home page</h1>} />

// Response error
<get path="/not-found" content="Page not found" status={404} />

// Response with handler
<get path="/posts/:id" handler={(req,res) => res.send(`id is ${req.params.id}`)} />

// The same for all methods
<post path="/posts/:id" handler={(req,res) => res.send(`id is ${req.params.id}`)} />
Enter fullscreen mode Exit fullscreen mode

React API

Currently it's possible to use React Context API.
For example there's a way to get handler's request and response arguments. It used in the project's demo

import { context } from "../../context";

export const TopNav = () => {
  const { req, res } = useContext(context);
  return (
    <TopWrapper currentPath={req.originalUrl}>
      <Logo href="/"> </Logo>
      <NavItem href="/">Home</NavItem>
      <NavItem href="/components">Components</NavItem>
      <NavItem href="https://github.com/gigantz/react-xpress">Github</NavItem>
    </TopWrapper>
  );
};
Enter fullscreen mode Exit fullscreen mode

What is planning?

I work on it and I'm trying to improve it, even it's not a good idea to use this kinda renderer for real-world app. But It would be awesome to have contributors to make its DX much better.

Future of the components

I have a plan to make it something like this


// Add components from the lib
import {Router, Middleware, Res, Get, Post} from 'react-xpress';

// Make more component based structure
<Get path="/not-found">
  <Res.Status code={404} />
  <Res.Content text="Page is not found" />
</Get>

// Using Middlewares
<Get path="/user">
  <Middleware handler={checkToken}>
    <Res.Status code={401} />
    <Res.Content json={{ status: 401, msg: "No access" }} />
  </Middleware>
  <Res.Content>
    <UserPage />
  </Res.Content>
</Get>
...
Enter fullscreen mode Exit fullscreen mode

There're more crazy ideas is in process.

Demo

Here's a working prototype - http://react-xpress-demo.herokuapp.com/
Its Github repo - https://github.com/gigantz/react-xpress

Conclusion

Feel free to contact me and contribute the project. It's just on its way and just be followed to get updates. Hopefully we'll deliver better product soon. For now you can easily clone the repo and try it.

I'm also planning to write an article about react custom renderer. I hope you like this kind of experiments.

Cheers 🎉✨,
Orkhan Jafarov

Discussion (46)

pic
Editor guide
Collapse
myzel394 profile image
Myzel394

😲😲 Sounds interesting!

But...

HOW THE F$CK DO YOU IMPLEMENT REACT ON A SERVER?!?!? :O Completely confused...

Collapse
orkhanjafarovr profile image
Orkhan Jafarov Author

LOL :D
React.js is only a structure, state and etc. It doesn't have any idea what it should render, for example you use React.js with react-dom or react-native, these two libs just rendering what they need depends on react structure.
I'll write an article about how I build this :)

Collapse
cliffordfajardo profile image
Clifford Fajardo

At high level, your compiler of choice (typescript/babel etc) will take the code and output out code that is valid on the platform your intending to run on.
So those JSX looking tags in react-express examples above will get transformed to regular javascript function calls

This is similar to how JSX tags in react get transformed to plain old javascript function calls after

TLDR: a compiler is converting this code into "valid" code that can later run in the javascript runtime.

Thread Thread
myzel394 profile image
Myzel394

Yeah that makes sense - thank you very much. But how do more complex functions work? E.g useState or useContext

Thread Thread
cliffordfajardo profile image
Clifford Fajardo • Edited

In the example below, just think of useContext as regular javascript function that returns an object, which you are then destructing to get values from for now

export const TopNav = () => {
  const { req, res } = useContext(context);
  return (
    <TopWrapper currentPath={req.originalUrl}>
      <Logo href="/"> </Logo>
      <NavItem href="/">Home</NavItem>
      <NavItem href="/components">Components</NavItem>
      <NavItem href="https://github.com/gigantz/react-xpress">Github</NavItem>
    </TopWrapper>
  );
};
Enter fullscreen mode Exit fullscreen mode

At this stage in the project it seems like this in its initial phases & that useContext is more of a nice expressive and familiar syntax being brought from the react frontend style coding to the backend and isn't doing all complex stuff like re-rendering data and stuff? (i could be wrong
CC @orkhanjafarovr )

On the frontend we use context for lots of things, one being sharing state across the application, when a value in the context changes all components subscribed to that context will update.

That example snippet above reminds of the work that the react team is doing with react server components to some degree

export const TopNav = () => {
  const { req, res } = useContext(context);
  //imagine if "req". was given a new `originalUrl` value from the client via an UPDATE request
  // I could see this creating a new HTML markup tree on the server that could then
  // be streamed to the client & being hot swapped with the older
  // markup in the DOM

  return (
    <TopWrapper currentPath={req.originalUrl}>
      <Logo href="/"> </Logo>
      <NavItem href="/">Home</NavItem>
      <NavItem href="/components">Components</NavItem>
      <NavItem href="https://github.com/gigantz/react-xpress">Github</NavItem>
    </TopWrapper>
  );
};
Enter fullscreen mode Exit fullscreen mode

See this part of the react-server components announcements

Again this high level thinking with some background in compilers without seeing source code

@orkhanjafarovr did mention this a bit more about this further down in the comments

Thread Thread
myzel394 profile image
Myzel394

Thank you, do you have any articles, videos you can recommend to learn react more in depth?

Thread Thread
orkhanjafarovr profile image
Orkhan Jafarov Author

@cliffordfajardo
Thanks for detailed answers! You're awesome, mate ✨

Yep, we can use useContext and it will work as expected, in @reactend/express you can import ReqResContext and pass into useContext to have access req, res

It's also possible to replace appHOC/appWrapper of pages and replace html template.
You can do like this (Sorry for bad naming, I'll change them later to better ones)

registerApp(ExpressApp, {
  appHOC: (Component) => (
    <ReduxProvider store={store}>
      <Component />
    </ReduxProvider>
  ),
  renderHTML: ({ head, styles, root }) => `
    <html>
      <head>
        ${head}
        ${styles}
      </head>
      <body>${root}</body>
    </html>
  `,
});

Enter fullscreen mode Exit fullscreen mode
Thread Thread
cliffordfajardo profile image
Clifford Fajardo • Edited

I like these articles:

These Github users below write lots of cool micro libraries for learning purposes, here are tiny react clone in modern JS

A general resource I like to often refer to is this one, when I'm curious about a technology & how it works under the hood

Paid resource

  • KentC Dodds has a react course (epicreact.dev/) covering nearly everything you would need. It's fairly expensive depending on how you view the investment. 5 months ago, I joined a company that uses React. I had production experience with Angular/Vue, vanillaJS and only dabbling with React. I wanted a resource that was cohesive and didn't want to spend time hunting and pieces resources together and building a fragmented view of the react ecosystem so I bought his course. I thought about it like this: Companies pay thousands of dollars for the expertise of someone like Kent C Dodd (author of several top GitHub libraries) and he's offering a course for a few hundred bucks that's replayable and in video with awesome examples..., if I can learn from one of the best that sounds amazing to me
  • Epic React
  • Kent's awesome React blog
Collapse
wchamithu profile image
wchamithu

Waiting for it

Collapse
myzel394 profile image
Myzel394

Have you already thought about a name? Maybe something like Rexpress, Exact, Expract.....?

Thread Thread
orkhanjafarovr profile image
Orkhan Jafarov Author

Actually the best option is react-express, but it's taken(
But there're options (Rexpress too!) I would like to use to name it, but a bit later :)

Collapse
alfiannsx98 profile image
Irman itu Aku

Ill waiting for it.

Collapse
e11y0t profile image
Elliot Wong

Can't wait, would be nice if there's an interactive demo on your heroku site too!

Thread Thread
orkhanjafarovr profile image
Orkhan Jafarov Author

For now there's only demo website - react-xpress-demo.herokuapp.com
That built by using the way described above

Collapse
chadalen profile image
Chad Alen

So you’re turning React into PHP aye?

Collapse
orkhanjafarovr profile image
Orkhan Jafarov Author

It’s something like, “build your server with only html skills” lol. Part of the truth, but I’m working on its updates and sandbox. Soon you’ll be able to play with that

Collapse
maciekgrzybek profile image
Maciek Grzybek

The circle of life :)

Collapse
sroehrl profile image
neoan

I am not sure if even yourself are aware of how many problems such a solution solves.
I am working on a similar concept (it's VueJS and neoan3 instead of React and express, but the principal is the same). Maybe once you solved your components this will give you some ideas: youtu.be/FBLR28qquCI

Collapse
taviroquai profile image
Marco Afonso

How better is compared to Next.js?

Collapse
orkhanjafarovr profile image
Orkhan Jafarov Author

This one is http server that described with jsx. It can render regular react dom components when you pass it to get response (like a template engine does)
I’m working on its package and it will be possible to play with that in sandbox.

Collapse
taviroquai profile image
Marco Afonso

Oh I see the difference is declaring with JSX... ok.
But at the end will do the same SSR, right?

Thread Thread
orkhanjafarovr profile image
Orkhan Jafarov Author

It gonna do only SSR for now, it's more about backend/http-server part than frontend

Thread Thread
taviroquai profile image
Marco Afonso

I like JSX... looks nice =)

Collapse
renatorib profile image
Renato Ribeiro

not the same purpose

Collapse
taviroquai profile image
Marco Afonso

Considering rendering React in server side, Nextjs does this. What Am I missing?

Thread Thread
cliffordfajardo profile image
Clifford Fajardo • Edited

This is adding another level of abstraction on top of writing vanilla javascript code to generate a server code; so instead of writing the code that looks the your typical functional that looks like an express handler, you'd write this it seems

react-express -> spits out server infrastructure code

app.get('/', function (req, res) {
  ............other boilerplate code
  res.send('hello world')
})
Enter fullscreen mode Exit fullscreen mode

Side note: I really appreciated the power of declarative languages and built a better mental model on the when/why you would do this after reading Ch2 of Designing Data Intensive Applications by Martin Kleppman

A declarative query language can be more attractive because:

  • it is typically more concise and easier to work with than an imperative API

  • But more importantly, it also hides implementation details of the underlying code making it possible for the system to introduce performance improvements without requiring any changes to userland code Other examples

    • (SQL, you write declarative queries, the engine/query optimizer handles trying to generate the most efficient code for you under the hood given the declarative code)
Collapse
andrewbrown profile image
Andrew Brown 🇨🇦

Such a good banner image

Collapse
buraksaraloglu profile image
Burak Saraloglu

They found our secret solution :(
Hide Next.js into shelters

Collapse
okrohan profile image
Rohan Salunke

This is cool! ReactPHP might be a more relevant name thought JK :P

Bdw, What rendering engine did you use?

Collapse
devhammed profile image
Hammed Oyedele • Edited

Did you know why you need to use react and react-dom when building React.js projects?

Because React just provides the logic but depends on a renderer to actually output stuff which is where react-dom comes in to render the UI to the browser DOM.

There is a lesser-known package called react-reconciler which is the package react-dom is using and it is what you will use to create your own custom React.js renderers.

Collapse
cliffordfajardo profile image
Collapse
orkhanjafarovr profile image
Orkhan Jafarov Author

Yes, that’s exactly as Hammed described. The solution is component based http server and you can pass your regular react dom components and render them. Use useContext hook to get req, res in the components you gonna pass in it

Collapse
zoedreams profile image
Collapse
danishsiraj profile image
Danish Siraj

🧐 Looks Interesting! 😮

Collapse
hanco profile image
Hanco

Interesting and really cool! I'm in stars

Collapse
chiubaca profile image
Alex Chiu

This looks like IIS lol

Collapse
orkhanjafarovr profile image
Orkhan Jafarov Author

react-sql, react-dns, and react-nginx are coming on

Collapse
rashtel profile image
Tella Abdulrasheed

Interesting

Collapse
pony profile image
Pony

This is so Cool and I have strong interest

Collapse
germangamboa95 profile image
German Gamboa

What a horrible day to have eyes.

Collapse
faraazahmad profile image
Syed Faraaz Ahmad

why though

Collapse
mohammedayman2018 profile image
Aymoon

Smart enough i like it. 👏👏
Can you tell me how to start with renderer stuff cuz i wanna dive into those stuff.

Collapse
0vortex profile image
TED Vortex (Teodor Eugen Duțulescu)

hype post just to trigger people

Collapse
bbbryan14 profile image
bryan

What's the goal here? Just have a node server serve HTML? Like ReactDomRender?

Collapse
orkhanjafarovr profile image
Collapse
marraybob profile image
Bob Marray

So you’re turning React into PHP aye?