You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<!DOCTYPE html><html><head><!-- 使用双花括号(double-mustache)进行 HTML 转义插值(HTML-escaped interpolation) --><title>{{ title }}</title><!-- 使用三花括号(triple-mustache)进行 HTML 不转义插值(non-HTML-escaped interpolation) -->
{{{ meta }}}
</head><body><!--vue-ssr-outlet--></body></html>
注意 <!--vue-ssr-outlet--> 注释 -- 这里将是应用程序 HTML 标记注入的地方。
然后,我们可以读取和传输文件到 Vue renderer 中:
生命周期
由于没有动态更新,所有的生命周期钩子函数中,只有 beforeCreate 和 created 会在服务器端渲染 (SSR) 过程中被调用。这就是说任何其他生命周期钩子函数中的代码(例如 beforeMount 或 mounted),只会在客户端执行。
安装
vue-server-renderer
和vue
必须匹配版本。vue-server-renderer
依赖一些 Node.js 原生模块,因此只能在 Node.js 中使用。我们可能会提供一个更简单的构建,可以在将来在其他「JavaScript 运行时(runtime)」运行。渲染实例
新建一份
test.js
写入以下代码,并运行node test
,将会运行出三段结果<div data-server-rendered="true">Hello World</div>
,说明已经成功实现服务端渲染。与服务器集成
在 Node.js 服务器中使用时相当简单直接,例如 Express:
使用一个页面模板
当你在渲染 Vue 应用程序时,renderer 只从应用程序生成 HTML 标记 (markup)。在这个示例中,我们必须用一个额外的 HTML 页面包裹容器,来包裹生成的 HTML 标记。
为了简化这些,你可以直接在创建 renderer 时提供一个页面模板。多数时候,我们会将页面模板放在特有的文件中,例如
index.template.html
:注意
<!--vue-ssr-outlet-->
注释 -- 这里将是应用程序 HTML 标记注入的地方。然后,我们可以读取和传输文件到 Vue renderer 中:
生命周期
由于没有动态更新,所有的生命周期钩子函数中,只有 beforeCreate 和 created 会在服务器端渲染 (SSR) 过程中被调用。这就是说任何其他生命周期钩子函数中的代码(例如 beforeMount 或 mounted),只会在客户端执行。
DOM 和 BOM
通用代码不可接受特定平台的 API,因此如果你的代码中,直接使用了像
window
或document
,这种仅浏览器可用的全局变量,则会在 Node.js 中执行时抛出错误,反之也是如此。避免状态单例
当编写纯客户端 (client-only) 代码时,我们习惯于每次在新的上下文中对代码进行取值。但是,Node.js 服务器是一个长期运行的进程。当我们的代码进入该进程时,它将进行一次取值并留存在内存中。这意味着如果创建一个单例对象,它将在每个传入的请求之间共享。
如基本示例所示,我们为每个请求创建一个新的根 Vue 实例。这与每个用户在自己的浏览器中使用新应用程序的实例类似。如果我们在多个请求之间使用一个共享的实例,很容易导致交叉请求状态污染 (cross-request state pollution)。
因此,我们不应该直接创建一个应用程序实例,而是应该暴露一个可以重复执行的工厂函数,为每个请求创建新的应用程序实例:
并且我们的服务器代码现在变为:
同样的规则也适用于 router、store 和 event bus 实例。你不应该直接从模块导出并将其导入到应用程序中,而是需要在 createApp 中创建一个新的实例,并从根 Vue 实例注入。
使用 webpack 的源码结构
现在我们正在使用 webpack 来处理服务器和客户端的应用程序,大部分源码可以使用通用方式编写,可以使用 webpack 支持的所有功能。同时,在编写通用代码时,有一些事项要牢记在心。
一个基本项目可能像是这样:
app.js
app.js 是我们应用程序的「通用 entry」。在纯客户端应用程序中,我们将在此文件中创建根 Vue 实例,并直接挂载到 DOM。但是,对于服务器端渲染(SSR),责任转移到纯客户端 entry 文件。app.js 简单地使用 export 导出一个 createApp 函数:
entry-client.js:
客户端 entry 只需创建应用程序,并且将其挂载到 DOM 中:
entry-server.js:
服务器 entry 使用 default export 导出函数,并在每次渲染中重复调用此函数。此时,除了创建和返回应用程序实例之外,它不会做太多事情 - 但是稍后我们将在此执行服务器端路由匹配 (server-side route matching) 和数据预取逻辑 (data pre-fetching logic)。
参考文档
The text was updated successfully, but these errors were encountered: