首页IT科技node.js canvas(使用node-canvas在服务端渲染echarts图表解析)

node.js canvas(使用node-canvas在服务端渲染echarts图表解析)

时间2025-07-30 22:29:10分类IT科技浏览5176
导读:踩了很长时间的坑,总算是能跑起来了 但是如果要我给echarts的SSR一个评价,那就是不好用……可能是我太菜了。而且,因为我是Windows用户,这个过程对Windows极其不友好。...

踩了很长时间的坑              ,总算是能跑起来了

但是如果要我给echarts的SSR一个评价                  ,那就是不好用……可能是我太菜了            。而且       ,因为我是Windows用户           ,这个过程对Windows极其不友好                     。

友情提示:入坑请慎重

在服务端渲染图表                  ,绕不开的一个问题就是          ,没有DOM怎么绘图?这个主要有两种解决方案        ,一个是用那些headless的浏览器去渲染                   ,然后进行截图;另一个就是在Node环境下模拟DOM元素             ,比如我在这里想用canvas    ,就得装个node-canvas;如果想用SVG                    ,就得用JSDOM一类的库      。我这里主要是用的canvas                ,所以就用node-canvas了         。

首先,需要安装node-canvas和echarts                     。echarts不用多说                 ,但是有一点                   ,不建议使用官方推荐的node-echarts    ,版本陈旧              ,而且依赖的库新版本的Node(12.x)不支持         。

node-canvas安装请参考官方文档                  ,因为安装流程比较复杂       ,尤其是Windows用户:https://github.com/Automattic/node-canvas/wiki/Installation:-Windows

当然           ,因为众所周知的原因                  ,最后一步用npm install安装node-canvas是个问题          ,因为它预编译的安装包好像是在AWS上        ,大概率会卡在这里:

node-pre-gyp WARN Using request for node-pre-gyp https download

或者                   ,还有可能卡在这里:

node-pre-gyp info install unpacking Release/ node-pre-gyp info install unpacking Release/canvas.exp node-pre-gyp info install unpacking Release/canvas.ilk

然后还有可能直接报错      。解决方案就是             ,加个–build-from-source    ,不用他编译好的                    ,而是在我们本机进行编译:

npm install canvas --verbose --build-from-source

在这个过程中                ,还有可能报错,比较常见的有这些

1            、找不到node-gyp                     。

决办法:npm install -g node-gyp                 ,装一个就是了             。不过一般来说会自带才对……

2                     、fatal error C1083: 无法打开包括文件: “cairo.h            ”: No such file or directory   。

解决方法:参考官方文档安装GTK 2                   ,并放在合适的路径                    。

3      、fatal error C1083: 无法打开包括文件: “jpeglib.h                     ”: No such file or directory

解决方法:参考官方文档安装libjpeg-turbo    ,并放在合适的路径                 。

注意              ,对于Windows用户                  ,一定要安装for VC++的版本       ,不要装成for gcc的版本。

4         、Error: Cannot find module ../build/Release/canvas.node

解决方法:进入node_modules/canvas目录           ,然后使用node-gyp configure build手动编译                。

5                     、gyp: binding.gyp not found

解决方法:同4                     。还有一种可能是缺少windows-build-tools                  ,这个在第7点中说   。

6         、node.lib已损坏            。

解决方法:升级Node版本          ,或者尝试Node安装包的repair功能                     。大概率是Node没装好        ,或者你使用了canvas-prebuilt这个已经废弃的库      。实测升级到最新版本12.16.1可以修复         。

7      、与windows-build-tools相关的一系列错误                     。

解决方法:npm install --global --production windows-build-tools

但是在此过程中可能会出现一系列问题         。可能会卡在这里:

Python 2.7.16 is already installed, not installing again.

也有可能卡在这里:

Successfully installed Python 2.7

或者提示安装完了                   ,但一直没有退出             ,请往下看      。

第一次卡住的时候    ,尝试重复一遍install                    ,如果解决了那自然最好                ,如果没解决,甚至报错:

