0.1.145 • Published 5 years ago

@react-ssr/express-engine-jsx v0.1.145

Weekly downloads
18
License
MIT
Repository
github
Last release
5 years ago

Overview

  • SSR (Server Side Rendering) as a view template engine
  • Passing the server data to the client props
  • Dynamic props without caring about SSR
    • Suitable for dynamic routes like blogging
  • Dynamic Head component
  • HMR when process.env.NODE_ENV !== 'production'

Usage

With @react-ssr/express

Install it:

$ npm install --save @react-ssr/express express react react-dom

And add a script to your package.json like this:

{
  "scripts": {
    "start": "node server.js"
  }
}

Populate files below inside your project:

./.babelrc

{
  "presets": [
    "@react-ssr/express/babel"
  ]
}

./server.js

const express = require('express');
const register = require('@react-ssr/express/register');

const app = express();

(async () => {
  // register `.jsx` or `.tsx` as a view template engine
  await register(app);

  app.get('/', (req, res) => {
    const message = 'Hello World!';
    res.render('index', { message });
  });

  app.listen(3000, () => {
    console.log('> Ready on http://localhost:3000');
  });
})();

./views/index.jsx

export default function Index({ message }) {
  return <p>{message}</p>;
}

Then just run npm start and go to http://localhost:3000.

You'll see Hello World!.

With @react-ssr/nestjs-express

Install it:

# install NestJS dependencies
$ npm install --save @nestjs/core @nestjs/common @nestjs/platform-express

# install @react-ssr/nestjs-express
$ npm install --save @react-ssr/nestjs-express react react-dom

And add a script to your package.json like this:

{
  "scripts": {
    "start": "ts-node --project tsconfig.server.json server/main.ts"
  }
}

Populate files below inside your project:

./.babelrc

{
  "presets": [
    "@react-ssr/nestjs-express/babel"
  ]
}

./tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "jsx": "preserve",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "strict": true,
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "isolatedModules": true,
    "resolveJsonModule": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true
  },
  "exclude": [
    "node_modules",
    ".ssr"
  ]
}

./tsconfig.server.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "commonjs"
  },
  "include": [
    "server"
  ]
}

./server/main.ts

import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import register from '@react-ssr/nestjs-express/register';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);

  // register `.tsx` as a view template engine
  await register(app);

  app.listen(3000, async () => {
    console.log(`> Ready on http://localhost:3000`);
  });
}

bootstrap();

./server/app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';

@Module({
  controllers: [
    AppController,
  ],
})
export class AppModule {}

./server/app.controller.ts

import {
  Controller,
  Get,
  Render,
} from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Render('index') // this will render `views/index.tsx`
  public showHome() {
    const user = { name: 'NestJS' };
    return { user };
  }
}

./views/index.tsx

interface IndexProps {
  user: any;
}

const Index = ({ user }: IndexProps) => {
  return <p>Hello {user.name}!</p>;
};

export default Index;

Then just run npm start and go to http://localhost:3000, you'll see Hello NestJS!.

Configuration (ssr.config.js)

Here is the default ssr.config.js, which is used by react-ssr when there are no valid values:

module.exports = {
  id: 'default',
  viewsDir: 'views',
  distDir: '.ssr',
  webpack: (config /* webpack.Configuration */, env /* 'development' | 'production' */) => {
    return config;
  },
};

ssr.config.js#id

The id of UI framework. (default: default)

It can be ignored only when the project does not use any UI frameworks.

Supported UI frameworks are:

For example, if we want to use emotion, ssr.config.js is like this:

module.exports = {
  id: 'emotion',
};

ssr.config.js#viewsDir

The place where we put views. (default: views)

A function res.render('xxx') will render views/xxx.jsx or views/xxx.tsx.

A working example is here: examples/custom-views

ssr.config.js#distDir

The place where react-ssr outputs production results. (default: .ssr)

If we use TypeScript or any other library which must be compiled, the config below may be useful:

module.exports = {
  // dist folder should be ignored by `.gitignore`
  distDir: 'dist/.ssr',
};

ssr.config.js#webpack()

module.exports = {
  webpack: (config /* webpack.Configuration */, env /* 'development' | 'production' */) => {
    // we can override default webpack config here
    return config;
  },
};

For example, let's consider we want to import css files directly:

