Server Render
Render service in the server
Vise provide express-server to host SSR service by default, and also support any custom Node.js HTTP server as long as it implements Vise’s SSR bundle API.
If you need to implements your own HTTP SSR sever, you could continue reading.
App bundle
After execute vise build
in a Vise app directory, the generated bundles will be like this:
app-my-project
└── dist
├── client
│ ├── index.html
│ └── assets
│ ├── module.hash.js
│ ├── module.hash.css
│ ├── some.png
│ └── ...
└── server
├── ssr-manifest.json
├── server-hooks.js
└── entry-server.js
Files in client
directory are used by end user’s browser, and it’s best to be deployed on CDN. In fact the index.html
is the entry to a CSR SPA, which can be used as a fallback url when SSR service fails. If you want to generate CSR entries for all pages, generateCsrHtml
in vise.config.ts could be used.
In the server
directory, there is a ssr-manifest.json
which contains module’s dependencies information, a server-hooks.js
which contains app’s server logic, a entry-server.js
which is entry of the UI library framework’s server render bundle.
Using Render bundle in TypeScript
Server can import as a ViseRenderBundle
:
import type { ViseRenderBundle } from 'vise-ssr';
const bundleOfApp = await import('/path/to/bundles/entry-server.ts') as ViseRenderBundle;
API of Render bundle
Render bundle provide the following API from ViseRenderBundle
type:
type ViseRenderBundle = {
render: SsrBundleRender;
};
The render
function accepts an RenderContext
type parameter, returns a Promise<SsrBundleResult>
, the render hooks use the result to compose the final RenderResult
;
Control HTML generation from UI render bundle
The SsrBundleResult
, which is the server render output, is as following:
type SsrContext = {
meta: RenderContextMeta,
extra: JSONObject,
};
type SsrBundleSuccess = Record<'html', string> & SsrContext;
type SsrBundleResult = SsrBundleSuccess | RenderError;
Except the main render result html
, there are also the SsrContext
which controls how the page is generated. Generally developer puts their logic in the UI library page code, so it’s convenient to control the overall HTML through change SsrContext
. For example, page title is generated from context.meta.title
, Vue user can change the context through useSSRContext
hook, React user can use the updateContext
function pass from page’s attributes.
defineComponent({
setup() {
const context = useSSRContext();
context.meta.title = 'My Page Title';
},
...
});
If context needs to be updated after render, user can update the RenderContext then call refillRenderResult
again.
Accessing data from server hooks
In almost all server hooks, data could be changed and passed in the RenderContext
. Data defined by Vise is in RenderContext.meta
, user define data is passed in RenderContext.extra
. Those data will be passed to UI library’s SSRContext.
export async function render(renderContext: RenderContext): Promise<SsrBundleResult> {
// ...
const ssrContext: SSRContext = {
meta: renderContext.meta,
extra: renderContext.extra,
};
UI library can access data in the RenderContext and update them. Mind the extra has a type of JSONValue
, only simple literal value allowed.
Deploy Service
After implements APIs above and tapable hooks’s HookLifeCycle, now the HTTP server is able to process user’s request, render the HTML and provide SSR service.