Error: EBUSY: resource busy or locked

那么我们可能是遇到了同样的问题                     。

网上有两种方案                 ,我放在这里做个参考                   ,虽然对我来说都没用就是了:

1                     、先安装一个旧版本npm install --global --production windows-build-tools@4.0.0    ,然后重新npm install -g --production windows-build-tools              ,就可以了             。

2             、针对resource busy or locked的报错                  ,先在任务管理器里kill掉BuildTolls_Full.exe这个进程       ,然后去C:\Users\<你的用户名>\.windows-build-tools里找到build-tools-log.txt           ,在这个文件的最后增加一行:

Variable: IsInstalled = 1

保存后重新install   。

但是这两种对我来说都没用                    。后来                  ,我无意中看到一个方法          ,死马当活马医        ,居然成了……说起来也很迷幻                   ,加个–verbose就好了:

npm install --global --production --verbose windows-build-tools

到了这里             ,基本上就可以开始了                 。其实方法并不神秘    ,主要就是这么一个方法:

const path = require(path) const { createCanvas } = require(canvas) const echarts = require(echarts) function generateImage(options) { const canvas = createCanvas(600, 600) // 600 * 600的canvas const ctx = canvas.getContext(2d) ctx.font = 12px echarts.setCanvasCreator(() => canvas) // 使用node-canvas const chart = echarts.init(canvas) options.animation = false options.textStyle = { fontSize: 12 } chart.setOption(options) // 就是echarts的options return chart.getDom().toBuffer() // 返回buffer }

这里也可以用fs.writeFileSync来进行文件读写                    ,不过我更倾向于返回buffer流                ,个人爱好而已。

不过,返回buffer流的话                 ,前端需要一些处理                   ,以axios为例    ,需要设置responseType为blob              ,然后用createObjectURL来处理blob                  ,然后把url放到img里去:

const { data } = await axios.get(/api/chart, { responseType: blob }) URL.createObjectURL(data) // 放进img.src的url

最终效果差不多是这样:

同时       ,服务端渲染还面临着服务端不支持中文导致乱码           ,图片不清晰等问题                  ,这些我还没有特别好的处理办法          ,只能看情况进行处理                。

我只说说我试过有用的办法

1   、针对乱码问题        ,node-canvas 2.x提供了一个导入字体的方法registerFont()                   ,可以指定中文字体                     。但是我并不喜欢这个方法             ,平白无故增加静态资源的数量   。

据说在服务器上装好中文字体可以解决    ,但在我这里没用            。

2                    、图片不清晰                    ,可以在init的时候增大像素比:

echarts.init(canvas, null, {devicePixelRatio: 2});

但是这又有一个问题                ,这么弄出来的图片大小会翻倍                     。本来我用SSR就是希望提高性能,为了清晰度还得牺牲性能                 ,就有点本末倒置了      。

总的来说                   ,目前我还没有发现对echarts进行SSR的好处    ,可能用那些更轻量的图表库配合SVG效果会比较好              ,比如D3         。可能有用的场景就是显示那些对清晰度要求不太高的图表                  ,比如图表的动态缩略图       ,因为有时候可能会有这样的需求           ,虽然是缩略图或者是示意图                  ,也希望能够动态更新          ,因为前后数据变化可能比较大                     。

以上为个人经验        ,希望能给大家一个参考                   ,也希望大家多多支持本站         。

参考资料

https://github.com/Automattic/node-canvas/issues/1468#issuecomment-522961098

https://github.com/mapbox/node-pre-gyp/issues/477#issuecomment-534231739

声明:本站所有文章             ,如无特殊说明或标注    ,均为本站原创发布      。任何个人或组织                    ,在未征得本站同意时                ,禁止复制                 、盗用、采集                、发布本站内容到任何网站                     、书籍等各类媒体平台                     。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理             。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
外链大全(外链查询工具,附详细介绍) 王者荣耀怎么能解除师徒关系(王者荣耀怎么解除师徒关系呢?)