TLDR
- Pass the server data to the React client
props
- Because this is a view template engine, so results can be searchable by searching engines like Google (yes, we use server side rendering)
saltyshiomix / react-ssr
React SSR as a view template engine
Overview
- SSR (Server Side Rendering) as a view template engine
- Dynamic
props
- Passing the server data to the React client
props
- Suitable for
- Admin Panels
- Blogging
- Passing the server data to the React client
- Developer Experience
- Zero config of webpack and babel
- HMR (Hot Module Replacement) both scripts and even if styles when
process.env.NODE_ENV !== 'production'
- Built-in Sass (SCSS) support
Pros and Cons
Pros
Because it is just a view template engine:
- It doesn't need to have any APIs, all we have to do is to pass the server data to the client
- It supports multiple engines like
.hbs
,.ejs
and React.(ts|js)x
- We can use passport authentication as it always is
Cons
- It is not so performant, because it assembles the whole HTML on each request
- It does not support client side routing
Usage
With @react-ssr/express
Install it:
$ npm install --save @react-ssr/core @react-ssr/express express react react-dom
And add a script to your package.json like this:
…
Quick Start
Installation
$ npm install --save @react-ssr/express express react react-dom
Populate package.json
{ "scripts": { "start": "node server.js" } }
Write server.js
const express = require('@react-ssr/express'); const app = express(); app.get('/', (req, res) => { const user = { name: 'World' }; res.render('index', { user }); }); app.listen(3000, () => { console.log('> Ready on http://localhost:3000'); });
Implement views/index.jsx
import React from 'react'; export default function Index(props) { return `Hello ${props.user.name}!`; }
Run Server
$ npm start
You'll see Hello World!
Deep into Dive
1. Register jsx
and tsx
source: register.ts
const ENGINE: 'jsx' | 'tsx' = getEngine(); app.engine(ENGINE, renderFile); app.set('views', resolve(process.cwd(), viewsDir)); app.set('view engine', ENGINE); app.use(express.static(distDir));
2. Render a File (Server Side Rendering)
source: render.tsx
import { renderToString } from 'react-dom/server'; let html: string = '<!DOCTYPE html>'; let Page = require(file); // `file` is a React function component Page = Page.default || Page; html += renderToString( <Html script={`${hash}.js`}> <Page {...props} /> </Html> ); return html;
3. Bundle Scripts and Write Output
source: render.tsx
import fs from 'fs'; import template from 'art-template'; import webpack from 'webpack'; const { ufs } = require('unionfs'); const MemoryFileSystem = require('memory-fs'); const template = require('art-template'); const cwd: string = process.cwd(); template.defaults.minimize = false; const mfs = new MemoryFileSystem; ufs.use(mfs).use(fs); // union memory-fs and fs! // write file in the server memory mfs.mkdirpSync(resolve(cwd, 'react-ssr-src')); mfs.writeFileSync(resolve(cwd, `react-ssr-src/entry.jsx`), template(resolve(__dirname, '../page.jsx'), { props })); mfs.writeFileSync(resolve(cwd, `react-ssr-src/page.jsx`), template(file, props)); // compile in the server memory! const compiler: webpack.Compiler = webpack(configure(hash, ext, distDir)); compiler.inputFileSystem = ufs; compiler.outputFileSystem = mfs; compiler.run((err: any) => { if (err) { console.error(err.stack || err); if (err.details) { console.error(err.details); } return; } }); // read the results from memory file system // write the results to the real file system await outputFileSync('result.js', mfs.readFileSync(cache).toString());
That's it!
Final output html is like this:
<!DOCTYPE html> <html> <body> <div id="app"> <p>Hello World!</p> </div> <script src="/c834ab9b47260a08d695f59ba1a5b24d.js"></script> </body> </html>
Ending
But I love to use NEXT.js! lol
Top comments (6)
I am getting error at "Run Server" part.
" Cannot find module '@react-ssr/core/dist/document' "
Can't see any result in google either :(
Have you installed @react-ssr/core?
If you want to see full information, please check out GitHub README, not this post :)
Aaaah :(((( Sorry. I only installed @react-ssr/express. I thought it was a dependency and will install by itself. Now it is OK. Thank you for fast reply
No problem, the latest information is at GitHub readme :)
Formally it's true that @react-ssr/express includes @react-ssr/core, but now it is separated for many reasons.
const app = express();
^
TypeError: express is not a function
Why is it like this?????
register.ts in point 1 is broken