Next.js SSG场景下大数据量SVG地图渲染性能优化问询
解决部署超时的优先级优化方案(SSG构建层)
- 抽离预计算逻辑:提前在独立的构建脚本中完成TopoJSON要素处理、CSV数据关联、投影计算生成path的d属性、
figureOutColor颜色计算,把24个版本的地图所有path需要的属性(d、fill、tooltip展示字段)全部导出为静态JSON文件。SSG阶段直接读取对应版本的JSON,不需要重复执行计算逻辑,能减少90%以上的构建计算量。 - 规避Node端DOM模拟开销:你当前用D3在SSG阶段执行DOM操作绘制地图,Node环境需要调用jsdom模拟DOM创建上万元素,开销极高。可以直接把预计算好的path属性拼接为静态SVG字符串,直接注入到页面HTML中,完全跳过D3的DOM操作流程。
- 可选:把地图渲染下移到客户端:SSG阶段只输出空SVG容器和预计算好的路径数据,部署阶段完全不执行地图绘制逻辑,客户端加载后再渲染,13000个path的客户端渲染耗时通常不超过100ms,用户无感知,还能彻底解决构建超时问题。
渲染逻辑优化
- 简化TopoJSON精度:提前简化行政区边界的冗余节点,在不影响视觉效果的前提下把TopoJSON体积压缩30%~70%,path的d属性长度大幅缩短,不管是生成还是渲染速度都会明显提升。
- 修复现有代码的性能bug:
- transform属性拼写错误:原代码
attr('transform', 'translate(0' + margin.left + ',' + margin.top + ')')多了多余的0,会导致属性解析异常,修改为attr('transform',translate(${margin.left},${margin.top})) - mouseover事件的字符串未闭合:原代码
.text(${d.properties.name});`缺少反引号闭合,会导致运行时报错拖慢性能
- transform属性拼写错误:原代码
- 静态化颜色映射:把
figureOutColor的计算逻辑提前生成静态的type到颜色值的映射表,运行时直接查表取值,不需要每次调用都执行计算逻辑。 - 抽离公共样式:不要给每个path重复设置stroke相关属性,在SVG内部添加公共样式:
减少每个DOM节点的属性数量,降低渲染开销。<style> .district { stroke: currentColor; stroke-width: 0.5; } </style>
事件绑定优化
- 替换单个事件绑定为事件委托:13000个path每个绑定3个事件监听器的内存开销极高,改为只给外层SVG绑定一次事件,通过
event.target判断触发元素是否为行政区path。提前把tooltip需要的字段存到path的data-*属性中,事件触发时直接读取dataset即可,示例逻辑:// 只绑一次事件到svg svg.on('mouseover', (e) => { const target = e.target; if (target.classList.contains('district')) { tooltip.style('visibility', 'visible').text(target.dataset.name) // 其他交互逻辑 } }).on('mousemove', (e) => { tooltip.style('top', e.pageY - 40 + 'px').style('left', e.pageX + 'px') }).on('mouseout', (e) => { const target = e.target; if (target.classList.contains('district')) { target.classList.remove('selected', 'fill-current', 'text-white') tooltip.style('visibility', 'hidden') } }) - 复用tooltip实例:不要每次调用drawMap都新建tooltip元素,全局只创建一个tooltip实例,所有地图版本复用,减少DOM创建销毁开销。
内容的提问来源于stack exchange,提问作者SK Sam
相关产品推荐
相关产品推荐

