明确什么是服务端渲染?
页面上的内容是由服务器生产的
常规页面渲染面临的问题:
1、脚本依赖,加载耗时
蓝色(Loading
):网络通信和HTML解析
黄色(Scripting
):JavaScript执行
紫色(Rendering
):样式计算和布局,即重排
绿色(Painting
):重绘
灰色(other
):其它事件花费的时间
白色(Idle
):空闲时间
事件总结:
Loading事件
事件描述
Parse HTML
浏览器执行HTML解析
FinishLoading
网络请求完毕事件
ReceiveData
请求的响应数据到达事件,如果响应数据很大(拆包),可能会多次触发该事件
ReceiveResponse
响应头报文到达时触发
SendRequest
发送网络请求时触发
Scripting事件
事件描述
Animation Frame Fired
一个定义好的动画帧发生并开始回调处理时触发
Cancel Animation Frame
取消一个动画帧时触发
GC Event
垃圾回收时触发
DOMContentLoaded
当页面中的DOM内容加载并解析完毕时触发
Evaluate Script
A script was evaluated.
Event
js事件
Function Call
只有当浏览器进入到js引擎中时触发
Install Timer
创建计时器(调用setTimeout()和setInterval())时触发
Request Animation Frame
A requestAnimationFrame() call scheduled a new frame
Remove Timer
当清除一个计时器时触发
Time
调用console.time()触发
Time End
调用console.timeEnd()触发
Timer Fired
定时器激活回调后触发
XHR Ready State Change
当一个异步请求为就绪状态后触发
XHR Load
当一个异步请求完成加载后触发
Rendering事件
事件描述
Invalidate layout
当DOM更改导致页面布局失效时触发
Layout
页面布局计算执行时触发
Recalculate style Chrome
重新计算元素样式时触发
Scroll
内嵌的视窗滚动时触发
Painting事件
事件描述
Composite Layers
Chrome的渲染引擎完成图片层合并时触发
Image Decode
一个图片资源完成解码后触发
Image Resize
一个图片被修改尺寸后触发
Paint
合并后的层被绘制到对应显示区域后触发
典型场景
首屏渲染,资源过重,加载慢
多层次优化方案:
1,构建层模板编译
,即将模板编译拆分出runtime,在构建层面作模板编译,提升runtime速度
2,公共数据的prerender
,即将公用的页面在构建时进行数据渲染且编译出静态模板,提升runtime速度
3,服务端渲染(ssr),
如服务端采用nodejs服务,同样的js执行环境,可以在Node服务端执行vue框架,编译出静态页面,用户请求可以直接返回在服务端已经编译生成的html静态模板,省去了客户端,加载编译执行等过程,提升交互体验(优点:
提升交互体验,平衡前后端的运算压力。缺点:
提升公司内部系统架构的复杂度,降低了开发效率,增加了服务端的负载)
案例demo01
1、新建文件夹,初始化一个项目:npm init
2、安装生产依赖框架,以express为例: cnpm install express
3、新建src
文件家用于放项目代码文件,在src中创建server
文件夹存node服务源码文件,在server中添加index.js
入口文件
看响应数据就是服务端直接返回的静态模板
看源码跟index.js返回的静态模板一模一样
总结:这就是所谓的服务端渲染,对于浏览器来说,只需要将请求回来的数据渲染出来即可,不用进行任何的脚本计算,不会对浏览器造成额外的加载负担(如scripting,loading,Painting),提升体验
那么什么是客户端渲染呢?
即依赖浏览器的解析能力,通过解析之后进行渲染,这个过程依赖浏览器各种能力力,如:
此时刷新浏览器会出现WORD
但是此时如果你把浏览器禁用js
,那么WORD就不会渲染出来,这说明页面渲染以来了浏览器自身解析js的能力。
以上是一个原生js的demo=============邪恶的分割线
基于reactjs的ssr的基础使用
1,安装reactjs :cnpm install react react-dom -S
2,安装打包工具:cnpm install webpack webpack-cli -D
3,安装转码工具:cnpm install babel-loader @babel/core @babel/preset-env @babel/preset-react -D
4,然后在src下创建containers文件夹,用于存放组建demo
5,然后创建第一个组建:新建Home文件并创建index.js
containers/Home/index.js
在服务端使用renderTostring将组件转换成字符串一起渲染到客户端
打包测试:新建webpack.config.js文件
在打包server端js文件时,比如fs,path…这些引入的文件,是nodejs的核心模块,node环境提供直接引入,打包不了也不需要打包,所以我们要在打包是声明直接排除这些不用打包的文件
所以安装一个webpack打包时检测核心模块的插件:cnpm install webpack-node-externals -D
使用watch方法监听文件webpack.config.js的变化,一旦变化就会重新执行打包
优化启动流程:
只监听了webpack,文档变化重新打包,但是刷新页面并不生效,原因是node此时并未重新执行新打包的文件
解决:1、安装node管理器:cnpm i nodemon -g
2、安装 npm-run-all:cnpm i npm-run-all -g //批量执行脚本
3、修改package.json
以上只是一个静态渲染,那么SSR的事件是怎么回事呢???
1、接上面代码在containers里面新建组件Counter,并在Counter新建index.js
2、安装将类属性语法转成es5的插件:cnpm install @babel/plugin-proposal-class-properties
并将其配置到
webpack.config.js
的plugins
中如:
Counter/index.js
/server/index.js
注意:服务端渲染处理什么?单页面应用的首屏dom结构渲染,而事件绑定都是客户端在处理,核心是什么?renderToString()
那么真的要绑定事件我们应该怎么做呢?
/client/index.js
webpack.base.js
此时问题,既然有base公用文件,那么怎么引用呢?安装:webpack-merge 命令:cnpm install webpack-merge
/webpack.client.js
/webpack.server.js
修改package.json的运行命令
那如何让服务端渲染出来的页面和引入的client端写好的事件包产生关系呢? 静态文件中间件
…未完待续…