# genesis-core

提供了生产环境运行所需的功能,所以它在生产环境时,总是保证依赖是最小的。在开发环境时,需要和 @fmfe/genesis-compiler 配合使用

# 安装

npm install @fmfe/genesis-core

# SSR 选项

import { SSR } from '@fmfe/genesis-core';
const ssr = new SSR({
    // 选项
});

# name

  • 说明:应用名称,如果你的页面有多个ssr实例,需要使用不同的名词区分它。
  • 类型:string
  • 默认值:ssr-genesis
  • 例子:
const ssr = new SSR({
    name: 'ssr-demo'
});

# isProd

  • 说明:设置程序的运行模式
  • 类型:boolean
  • 默认值:process.env.NODE_ENV === 'production'
  • 例子:
const ssr = new SSR({
    isProd: process.env.NODE_ENV === 'production'
});

# cdnPublicPath

  • 说明:所有的静态资源,如果要添加 CDN 地址,直接在这里添加即可,仅在生产环境有效
  • 类型:string
  • 默认值:``
  • 例子:
const ssr = new SSR({
    cdnPublicPath: '//cdn.xxx.com'
});

# build.baseDir

  • 说明:应用的根目录:在此基础上获取对应的 srcdist目录
  • 类型:string
  • 默认值:path.resolve()
  • 例子:
const ssr = new SSR({
    build: {
        baseDir: path.resolve(__dirname, './')
    }
});

# build.outputDir

  • 说明:应用的编译目录,你可以使用相对于项目的路径,也可以使用绝对的路径
  • 类型:string
  • 默认值:应用根目录/dist/
  • 例子:
const ssr = new SSR({
    build: {
        outputDir: path.resolve(__dirname, './dist')
    }
});

# build.transpile

  • 说明:默认的情况下,webpack loader会忽略 node_modules 目录的打包,通过配置 build.transpile 来打包你的程序,在开发插件的时候,特别有用
  • 类型:string
  • 默认值:[]
  • 例子:
const ssr = new SSR({
    build: {
        transpile: [/src/]
    }
});

# build.alias

  • 说明:webpack的别名设置
  • 类型:{[x: string]: string}
  • 默认值:{}
const ssr = new SSR({
    build: {
        alias: {
            '@': path.resolve(__dirname, './src')
        }
    }
});

# build.browsers

{
    client: ['ie >= 9', 'ios >= 5', 'android >= 4.0'],
    server: [`node >= ${process.versions.node}`]
}

例子:

import process from 'process';

const ssr = new SSR({
    build: {
        browsers: {
            client: ['ie >= 9', 'ios >= 5', 'android >= 4.0'],
            server: [`node >= ${process.versions.node}`]
        }
    }
});

# build.template

  • 说明:SSR 和 CSR 渲染的模板的地址,它使用了 ejs (opens new window) 模板引擎,如果你配置了模板地址,就会使用你的模板地址,否则会使用默认模板
  • 类型:string
  • 默认值:path.resolve(this.srcDir, 'index.html')
  • 默认模板:
<!DOCTYPE html>
<html>

<head>
    <title>Vue SSR for Genesis</title><%-style%>
</head>

<body>
<%-html%>
<%-scriptState%>
<%-script%>
</body>

</html>

例子:

import path from 'path';

const ssr = new SSR({
    build: {
        template: path.resolve(__dirname, './index.html')
    }
});

# SSR 属性

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

const ssr = new SSR({
    // ...可选项
});

// ssr.属性

# ssr.Renderer

说明:一个SSR的渲染器,详情请看 Renderer

# ssr.options

说明:你传入的选项
类型:Genesis.Options

# ssr.plugin

说明:插件系统,详情请看 Plugin
类型:Genesis.PluginManage

# ssr.isProd

说明:判断是否是生产环境
默认值:process.env.NODE_ENV === 'production'
类型:string

# ssr.name

说明:应用的名称,options.name可以修改这个值
类型:string

# ssr.publicPath

说明:应用静态资源的基本路径,会影响 webpack 的相关配置,options.name可以修改这个值
类型:string

# ssr.baseDir