views/index.jsx

import '../styles/index.css';

styles/index.css

body {
  background-color: burlywood;
}

Then, we must override the default webpack config like this:

ssr.config.js

module.exports = {
  webpack: (config, env) => {
    config.module.rules = [
      ...(config.module.rules),
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          'css-loader',
        ],
      },
    ];
    return config;
  },
};

A working example is here: examples/basic-css-import

Custom Document

Just put _document.jsx or _document.tsx into the views root:

./views/_document.jsx

import React from 'react';
import {
  Document,
  Head,
  Main,
} from '@react-ssr/express';

export default class extends Document {
  render() {
    return (
      <html>
        <Head>
          <title>Default Title</title>
        </Head>
        <body>
          <Main />
        </body>
      </html>
    );
  }
};

Note: Please put <Main /> component directly under <body> tag AND don't wrap <Main /> component with another components because this is a hydration target for the client.

And then, use it as always:

./views/index.jsx

const Index = (props) => {
  return <p>Hello Layout!</p>;
};

export default Index;

A working example is here: examples/custom-document

Dynamic Head

We can use the Head component anyware:

./views/index.jsx

import React from 'react';
import { Head } from '@react-ssr/express';

const Index = (props) => {
  return (
    <React.Fragment>
      <Head>
        <title>Dynamic Title</title>
        <meta name="description" content="Dynamic Description" />
      </Head>
      <p>Of course, SSR Ready!</p>
    </React.Fragment>
  );
};

export default Index;

A working example is here: examples/basic-dynamic-head

Supported UI Framework

With Emotion

In order to enable SSR, we must install these packages:

And then, populate .babelrc in your project root:

{
  "presets": [
    "@react-ssr/express/babel"
  ],
  "plugins": [
    "emotion"
  ]
}

A working example is here: examples/with-jsx-emotion

With styled-components

In order to enable SSR, we must install babel-plugin-styled-components as devDependencies.

And then, populate .babelrc in your project root:

{
  "presets": [
    "@react-ssr/express/babel"
  ],
  "plugins": [
    "styled-components"
  ]
}

A working example is here: examples/with-jsx-styled-components

With Material UI

We can use material-ui without extra configuration.

A working example is here: examples/with-jsx-material-ui

With Ant Design

WIP

TypeScript Support

To enable TypeScript engine (.tsx), just put tsconfig.json in your project root directory.

The code of TypeScript will be like this:

./package.json

{
  "scripts": {
    "start": "ts-node server.ts"
  }
}

./server.ts

import express, { Request, Response } from 'express';
import register from '@react-ssr/express/register';

const app = express();

(async () => {
  // register `.tsx` as a view template engine
  await register(app);

  app.get('/', (req: Request, res: Response) => {
    const message = 'Hello World!';
    res.render('index', { message });
  });

  app.listen(3000, () => {
    console.log('> Ready on http://localhost:3000');
  });
})();

./views/index.tsx

interface IndexProps {
  message: string;
}

export default function Index({ message }: IndexProps) {
  return <p>{message}</p>;
}

Packages

packageversion
@react-ssr/core@react-ssr/core downloads
@react-ssr/express@react-ssr/express downloads
@react-ssr/nestjs-express@react-ssr/nestjs-express downloads

Examples

Starters

Develop examples/<example-folder-name>

$ git clone https://github.com/saltyshiomix/react-ssr.git
$ cd react-ssr
$ yarn
$ yarn dev <example-folder-name>

Articles

The React View Template Engine for Express

[Express] React as a View Template Engine?

Related

reactjs/express-react-views

0.1.145

5 years ago

0.1.144

5 years ago

0.1.143

5 years ago

0.1.142

5 years ago

0.1.141

5 years ago

0.1.140

5 years ago

0.1.139

5 years ago

0.1.138

5 years ago

0.1.137

5 years ago

0.1.136

5 years ago

0.1.135

5 years ago

0.1.134

5 years ago

0.1.133

5 years ago

0.1.132

5 years ago

0.1.131

5 years ago

0.1.130

5 years ago

0.1.129

5 years ago

0.1.128

5 years ago

0.1.127

5 years ago

0.1.126

5 years ago

0.1.125

5 years ago

0.1.124

5 years ago

0.1.123

5 years ago

