这很难,里面只是我以比较明显的一个问题,引发对整个ssr的研究。但是我又复习了下Vuex,发现了异步问题。过两天把router也复习了。那异步问题应该就解决了,到时候再出篇稿子。这篇,你可能看不懂,因为不适合新手,对于context的估计,如果有说的不对的,也请各位专家指教。
1.vue ssr 入门
1.一个简单的例子
接下去,我们使用express来继续,得到的是这个
他和render一样。不过服务器渲染需要两个步奏,第一步,先制作出renderer,第二步是使用renderTOString函数
2.使用页面模板
注意
插值
也可以与 Vue 应用程序实例共享
3.完整的demo
关于context和html
我们发现经过renderToString的函数方法html已经将三个完美融合
分别是读取html 的renderer,和context,和Vue组件。
之后我们获取了经过加工的context。
显然Vue,要么是读取了html,然后将context加工后的数据渲染到了HTML。
加工点,需要两到三个材料。
2.ssr编写过程注意点
1.服务器上的数据响应
禁用响应式数据,还可以避免将「数据」转换为「响应式对象」的性能开销。
2.组件生命周期钩子函数
由于没有动态更新,所有的生命周期钩子函数中,只有
你应该避免在
3.访问特定平台(Platform-Specific) API
4.自定义指令
大多数自定义指令直接操作 DOM,因此会在服务器端渲染 (SSR) 过程中导致错误。有两种方法可以解决这个问题:
- 推荐使用组件作为抽象机制,并运行在「虚拟 DOM 层级(Virtual-DOM level)」(例如,使用渲染函数(render function))。
- 如果你有一个自定义指令,但是不是很容易替换为组件,则可以在创建服务器 renderer 时,使用
directives 选项所提供"服务器端版本(server-side version)"。
1 2 3 4 5 6 7 8 9 10 | export default function show (node: VNodeWithData, dir: VNodeDirective) { if (!dir.value) { const style: any = node.data.style || (node.data.style = {}) if (Array.isArray(style)) { style.push({ display: 'none' }) } else { style.display = 'none' } } } |
这里还需要补充虚拟node
3.关于render 渲染函数的补充
1.渲染函数
首先,我们强调
整个Vue 中的渲染函数有三种方法
1.render
2.template
3.renderer
2.挂载方法
我们再来探讨下挂载的三种方法
1.全局注册
2.局部注册
1.组件和挂载点
2.组件和组件之间
3.模块挂载
这是在单文件中模块挂载的写法
这是vue-cli自带的。
还有一种比较骚,不作为讲解,就以上。我们不难看出,Vue 推荐在绝大多数情况下使用模板来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数,它比模板更接近编译器。
那么渲染函数本质就是代替template。组件是什么回事。他的数据是先从组件写上去还是,从父组件中取回数据。都有。
但是有一点确定,他一定会渲染上去。
这里context就是不管是父的还是子的,最终的数据都是渲染上去了。
我们就用这个context去寻找,我们所需要的数据。
到这里为止,我们已经知道这东西来自组件。客户端的context是Vue的一个写死的APi。具体的深入还有很多。请仔细查看。至于服务端的context。我们拉开围绕我们整个ssr的一个大boss。
那么开始下一节
4.源码结构
1.避免状态单例
那么context,是否可以解决了。非常糟糕,有些情况,我们不得的以它为假设,然后进行输出。
接下去就是关于server bundle 和bundle renderer 进行讨论。
5.路由和代码分隔
1.使用使用 vue-router 的路由
到目前我们存在了两个问题,结合别人的demo。
1.为什么调用renderTostream,居然会跑到entry-server,我们看到
2.就是这个server.bundle.js在哪里
在例子中server.bundle.js没有生成的。
但是在dist 中没有server.bundle.js,在https://www.webpackjs.com/guides/development/#%E4%BD%BF%E7%94%A8-source-map,我们知道他是不会显示在dist中的。
3.再次探讨context的本质
查看源码结构的第一张图,我们发现这个简单的demo没有entry-server.js 结合上面的Vue官方给出的路由。再结合上面提到的第一个问题。
这两个应该请求是同一个功能的文件。是的,在后者中,我们看到他把context送去给Vue 实例加工。返回一个app。
前者也是一样createApp中主要功能就是new Vue ,进行实例加工。将Vue实例和context进行融合。
从本质上,我们彻底搞清楚了,服务器渲染需要的两大部分。同时我们意识到渲染的时候,已经配置renderer的时候,没有那么简单。
又有新的问题
经过打包的入口变成了
到底发生了什么。
我们进入其中
我们也找到了
我们有理由相信他将这两个混为了一个app.js,所以我们还要对webpack进行研究。、
而且你已经发现了他们两者的不同
在接下去的一段章节,可能不会讲到这,你需要保持专注。
2.代码分隔
1.异步读取
2.onready的作用
需要注意的是,你仍然需要在挂载 app 之前调用
3.异步组件路由配置
6.数据预取和状态
1.数据预取存储容器 (Data Store)
1.在服务器端渲染(SSR)期间,我们本质上是在渲染我们应用程序的"快照",所以如果应用程序依赖于一些异步数据,那么在开始渲染过程之前,需要先预取和解析好这些数据。
2.首先,在服务器端,我们可以在渲染之前预取数据,并将数据填充到 store 中。此外,我们将在 HTML 中序列化(serialize)和内联预置(inline)状态。这样,在挂载(mount)到客户端应用程序之前,可以直接从 store 获取到内联预置(inline)状态。
2.带有逻辑配置的组件 (Logic Collocation with Components)
3.服务器端数据预取 (Server Data Fetching)
通过逻辑配置组件将asyncData暴露出来
4.客户端数据预取 (Client Data Fetching)
1.在路由导航之前解析数据:
2.匹配要渲染的视图后,再获取数据:
5.Store 代码拆分 (Store Code Splitting)
使用module
7.客户端激活
接下去,我们回到那个点,重新探讨那些问题。
8.Bundle Renderer 指引
1.使用基本 SSR 的问题
这是理所应当的,然而在每次编辑过应用程序源代码之后,都必须停止并重启服务
2.传入 BundleRenderer
如何做
我们已经看到了
优点:
- 内置的 source map 支持(在 webpack 配置中使用
devtool: 'source-map' ) - 在开发环境甚至部署过程中热重载(通过读取更新后的 bundle,然后重新创建 renderer 实例)
- 关键 CSS(critical CSS) 注入(在使用
*.vue 文件时):自动内联在渲染过程中用到的组件所需的CSS。更多细节请查看 CSS 章节。 - 使用 clientManifest 进行资源注入:自动推断出最佳的预加载(preload)和预取(prefetch)指令,以及初始渲染所需的代码分割 chunk。
接下去解释另一个问题。
对于context,如果看到这一步,就算我们没有继续深入更底层的代码,也已经知道,他的具体加工方式。createBundleRenderer.
9.构建配置
1.服务器配置 (Server Config)
这就引发了对source-map功能的联想和对createBundleRenderer的深入思考。显然两边都是有做准备工作的,就是你node读取json格式都要有些问题呢。
2.扩展说明 (Externals Caveats)
1.白名单:我们将 CSS 文件列入白名单,这是因为从依赖模块导入的 CSS 还应该由 webpack 处理。如果你导入依赖于 webpack 的任何其他类型的文件(例如
2.如果你使用
由于在使用 Node 7.6+ 时,在服务器并不真正需要它,所以实际上只需在客户端 entry 导入它。它可能说的是polyfill。
3.客户端配置 (Client Config)
首先我们要了解代码分隔的意义
代码分离是把代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件。代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。
我们先将webpack的 devtool和代码分隔放在一边。还是探讨,render,context,app(Vue组件)这三个的转换形式的问题。
我们首先引入一个普通的Vue 是怎么一会事情。
当然,是先挂载,再渲染。
首先这里说了客户端配置,你要懂,正如数据预存与预取,引用的就是服务端是客户端的快照。我们目前讲的客户端是服务器将已经激活的客户端拿过来。作为渲染的数据。
下面是正常的客户端
我们看到很简单,就像我之前讲的那个普通的Vue渲染的例子。在webapck打包成index.html之后,他就是返回index.html就好了。因为相关依赖的文件,已经在服务端上传了。
这也就解释了,为什么,当我们手动打开dist文件中的index.HTML 是空白页。
比如,我将Vue打包npm run build ,你用Vue cli搭建的。
路径加载错误。我们上传服务器就是用的相对路径。我们上传到相应路径,在index.html
写相应的路径即可。
这个链接帮你们解决,需要用到webpack。
https://blog.csdn.net/jiaoqi6132/article/details/106563018
最后我们只要搞清楚这种将三种原材料加工与传统的区别到底在哪就好了。但在这之前,我们还需要引入
关于server bundle 和bundle renderer 的范围 ,交集状况,以便我们更加深入理解。
引用这两句话
现在我们已经确定了他们的范围。bundleRender 是将他们集合。
一个clientManifest.一个template,一个serverbundle。
他们和Vue,html,context是什么关系。又有以下几问。
1.我们要探索serverbundle 也就是vue-ssr-server-bundle.json的包括的具体的内容。
2.clientManifest的内容和作用。
3.以及他们之间的关系。
https://www.cnblogs.com/jialikesensi/p/13047778.html
关于source-map的详解
第一个问题
这里看出,他没有包括entry-client.js
楚辞之外,它包括了 ,路由,和处理路由的entry-server.js
第二个问题
vue-ssr-client-manifest.json
client.bundle.js有
这里,也就懂了。
服务端渲染
客户端渲染的时候
那个0.bundle去哪了。
我们只在两个json中找到了它的踪迹
显然单纯的游览器是没有返回的。
那么
vue-ssr-client-manifest.json主要包括了 client.bundle.js。包括了
虽然我们在vue-ssr-server-bundle.json看到了app.js但是没有看到entry-client,但entry-client在clientManifest中。
ssrStream就是把三样已经都交给你完毕了。
我猜,他已经用到了$mount.他是将原来的直接拿过来,为什么?
在HTML中,我们有标签,可以写入,但是在服务端和客户端的混合模式下,我们看到服务器没有吸收index模板。
所以,他应该就是把客户端的数据,拿过来。这就是vue-ssr-client-manifest.json的作用。本质上,我们讨论了几种挂载和渲染方式。也看过,这些东西就是转来转去。
最后的关于三种原材料,他们的设计模式已经完全变了。
在原始中我们就是将三种混合,到时候渲染到HTML ,返回即可。
而服务端和客户端的混合模式,他们是自动注入,因此就会直接引用客户端,到底引用多少,只有开发VUE的知道,就像我们划开了海的接线。但是,海底的鱼可不按国界线的,他们受洋流,也就是底层源码的支配。
还有异步的问题,我会另开一个题。因为这一文章是以context引出webapck打包中,各个资源出现的位置。和重复使用度。
我们可以查看
通过此选项提供一个由
就像我分析的一样。
同时关于context的一点补充
那么接下去我们看下服务器的手动注入。
4.手动注入
默认情况下,当提供
但是有时候,你可能需要对资源注入的模板进行更细粒度 (finer-grained) 的控制,或者你根本不使用模板。在这种情况下,你可以在创建 renderer 并手动执行资源注入时,传入
这些人太懒了,也不会写下哪里。
在
1.context.renderStyles()
这将返回内联