# Quick Start

Genesis is a lightweight Vue SSR plug-in from the birth of Followme 5.0. It is always not tied to any framework. You can freely choose Express, Koa, Egg, nest and other server-side frameworks to use.

# Installation

TIP

In order to reduce the size of production dependencies, Genesis is deliberately split into two packages, @fmfe/genesis-core is responsible for the core SSR rendering logic, and @fmfe/genesis-compiler is responsible for use in the development and compilation stages, It is not needed in a production environment

npm install @fmfe/genesis-core
npm install @fmfe/genesis-compiler -D

# TS Runtime

TIP

All the examples in the document are based on ts. For how to run ts on Node, please understand ts-node. If you don’t want to use ts, you can skip this step, just change the example of the document to js syntax

npm install ts-node typescript -g

# HTTP Service

TIP

Because Genesis is just an SSR library, it does not have the ability to create HTTP services, so here we also need to install Express. If you choose another framework, you can skip this step and convert the code in the example into the code of the corresponding framework

npm install express

# Example Implementation

The following will implement an example of the most basic SSR project, which will use three core concepts SSRBuildRenderer

# Directory Structure

Create the following four files in the root directory of your project, of course, you can also use other file names

.
├── genesis.ts       // Core business logic entry
├── genesis.build.ts // Compile production environment code
├── genesis.dev.ts   // Dev environment startup entry
├── genesis.prod.ts  // Production environment start entrance
├── tsconfig.json    // TS Configuration file
└── package.json

# genesis.ts

import express from 'express';
import { SSR, Renderer } from '@fmfe/genesis-core';

/**
 * Create an application
 */
export const app = express();

/**
 * Create an SSR instance
 */
export const ssr = new SSR();

/**
 * After getting the renderer, start the application
 */
export const startApp = (renderer: Renderer) => {
    /**
     * Use the default rendering middleware for rendering, you can also call the lower-level renderer.renderJson and renderer.renderHtml to achieve rendering
     */
    app.use(renderer.renderMiddleware);
    /**
     * Listening port
     */
    app.listen(3000, () => console.log(`http://localhost:3000`));
};

Development environment and production environment, common startup logic

# genesis.build.ts

import { Build } from '@fmfe/genesis-compiler';
import { ssr } from './genesis';

const start = () => {
    /**
     * Create a compiled instance
     */
    const build = new Build(ssr);
    /**
     * Start executing the compiler and build the production environment application package
     */
    return build.start();
};
start();

Compile the code required for the production environment

# genesis.dev.ts

import { Watch } from '@fmfe/genesis-compiler';
import { ssr, app, startApp } from './genesis';

const start = async () => {
    /**
     * Create an observation instance
     */
    const watch = new Watch(ssr);
    /**
     * Start observation
     */
    await watch.start();
    /**
     * Get the corresponding renderer on the observation instance
     */
    const renderer = watch.renderer;
    /**
     * Static resource middleware
     */
    app.use(watch.devMiddleware);
    /**
     * Hot update middleware
     */
    app.use(watch.hotMiddleware);
    /**
     * After getting the renderer, start the application
     */
    startApp(renderer);
};
start();

Development environment, program startup entry

# genesis.prod.ts

import express from 'express';
import { ssr, app, startApp } from './genesis';

/**
 * Production environment, we have compiled the application, so you can directly create a renderer here
 */
const renderer = ssr.createRenderer();

/**
 * In the production environment, static resources are based on the file name generated by the content hash,
 * so when setting a static directory here, you can set a strong cache
 */
app.use(
    renderer.staticPublicPath,
    express.static(renderer.staticDir, {
        immutable: true,
        maxAge: '31536000000'
    })
);

/**
 * Launch the application
 */
startApp(renderer);

Production environment start entrance

# tsconfig.json

{
    "compilerOptions": {
        "target": "esnext",
        "module": "esnext",
        "moduleResolution": "node",
        "esModuleInterop": true,
        "experimentalDecorators": true,
        "allowJs": true,
        "sourceMap": true,
        "strict": true,
        "noEmit": true,
        "noUnusedLocals": true,
        "skipLibCheck": true,
        "noImplicitAny": false,
        "resolveJsonModule": true,
        "baseUrl": "./",
        "typeRoots": [
            "./types/*"
        ],
        "types": [
            "@types/node"
        ],
        "allowSyntheticDefaultImports": true
    },
    "ts-node": {
        "compilerOptions": {
            "target": "es2018",
            "module": "commonjs",
            "moduleResolution": "node",
            "allowSyntheticDefaultImports": true,
            "declaration": true,
            "esModuleInterop": true,
            "outDir": "../dist"
        }
    }
}

Here is a common ts configuration, you can adjust it according to your needs

# package.json

{
  "scripts": {
    "dev": "ts-node genesis.dev -p=tsconfig.json",
    "build": "rm -rf dist && NODE_ENV=production ts-node genesis.build -p=tsconfig.json",
    "start": "NODE_ENV=production ts-node genesis.prod -p=tsconfig.json"
  }
}
# Development environment startup
npm run dev
# Packaging production environment code
npm run build
# Production environment operation
npm run start

Add common commands to npm script, which allows us to quickly start the application Run the npm run dev command and visit http://localhost:3000 in the browser

# Example source code