0.1.122

5 years ago

0.1.121

5 years ago

0.1.120

5 years ago

0.1.119

5 years ago

0.1.118

5 years ago

0.1.117

5 years ago

0.1.116

5 years ago

0.1.115

5 years ago

0.1.114

5 years ago

0.1.113

5 years ago

0.1.112

5 years ago

0.1.111

5 years ago

0.1.110

5 years ago

0.1.109

5 years ago

0.1.108

5 years ago

0.1.107

5 years ago

0.1.106

5 years ago

0.1.105

5 years ago

0.1.104

5 years ago

0.1.103

5 years ago

0.1.102

5 years ago

0.1.101

5 years ago

0.1.100

5 years ago

0.1.99

5 years ago

0.1.98

5 years ago

0.1.97

5 years ago

0.1.96

5 years ago

0.1.95

5 years ago

0.1.94

5 years ago

0.1.93

5 years ago

0.1.92

5 years ago

0.1.91

5 years ago

0.1.90

5 years ago

0.1.89

5 years ago

0.1.88

5 years ago

0.1.87

5 years ago

0.1.86

5 years ago

0.1.85

5 years ago

0.1.84

5 years ago

0.1.83

5 years ago

0.1.82

5 years ago

0.1.81

5 years ago

0.1.80

5 years ago

0.1.79

5 years ago

0.1.78

5 years ago

0.1.77

5 years ago

0.1.76

5 years ago

0.1.75

5 years ago

0.1.74

5 years ago

0.1.73

5 years ago

0.1.72

5 years ago

0.1.71

5 years ago

0.1.70

5 years ago

0.1.69

5 years ago

0.1.68

5 years ago

0.1.67

5 years ago

0.1.66

5 years ago

0.1.65

5 years ago

0.1.64

5 years ago

0.1.63

5 years ago

0.1.62

5 years ago

0.1.61

5 years ago

0.1.60

5 years ago

0.1.59

5 years ago

0.1.58

5 years ago

0.1.57

5 years ago

0.1.56

5 years ago

0.1.55

5 years ago

0.1.54

5 years ago

0.1.53

5 years ago

0.1.52

5 years ago

0.1.51

5 years ago

0.1.50

5 years ago

0.1.49

5 years ago

0.1.48

5 years ago

0.1.47

5 years ago

0.1.46

5 years ago

0.1.45

5 years ago

0.1.44

5 years ago

0.1.43

5 years ago

0.1.42

5 years ago

0.1.41

5 years ago

0.1.40

5 years ago

0.1.39

5 years ago

0.1.38

5 years ago

0.1.37

5 years ago

0.1.36

5 years ago

0.1.35

5 years ago

0.1.34

5 years ago

0.1.33

5 years ago

0.1.32

5 years ago

0.1.31

5 years ago

0.1.30

5 years ago

0.1.29

5 years ago

0.1.28

5 years ago

0.1.27

5 years ago

0.1.26

5 years ago

0.1.25

5 years ago

0.1.24

5 years ago

0.1.23

5 years ago

0.1.22

5 years ago

0.1.21

5 years ago

0.1.20

5 years ago

0.1.19

5 years ago

0.1.18

5 years ago

0.1.17

5 years ago

0.1.16

5 years ago

0.1.15

5 years ago

0.1.14

5 years ago

0.1.13

5 years ago

0.1.12

5 years ago

0.1.11

5 years ago

0.1.10

5 years ago

0.1.9

5 years ago

0.1.8

5 years ago

0.1.7

5 years ago

0.1.6

5 years ago

0.1.5

5 years ago

0.1.4

5 years ago

0.1.3

5 years ago

0.1.2

5 years ago

0.1.1

5 years ago

0.1.0

5 years ago

0.0.18

5 years ago

0.0.17

5 years ago

0.0.16

5 years ago

0.0.15

5 years ago

0.0.14

5 years ago

0.0.13

5 years ago

0.0.12

5 years ago

0.0.11

5 years ago

0.0.10

5 years ago

0.0.9

5 years ago

0.0.8

5 years ago

0.0.7

5 years ago

0.0.6

5 years ago

0.0.5

5 years ago

0.0.4

5 years ago

0.0.3

5 years ago

0.0.2

5 years ago

0.0.1

5 years ago