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

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

时间2025-06-20 17:27:12分类IT科技浏览4389
导读:踩了很长时间的坑,总算是能跑起来了 但是如果要我给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
微信投票赚钱平台推荐(微信投票赚钱有哪些平台-微信半自动阅读赚钱平台)