paint-brush
Serlina: A progressive React serverside-rendering frameworkby@djyde
639 reads
639 reads

Serlina: A progressive React serverside-rendering framework

by RandyAugust 7th, 2018
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Since <a href="https://github.com/zeit/next.js/" target="_blank">Next.js</a> is a lightweight and well-experience serverside-rendering <a href="https://hackernoon.com/tagged/framework" target="_blank">framework</a>, I love using it on my side projects. It saves my time in dealing with the boilerplate <a href="https://hackernoon.com/tagged/code" target="_blank">code</a>. I write React code, and it just works.
featured image - Serlina: A progressive React serverside-rendering framework
Randy HackerNoon profile picture

Since Next.js is a lightweight and well-experience serverside-rendering framework, I love using it on my side projects. It saves my time in dealing with the boilerplate code. I write React code, and it just works.

But when I want to use it on a project that runs its own server, something happened. Next.js takes the full control of the http context when app.render is called, while our server has some effects on the context.

I read the codes of Next.js and try to find something like nextjs/core but there is not.

So I decided to make a serverside-rendering framework that without running a server. It only does the compiling, rendering your pages to string. And let your own server to render the string to the client. And keep the well-experience just like Next.js.

This is what Serlina is. Let’s see how the most simple Serlina application is like:

npm i serlina react react-dom --save

Create a folder structure like:



├── index.js # Your server├── page # Your React pages│ └── page1.js

Your server:

// index.js


const { Serlina } = require('serlina')const path = require('path')

const http = require('http')



const serlina = new Serlina({baseDir: path.resolve(__dirname, './')})














serlina.prepare().then(() => {http.createServer(async (req, res) => {res.writeHead(200, { 'Content-Type': 'text/html' })if (req.url === '/page1') {const rendered = await serlina.render('page1')res.write(rendered.string)} else {res.write('works!')}res.end()}).listen(8090)}).catch(console.error)

Your page:

// page/page1.js



export default () => {return <div>Hello Serlina!</div>}

Finally, run node index.js and visit http://localhost:8090/page1. You will see the React page.

As you can see, there are two main methods:

  • prepare() Doing the compiling works.
  • render() Render a page and get the rendered string that will be sent to the client.

Unlike Next.js, Serlina needs manually injecting the payload that you use in getInitialProps:

// index.js


const { Serlina } = require('serlina')const path = require('path')

const http = require('http')



const serlina = new Serlina({baseDir: path.resolve(__dirname, './')})




serlina.prepare().then(() => {http.createServer(async (req, res) => {+ serlina.injectPayload({ req }) // manually inject. globally

    res.writeHead(200, { 'Content-Type': 'text/html' })  
    if (req.url === '/page1') {  









+ const rendered = await serlina.render('page1', { foo: 'bar' }) // manually inject. specifically.res.write(rendered.string)} else {res.write('works!')}res.end()}).listen(8090)}).catch(console.error)

Then you can use the payload:

// page/page1.jsimport * as React from 'react'export default class Page1 extends React.Component {  static async getInitialProps ({ req }) {    return {      url: req.url    }  }  render () {    return <div>You are now at {this.props.url}</div>  }}

You can take a deep dive into Serlina through http://serlina.js.org or https://github.com/djyde/serlina

You could use it in your existing codebase easily. Just write a new router, prepare() before starting your server, render() a page and return the rendered string to the client. That is. This is why I call it progressive.

Another example is egg-serlina, which is the main reason I create Serlina. It brings the best serverside-rendering solution to Egg.js.