8.14.5 Renderer 选项
template
为整个页面的 HTML 提供一个模板。此模板应包含注释
<!--vue-ssr-outlet-->
,作为渲染应用内容的占位符。
模板还支持使用渲染上下文 (render context) 进行基本插值:
- 使用双花括号 (double-mustache) 进行 HTML 转义插值 (HTML-escaped interpolation);
- 使用三花括号 (triple-mustache) 进行 HTML 不转义插值 (non-HTML-escaped interpolation)。
当在渲染上下文 (render context) 上存在一些特定属性时,模板会自动注入对应的内容:
context.head
:(字符串)将会被作为 HTML 注入到页面的头部 (head) 里。context.styles
:(字符串)内联 CSS,将以 style 标签的形式注入到页面头部。注意,如过你使用了vue-loader
+vue-style-loader
来处理组件 CSS,此属性会在构建过程中被自动生成。context.state
:(对象)初始 Vuex store 状态,将以window.__INITIAL_STATE__
的形式内联到页面。内联的 JSON 将使用serialize-javascript自动清理,以防止 XSS 攻击。此外,当提供
clientManifest
时,模板会自动注入以下内容:渲染当前页面所需的最优客户端 JavaScript 和 CSS 资源(支持自动推导异步代码分割所需的文件)
为要渲染页面提供最佳的
<link rel="preload/prefetch">
资源提示(resource hints)。你也可以通过将
inject: false
传递给 renderer,来禁用所有自动注入。
具体查看:
手动资源注入(Manual Asset Injection)
clientManifest
2.3.0+
通过此选项提供一个由
vue-server-renderer/client-plugin
生成的客户端构建 manifest 对象 (client build manifest object)。此对象包含了 webpack 整个构建过程的信息,从而可以让 bundle renderer 自动推导需要在 HTML 模板中注入的内容。更多详细信息,请查看生成 clientManifest。inject
- 2.3.0+
控制使用
template
时是否执行自动注入。默认是true
。shouldPreload
- 2.3.0+
一个函数,用来控制什么文件应该生成
<link rel="preload">
资源预加载提示 (resource hints)。
默认情况下,只有 JavaScript 和 CSS 文件会被预加载,因为它们是启动应用时所必需的。
对于其他类型的资源(如图像或字体),预加载过多可能会浪费带宽,甚至损害性能,因此预加载什么资源具体依赖于场景。你可以使用shouldPreload
选项精确控制预加载资源:
const renderer = createBundleRenderer(bundle, {
template,
clientManifest,
shouldPreload: (file, type) => {
// 基于文件扩展名的类型推断。
// https://fetch.spec.whatwg.org/#concept-request-destination
if (type === 'script' || type === 'style') {
return true
}
if (type === 'font') {
// only preload woff2 fonts
return /\.woff2$/.test(file)
}
if (type === 'image') {
// only preload important images
return file === 'hero.jpg'
}
}
})
runInNewContext
- 2.3.0+
- 只用于
createBundleRenderer
- Expects:
boolean | 'once'
('once'
仅在 2.3.1+ 中支持)
默认情况下,对于每次渲染,bundle renderer 将创建一个新的 V8 上下文并重新执行整个 bundle。这具有一些好处 - 例如,应用程序代码与服务器进程隔离,我们无需担心文档中提到的状态单例问题。然而,这种模式有一些相当大的性能开销,因为重新创建上下文并执行整个 bundle 还是相当昂贵的,特别是当应用很大的时候。
出于向后兼容的考虑,此选项默认为
true
,但建议你尽可能使用runInNewContext: false
或runInNewContext: 'once'
。
在 2.3.0 中,此选项有一个 bug,其中runInNewContext: false
仍然使用独立的全局上下文(separate global context)执行 bundle。以下信息假定版本为 2.3.1+。
使用runInNewContext: false
,bundle 代码将与服务器进程在同一个global
上下文中运行,所以请留意在应用程序代码中尽量避免修改global
。
使用runInNewContext: 'once'
(2.3.1+),bundle 将在独立的全局
上下文 (separate global context) 取值,然而只在启动时取值一次。这提供了一定程度的应用程序代码隔离,因为它能够防止 bundle 中的代码意外污染服务器进程的global
对象。注意事项如下:
- 在此模式下,修改
global
(例如,polyfill)的依赖模块必须被打包进 bundle,不能被外部化 (externalize); 从 bundle 执行返回的值将使用不同的全局构造函数,例如,在服务器进程中捕获到 bundle 内部抛出的错误,使用的是 bundle 上下文中的 Error 构造函数,所以它不会是服务器进程中
Error
的一个实例。参考:源码结构
basedir
- 2.2.0+
- 只用于
createBundleRenderer
显式地声明 server bundle 的运行目录。运行时将会以此目录为基准来解析
node_modules
中的依赖模块。只有在所生成的 bundle 文件与外部的 NPM 依赖模块放置在不同位置,或者vue-server-renderer
是通过 NPM link 链接到当前项目中时,才需要配置此选项。cache
提供组件缓存具体实现。缓存对象必须实现以下接口(使用 Flow 语法表示):
type RenderCache = {
get: (key: string, cb?: Function) => string | void;
set: (key: string, val: string) => void;
has?: (key: string, cb?: Function) => boolean | void;
};
典型用法是传入lru-cache:
const LRU = require('lru-cache')
const renderer = createRenderer({
cache: LRU({
max: 10000
})
})
请注意,缓存对象应至少要实现get
和set
。此外,如果get
和has
接收第二个参数作为回调,那get
和has
也可以是可选的异步函数。这允许缓存使用异步 API,例如,一个 Redis 客户端:
const renderer = createRenderer({
cache: {
get: (key, cb) => {
redisClient.get(key, (err, res) => {
// 处理任何错误
cb(res)
})
},
set: (key, val) => {
redisClient.set(key, val)
}
}
})
directives
对于自定义指令,允许提供服务器端实现:
const renderer = createRenderer({
directives: {
example (vnode, directiveMeta) {
// 基于指令绑定元数据(metadata)转换 vnode
}
}
})
例如,请查看v-show
的服务器端实现。