说明:应用的基本目录,options.baseDir可以修改这个值
默认值:path.resolve() 类型:string

# ssr.outputDir

说明:应用的编译输出目录,options.build.outputDir可以修改这个值
默认值:编译输出目录/应用名称/
类型:string

# ssr.srcDir

说明:源码目录
默认值:应用根目录/src/ 类型:string

# ssr.srcIncludes

说明:webpack loader 的 includes会读取配置,options.build.transpile可以添加你需要打包的文件或者目录
类型:string

# ssr.transpile

说明:options.transpile的配置
类型:string

# ssr.entryClientFile

说明:客户端的入口文件
默认值:应用根目录/src/entry-server
类型:string

# ssr.entryServerFile

说明:服务端的入口文件
默认值:应用根目录/src/entry-server
类型:string

# ssr.outputClientManifestFile

说明:客户端的映射文件的输出路径
默认值:编译输出目录/应用名称/server/vue-ssr-client-manifest.json
类型:string

# ssr.outputServerBundleFile

说明:服务端的映射文件的输出路径
默认值:编译输出目录/应用名称/server/vue-ssr-server-bundle.json
类型:string

# ssr.templateFile

说明:ssr 和 csr 的模块入口地址options.build.template可以修改这个值
类型:string
默认值:应用根目录/src/index.html

# ssr.outputTemplateFile

说明:模板文件的输出地址
类型:string
默认值:编译输出目录/应用名称/server/index.html

# SSR 方法

# ssr.getBrowsers

说明:获取 browsers 的配置
签名:

ssr.getBrowsers(env: keyof Genesis.Browsers): Genesis.Browserslist;

例子:

ssr.getBrowsers('client');
ssr.getBrowsers('server');

# ssr.createRenderer

说明:创建一个SSR的渲染器,一般来说,你会在生产环境中使用
签名:

ssr.createRenderer(options?: Genesis.RendererOptions): Renderer;

例子:

const renderer = ssr.createRenderer();
const app = express();

// 静态资源挂载
app.use(
    renderer.staticPublicPath,
    express.static(renderer.staticDir, {
        immutable: true,
        maxAge: '31536000000'
    })
);
// SSR 渲染中间件
app.use(renderer.renderMiddleware());

# Renderer 属性

# renderer.ssr

说明:当前的SSR实例

# renderer.staticPublicPath

说明:静态资源文件的基本路径,等同于ssr.publicPath,在生产环境的时候会使用到

# renderer.staticDir

说明:静态资源文件所在的目录地址,等同于ssr.staticDir,在生产环境的时候会使用到

# renderer.clientManifest

说明:客户端的文件清单,如果你需要做 PWA 的时候,可以拿到客户端所有的资源清单,进行预加载

export interface ClientManifest {
    publicPath: string;
    all: string[];
    initial: string[];
    async: string[];
    modules: { [key: string]: number[] };
}

# Renderer 方法

# renderer.hotUpdate

说明:热更新接口,一般来说只作为开发环境的热更新使用
签名:

renderer.hotUpdate(options?: Genesis.RendererOptions): void;

# renderer.render

说明:最底层的渲染方法,后面的 renderer.renderJsonrenderer.renderHtmlrenderer.renderMiddleware 都是基于它进行二次封装。
签名:

export interface RenderOptions<
    T extends Genesis.RenderMode = Genesis.RenderMode
> {
    req?: IncomingMessage;
    res?: ServerResponse;
    mode?: T;
    url?: string;
    id?: string;
    name?: string;
    automount?: boolean;
    state?: {
        [x: string]: any;
    };
}
render<T extends Genesis.RenderMode = Genesis.RenderMode>(
    options?: Genesis.RenderOptions<T>
): Promise<Genesis.RenderResul>;

# req

  • 说明:当前请求体的对象
  • 类型:IncomingMessage
  • 默认值:undefined

# res

  • 说明:当前响应体的对象
  • 类型:ServerResponse
  • 默认值:undefined

# mode

  • 说明:使用什么渲染模式
  • 类型:string
  • 默认值:ssr-html
  • 可选值:"csr-json" | "ssr-json" | "csr-html" | "ssr-html"

