npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@react-ssr-easy/nestjs-express

v0.24.1-beta.1

Published

React SSR as a view template engine

Downloads

1

Readme

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
  • 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

Install it:

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

# install @react-ssr/nestjs-express
$ npm install --save @react-ssr/core @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"
  }
}

Then, populate files below inside your project:

tsconfig.json:

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

tsconfig.server.json:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "commonjs",
    "outDir": "dist"
  },
  "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 () => {
  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`);
  });
})();

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;

Finally, just run npm start and go to http://localhost:3000, and 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',
  distDir: '.ssr',
  viewsDir: 'views',
  staticViews: [],
  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#distDir

The place where react-ssr generates 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#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/basic-custom-views

ssr.config.js#staticViews

If specified, react-ssr generates html cache when production:

module.exports = {
  staticViews: [
    'auth/login',
    'auth/register',
    'about',
  ],
};

ssr.config.js#webpack()

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

Custom process.env.NODE_ENV

If you set process.env.REACT_SSR_ENV, you can separate process.env.NODE_ENV from react-ssr:

package.json

{
  "scripts": {
    "start": "cross-env NODE_ENV=k8s REACT_SSR_ENV=production node dist/main.js"
  }
}

Custom Babel Config

We can extends its default .babelrc like this:

.babelrc:

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

A working example is here: examples/basic-custom-babelrc

Custom App

Just put _app.tsx into the views root:

views/_app.tsx:

// we can import global styles or use theming
import '../styles/global.scss';

const App = (props) => {
  // yes, this `props` contains data passed from the server
  // and also we can inject additional data into pages
  const { children, ...rest } = props;

  // we can wrap this PageComponent for persisting layout between page changes
  const PageComponent = children;

  return <PageComponent {...rest} />;
};

export default App;

A working example is here:

Custom Document

Just put _document.tsx into the views root:

views/_document.tsx:

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

export default class extends Document {
  render() {
    return (
      <html lang="en">
        <Head>
          <title>Default Title</title>
          <meta charSet="utf-8" />
          <meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
          <link rel="shortcut icon" href="/favicon.ico" />
        </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.tsx:

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

export default Index;

A working example is here: examples/basic-custom-document

Dynamic Head

We can use the Head component in any pages:

views/index.tsx:

import React from 'react';
import { Head } from '@react-ssr/nestjs-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

Non CSS-in-JS framework

Like semantic-ui, non CSS-in-JS frameworks are supported without extra configuration.

All we have to do is to load global CSS in _document or each page:

views/_document.tsx:

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

export default class extends Document {
  render() {
    return (
      <html>
        <Head>
          <title>A Sample of Semantic UI React</title>
          <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/[email protected]/dist/semantic.min.css" />
        </Head>
        <body>
          <Main />
        </body>
      </html>
    );
  }
}

With Ant Design

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

And then, populate .babelrc in your project root:

{
  "presets": [
    "@react-ssr/express/babel"
  ],
  "plugins": [
    [
      "import",
      {
        "libraryName": "antd",
        "style": "css"
      }
    ]
  ]
}

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

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 Material UI

We can use material-ui without extra configuration.

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

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

Examples

@react-ssr/express

.jsx

.tsx

@react-ssr/nestjs-express

Real World Examples

Articles

Introducing an Alternative to NEXT.js

[Express] React as a View Template Engine?

Related

reactjs/express-react-views

Contact