SVG服务器渲染

这个月几乎全部精力都在完成公司图表库的Server-side Rendering,摆脱echarts投入d3的怀抱,旨在毫秒级的性能改善和预备以后反爬虫的可能性,不过性能表现的提升还得跟踪一段时间才能得到毕竟准确的结果。

Canvas和SVG的选择

Canvas似乎是现在的主流选择,Flipboard甚至不惜用Canvas代替DOM来改善交互,表现大家自有定论。但在服务器端渲染,Canvas不具备交互的条件,所以SVG是唯一的选择。

虚拟DOM的那些事儿

其实在服务器端渲染需要解决的一个最大的问题,便是虚拟DOM的操作了。虚拟DOM这个概念最近肯定是耳熟能详,为什么浏览器里需要一个虚拟DOM——还不是嫌DOM操作慢。而服务器端也面临同样的问题,有PhantomJS和JSDOM这样的完全模拟出浏览器环境进行DOM操作,但性能完全不能如意啊。
个人在做这个SVG服务器渲染的时候一开始是使用JSDOM(D3官方推荐),但渲染一个折线图(X轴50个点以内)大约需要80ms以上。这样的速度我们来进行SSR就是得不偿失了。所以我尝试了好几种方案:

  • cheerio:性能非常好,但仅仅提供简单的DOM树形结构,但不包含任何DOM方法,无法对节点进行操作。
  • minidom:提供了DOM2大部分方法,但仅限于HTML文档,缺少D3需要的createElementNS。
  • xmldom:提供了DOM2大部分方法,性能能够满足要求。但缺少D3需要的Selectors API。
    于是我给xmldom打了一个补丁,叫xmldom-qsa,让其DOM节点包含querySelector等方法。这样就可以在服务器端完美地调用各种D3的API进行SVG绘图。粗略测试它的性能大概是JSDOM的4倍左右。

JS config和CSS theme

在一个库里配置项总是最让我头疼的部分,配置项应该有什么,应该像什么。颜色主题是应该放CSS里还是放配置项里。在做package的时候反复验证了,最终样式还是交给CSS了,改起来容易啊。😊

Node端配置项

配置项还是参考了echarts的基本结构。但因为主题配色几乎由CSS包办了,所以省去了体积庞大的font-sizecolor这类样式配置。可以专注于数据啦!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
xAxis:
{ type: 'time',
data:
[ 20170524,
20170525,
...]
},
yAxis:
{ type: 'points',
data: [ 123, 345, ... ]},
tooltip: { pointIndex: 14 },
series:[
{
name: '票房',//not required, if you need legend you should give it to me
color: '#010101', //not required
data:[
{ yValue: 3160,
tooltip: '2017-06-22 3160',
xValue: 20170524 },
{ yValue: 7556,
tooltip: '2017-06-23 7556',
xValue: 20170525 }
]},
{data:[
{ yValue: 60000,
tooltip: '2017-06-22 6',
xValue: 20170524 },
{ yValue: 80000,
tooltip: '2017-06-23 8',
xValue: 20170525 }
]}
]
}

这样是不是很好,服务器就应该尽量只关心数据对吧。

浏览器内的交互

当然,事件绑定还是需要浏览器来完成,所以也给出了比较简单的浏览器配置项。

1
2
3
4
5
6
7
8
9
10
//after import client/js/chart.js
var setting = {
type : 'line', //type, required
tooltip : true, //has tooltip
tooltipTrigger: false,//show the tooltip when has it
callback: undefined,//the callback function of click on item
moveTrigger: true,//trigger callback when move in axis
defaultEvent: true//whether use defaute events on item
}
myChart(document.getElementById('lineChart'), setting);

配置项还是倾向于简洁明了,当然以后会继续改善,如果感兴趣,还是去看看文档吧,欢迎指导。

未尽之响应和动画

响应式应该是现有Web UI库里的标配了,在服务器端不是很好做的原因是,无法即时得到客户端视窗的大小,而在客户端进行二次渲染的话耗费的资源又有点得不偿失,所以响应式做的不尽完善。
而动画也因为时间关系没有深究,实际上SVG动画是有比较大的潜力的,有大牛给过相应的例子——SVG动画实践
当然,SVG服务器渲染这套东西还没完全完成,后续肯定会改善响应性和大屏上的体验。