# url

  • 说明:当前渲染的地址,你需要和 vue-router 配合使用
  • 类型:string
  • 默认值:/

# id

  • 说明:当前渲染的id,默认由 md5(name + url) 生成
  • 类型:string
  • 默认值:md5(name + url)

# name

  • 说明:当前应用的名称,如果你需要做微前端、微服务,则需要定义不同的名字
  • 类型:string
  • 默认值:ssr-genesis

# automount

  • 说明:js加载完成后,是否自动安装应用,远程加载的时候,你可能不需要自动安装,可以将其设置为 false
  • 类型:boolean
  • 默认值:true

# state

  • 说明:应用的状态,如果你需要在服务端预取数据,可以在这里存储,也可以和 vuex 配合使用。
  • 类型:object
  • 默认值:{}

# renderer.renderJson

说明:渲染一个json,可以利用这个API开发出微前端应用所需的接口
签名:

renderJson(
    options?: Genesis.RenderOptions<Genesis.RenderModeJson>
): Promise<Genesis.RenderResultJson>;

# renderer.renderHtml

说明:渲染一个html
签名:

renderHtml(
    options?: Genesis.RenderOptions<Genesis.RenderModeHtml>
): Promise<Genesis.RenderResultHtml>;

# renderer.renderMiddleware

说明:渲染的中间件,只要是类似于express的中间件设计,都可以直接使用,你可以通过Plugin的方式来调整应该渲染成json或html
签名:

renderMiddleware(
    req: IncomingMessage,
    res: ServerResponse,
    next: (err: any) => void
): Promise<void>;

# Renderer 例子

# 生成 HTML

说明:下面举了一个生成静态html的例子

import { IncomingMessage, ServerResponse } from 'http';
import { Socket } from 'net';
import { SSR } from '@fmfe/genesis-core';

const ssr = new SSR();
const renderer = ssr.createRenderer();

const render = (url: string) => {
    const req = new IncomingMessage(new Socket());
    const res = new ServerResponse(req);
    req.url = url;
    return renderer.renderHtml({ req, res, mode: 'ssr-html' });
};

render('/home').then((res) => {
    console.log(res.data); // 渲染成html,你可以保存起来,生成一个静态网站
});

# Plugin 插件

# 钩子说明

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

class MyPlugin extends Plugin {

    /**
     * 编译之前执行
     */
    public beforeCompiler(type: Genesis.CompilerType) {}
    /**
     * 修改 webpack 的配置
     */
    public chainWebpack(config: Genesis.WebpackHookParams) {}
    /**
     * 修改 babel 的配置
     */
    public babel(config: Genesis.BabelConfig) {}
    /**
     * 修改 postcss-loader 的配置
     */
    public postcss(config: PostcssOptions) {}
    /**
     * 编译完成之后执行
     */
    public afterCompiler(type: Genesis.CompilerType) {}
    /**
     * 渲染之前执行
     */
    public renderBefore(renderContext: Genesis.RenderContext) {}
    /**
     * 渲染之后执行
     */
    public renderCompleted(renderContext: Genesis.RenderContext) {}
}

const ssr = new SSR();
ssr.plugin.use(new MyPlugin(ssr));

# 外置化依赖

说明:如果你正在开发大型的应用,需要提供远程组件加载,避免项目与项目之间重复加载同样的内容,那么外置化依赖是必不可少的

class MyPlugin extends Plugin {
    /**
     * 修改webpack的配置
     */
    public chainWebpack({ config, target }: Genesis.WebpackHookParams) {
        if (target === 'client') {
            config.externals({
                vue: 'Vue',
                'vue-router': 'VueRouter',
                axios: 'axios'
            });
        }
    }

    /**
     * 渲染之前执行
     */
    public renderBefore(renderContext: Genesis.RenderContext) {
        renderContext.data.script +=
            '<script src="https://cdn.jsdelivr.net/npm/vue@' + require('vue').version + '" defer></script>' +
            '<script src="https://cdn.jsdelivr.net/npm/vue-router@' + require('vue-router').version + '" defer></script>' +
            '<script src="https://cdn.jsdelivr.net/npm/axios@' + require('axios').version + '" defer></script>';
    }
}