
Vue.js 是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出 Vue 组件,进行生成 DOM 和操作 DOM。然而,也可以将同一个组件渲染为服务器端的 HTML 字符串,将它们直接发送到浏览器,最后将这些静态标记"激活"为客户端上完全可交互的应用程序。在服务端渲染模板字符串的这一过程即为SSR。
概要
何时使用服务器端渲染 (SSR) (来自vue官方文档)
与传统 SPA (单页应用程序 (Single-Page Application)) 相比,服务器端渲染 (SSR) 的优势主要在于:
更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。
请注意,截至目前,Google 和 Bing 可以很好对同步 JavaScript 应用程序进行索引。在这里,同步是关键。如果你的应用程序初始展示 loading 菊花图,然后通过 Ajax 获取内容,抓取工具并不会等待异步完成后再行抓取页面内容。也就是说,如果 SEO 对你的站点至关重要,而你的页面又是异步获取内容,则你可能需要服务器端渲染(SSR)解决此问题。
更快的内容到达时间 (time-to-content),特别是对于缓慢的网络情况或运行缓慢的设备。无需等待所有的 JavaScript 都完成下载并执行,才显示服务器渲染的标记,所以你的用户将会更快速地看到完整渲染的页面。通常可以产生更好的用户体验,并且对于那些「内容到达时间(time-to-content) 与转化率直接相关」的应用程序而言,服务器端渲染 (SSR) 至关重要。
使用服务器端渲染 (SSR) 时还需要有一些权衡之处:
开发条件所限。浏览器特定的代码,只能在某些生命周期钩子函数 (lifecycle hook) 中使用;一些外部扩展库 (external library) 可能需要特殊处理,才能在服务器渲染应用程序中运行。
涉及构建设置和部署的更多要求。与可以部署在任何静态文件服务器上的完全静态单页面应用程序 (SPA) 不同,服务器渲染应用程序,需要处于 Node.js server 运行环境。
更多的服务器端负载。在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用 CPU 资源 (CPU-intensive - CPU 密集),因此如果你预料在高流量环境 (high traffic) 下使用,请准备相应的服务器负载,并明智地采用缓存策略。
在对你的应用程序使用服务器端渲染 (SSR) 之前,你应该问的第一个问题是,是否真的需要它。这主要取决于内容到达时间 (time-to-content) 对应用程序的重要程度。例如,如果你正在构建一个内部仪表盘,初始加载时的额外几百毫秒并不重要,这种情况下去使用服务器端渲染 (SSR) 将是一个小题大作之举。然而,内容到达时间 (time-to-content) 要求是绝对关键的指标,在这种情况下,服务器端渲染 (SSR) 可以帮助你实现最佳的初始加载性能。
SSR的原理
通过如下的原理图我们可以分析出SSR的基本原理:
左侧Source部分就是我们编写的源代码,所有代码有一个公共入口,即app.js,与app.js右侧相邻的就是服务端的入口
(entry-server.js)和客户端的入口(entry-client.js)。当完成所有源代码的编写之后,我们通过webpack打包出两个bundle,分别是server bundle和client bundle,当用户进行页面访问的时候,先是经过服务端的入口,将vue组件组装为html字符串,并混入客户端所访问的html模板中,最终就完成了整个SSR渲染的过程。
创建SSR demo
创建一个项目目录为vue-ssr-demo, 进入目录,输入如下命令:
安装完成后,可以看到我们的package.json文件如下:
在根目录下(vue-ssr-demo)新建一个server.js文件,用户创建node服务
在package.json文件中添加启动node服务的命令
在vscode终端输入 npm run server 可以看到服务已启动的提示语,在浏览器地址栏输入localhost:5000,可以看到页面显示<code>Hell SSR</code>。
上面我们成功渲染出一段文字,下面我们去渲染一个html模板。
修改server.js文件如下:
保存代码,重启服务npm run server,然后重新刷新页面, 可以看到渲染的文字为<code>这是模板消息:Hello SSR</code>。
浏览器按F12查看页面源代码,我们发现在源代码中,已经存在一个标签h1,同时,h1标签上面有一个属性:data-server-rendered="true",这其实是一个标记,表明这个页面是由vue-ssr渲染而来的。
虽然h1标签对被成功渲染,但是我们发现这个html页面并不完整, 缺少文档声明,html标签,body标签,title标签等。
当你在渲染 Vue 应用程序时,renderer 只从应用程序生成 HTML 标记 (markup)。我们必须用一个额外的 HTML 页面包裹容器,来包裹生成的 HTML 标记。
为了简化这些,你可以直接在创建 renderer 时提供一个页面模板。多数时候,我们会将页面模板放在特有的文件中,例如 index.template.html:
注意 <code><!--vue-ssr-outlet--> </code>注释 -- 这里将是应用程序 HTML 标记注入的地方。
然后,我们可以读取和传输文件到 Vue renderer 中,修改server.js
重新启动node服务,刷新页面,按下F12,这时我们可以看到完整的html结构