blob: e3e341b27408acf045630a97c17d6bdbc53989c7 [file] [log] [blame]
<!doctype html>
<html data-n-head-ssr>
<head>
<link rel="stylesheet" type="text/css" href="https://fastly.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://echarts.apache.org/zh/css/main.css">
<link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css">
<title>Server Side Rendering - Cross Platform - How To Guides - Handbook - Apache ECharts</title><meta data-n-head="ssr" charset="utf-8"><meta data-n-head="ssr" name="viewport" content="width=device-width,initial-scale=1"><meta data-n-head="ssr" data-hid="docsearch:language" name="docsearch:language" content="en"><base href="/handbook/"><link data-n-head="ssr" rel="icon" type="image/x-icon" href="https://echarts.apache.org/zh/images/favicon.png"><link rel="preload" href="/handbook/_nuxt/4d2a12b.js" as="script"><link rel="preload" href="/handbook/_nuxt/js/fa73816a85b29fbf7562.js" as="script"><link rel="preload" href="/handbook/_nuxt/css/8117eb7.css" as="style"><link rel="preload" href="/handbook/_nuxt/js/b964c20bb1562bc48da6.js" as="script"><link rel="preload" href="/handbook/_nuxt/css/1f3ef45.css" as="style"><link rel="preload" href="/handbook/_nuxt/js/60d2f1dbd961abb7604b.js" as="script"><link rel="preload" href="/handbook/_nuxt/css/ba9ec8a.css" as="style"><link rel="preload" href="/handbook/_nuxt/js/43cd67c0cf5a9d972051.js" as="script"><link rel="preload" href="/handbook/_nuxt/css/3556c50.css" as="style"><link rel="preload" href="/handbook/_nuxt/js/9d86a6602b3f4dd6c979.js" as="script"><link rel="stylesheet" href="/handbook/_nuxt/css/8117eb7.css"><link rel="stylesheet" href="/handbook/_nuxt/css/1f3ef45.css"><link rel="stylesheet" href="/handbook/_nuxt/css/ba9ec8a.css"><link rel="stylesheet" href="/handbook/_nuxt/css/3556c50.css">
</head>
<body>
<div data-server-rendered="true" id="__nuxt"><!----><div id="__layout"><div><nav role="navigation" class="navbar navbar-default navbar-fixed-top"><div class="container-fluid"><div class="navbar-header"><button type="button" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false" class="navbar-toggle collapsed"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="https://echarts.apache.org/en/index.html" class="navbar-brand"><img src="https://echarts.apache.org/en/images/logo.png" alt="echarts logo" class="navbar-logo"></a></div><div id="navbar-collapse" class="collapse navbar-collapse"><ul class="nav navbar-nav navbar-left"><li id="nav-index"><a href="https://echarts.apache.org/en/index.html">Home</a></li><li id="nav-doc" class="dropdown"><a href="#" data-toggle="dropdown" class="dropdown-toggle">Docs<b class="caret"></b></a><ul class="dropdown-menu"><li><a href="https://echarts.apache.org/en/feature.html">Features</a></li><li><a href="https://echarts.apache.org/handbook/en/get-started/">Handbook</a></li><li><a href="https://echarts.apache.org/en/api.html">API</a></li><li><a href="https://echarts.apache.org/en/option.html">Chart Configuration</a></li><li><a href="https://echarts.apache.org/en/changelog.html">Changelog</a></li><li><a href="https://echarts.apache.org/en/faq.html">FAQ</a></li><li><a href="https://echarts.apache.org/handbook/en/basics/release-note/v5-upgrade-guide">V5 Upgrade Guide</a></li></ul></li><li id="nav-download" class="dropdown"><a href="#" data-toggle="dropdown" class="dropdown-toggle">Download<b class="caret"></b></a><ul class="dropdown-menu"><li><a href="https://echarts.apache.org/en/download.html">Download</a></li><li><a href="https://echarts.apache.org/en/download-theme.html">Download Themes</a></li><li><a href="https://echarts.apache.org/en/download-extension.html">Download Extensions</a></li></ul></li><li id="nav-examples"><a href="https://echarts.apache.org/examples/en/index.html">Examples</a></li><li id="nav-resources"><a href="#" data-toggle="dropdown" class="dropdown-toggle">Resources<b class="caret"></b></a><ul class="dropdown-menu"><li><a href="https://echarts.apache.org/en/spreadsheet.html">Spread Sheet Tool</a></li><li><a href="https://echarts.apache.org/en/theme-builder.html">Theme Builder</a></li><li><a href="https://echarts.apache.org/en/cheat-sheet.html">Cheat Sheet</a></li><li><a href="https://echarts.apache.org/en/resources.html">More Resources</a></li></ul></li><li id="nav-contribute"><a href="#" data-toggle="dropdown" class="dropdown-toggle">Community<b class="caret"></b></a><ul class="dropdown-menu"><li><a href="https://echarts.apache.org/en/events.html">Events</a></li><li><a href="https://echarts.apache.org/en/committers.html">Committers</a></li><li><a href="https://echarts.apache.org/en/maillist.html">Mailing List</a></li><li><a href="https://echarts.apache.org/en/contributing.html">How to Contribute</a></li><li><a href="https://echarts.apache.org/en/dependencies.html">Dependencies</a></li><li><a href="https://echarts.apache.org/en/coding-standard.html">Code Standard</a></li><li><a href="https://github.com/apache/echarts" target="_blank">Source Code (GitHub)<svg width="15px" height="15px" viewbox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="icon-external-link"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li><a href="https://github.com/apache/echarts/issues" target="_blank">Issues (GitHub)<svg width="15px" height="15px" viewbox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="icon-external-link"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li></ul></li><li id="nav-others"><a href="#" data-toggle="dropdown" class="dropdown-toggle">ASF<b class="caret"></b></a><ul class="dropdown-menu"><li><a href="https://www.apache.org/" target="_blank">Apache Software Foundation<svg width="15px" height="15px" viewbox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="icon-external-link"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li><a href="https://echarts.apache.org/en/security.html">Security</a></li><li><a href="https://www.apache.org/licenses/" target="_blank">License<svg width="15px" height="15px" viewbox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="icon-external-link"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li><a href="https://www.apache.org/events/current-event" target="_blank">Events<svg width="15px" height="15px" viewbox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="icon-external-link"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li><a href="https://www.apache.org/foundation/sponsorship.html" target="_blank">Sponsorship<svg width="15px" height="15px" viewbox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="icon-external-link"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li><a href="https://www.apache.org/foundation/thanks.html" target="_blank">Thanks<svg width="15px" height="15px" viewbox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="icon-external-link"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li></ul></li></ul><ul class="nav navbar-nav navbar-right"><li id="nav-homeen"><a href="javascript:;" onclick='changeLang("zh")'>中文</a></li></ul></div></div></nav> <div class="page-main"><div class="page-content handbook-content single-page container-fluid row flex-xl-nowrap"><div class="bd-sidebar col-sm-3 col-md-2 closed"><div class="sidebar-search"><input id="handbook-search-intput" type="search" placeholder="Search Handbook"> <div class="search-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg></div></div> <div class="bd-docs-nav"><ul class="nav bd-sidenav nav-root level0"><li class="nav-item"><a href="/handbook/en/get-started" class="nav-link"><span class="title">Get Started</span></a> <ul class="nav bd-sidenav level1" style="display:none"></ul></li><li class="nav-item"><div class="nav-link"><span class="title">Basics</span></div> <ul class="nav bd-sidenav level1"><li class="nav-item"><a href="/handbook/en/basics/download" class="nav-link"><span class="title">Download ECharts</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/basics/import" class="nav-link"><span class="title">Import ECharts</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li><!----><li class="nav-item"><a href="/handbook/en/basics/help" class="nav-link"><span class="title">Get Help</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li><li class="nav-item"><a class="nav-link"><span class="title">What's New</span> <span class="glyphicon glyphicon-menu-down"></span></a> <ul class="nav bd-sidenav level2" style="display:none"><li class="nav-item"><a href="/handbook/en/basics/release-note/v5-feature" class="nav-link"><span class="title">ECharts 5 Features</span></a> <ul class="nav bd-sidenav level3" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/basics/release-note/v5-upgrade-guide" class="nav-link"><span class="title">Migration from v4 to v5</span></a> <ul class="nav bd-sidenav level3" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/basics/release-note/5-2-0" class="nav-link"><span class="title">5.2</span></a> <ul class="nav bd-sidenav level3" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/basics/release-note/5-3-0" class="nav-link"><span class="title">5.3</span></a> <ul class="nav bd-sidenav level3" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/basics/release-note/5-4-0" class="nav-link"><span class="title">5.4</span></a> <ul class="nav bd-sidenav level3" style="display:none"></ul></li></ul></li></ul></li><li class="nav-item"><div class="nav-link"><span class="title">Concepts</span></div> <ul class="nav bd-sidenav level1"><li class="nav-item"><a href="/handbook/en/concepts/chart-size" class="nav-link"><span class="title">Chart Container</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li><!----><!----><li class="nav-item"><a href="/handbook/en/concepts/style" class="nav-link"><span class="title">Style</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/concepts/dataset" class="nav-link"><span class="title">Dataset</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/concepts/data-transform" class="nav-link"><span class="title">Data Transform</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li><!----><li class="nav-item"><a href="/handbook/en/concepts/axis" class="nav-link"><span class="title">Axis</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/concepts/visual-map" class="nav-link"><span class="title">Visual Mapping</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/concepts/legend" class="nav-link"><span class="title">Legend</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/concepts/event" class="nav-link"><span class="title">Event and Action</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li></ul></li><li class="nav-item"><div class="nav-link"><span class="title">How To Guides</span></div> <ul class="nav bd-sidenav level1"><li class="nav-item"><a class="nav-link"><span class="title">Common Charts</span> <span class="glyphicon glyphicon-menu-down"></span></a> <ul class="nav bd-sidenav level2" style="display:none"><li class="nav-item"><a class="nav-link"><span class="title">Bar</span> <span class="glyphicon glyphicon-menu-down"></span></a> <ul class="nav bd-sidenav level3" style="display:none"><li class="nav-item"><a href="/handbook/en/how-to/chart-types/bar/basic-bar" class="nav-link"><span class="title">Basic Bar</span></a> <ul class="nav bd-sidenav level4" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/how-to/chart-types/bar/stacked-bar" class="nav-link"><span class="title">Stacked Bar</span></a> <ul class="nav bd-sidenav level4" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/how-to/chart-types/bar/bar-race" class="nav-link"><span class="title">Bar Racing</span></a> <ul class="nav bd-sidenav level4" style="display:none"></ul></li><!----><li class="nav-item"><a href="/handbook/en/how-to/chart-types/bar/waterfall" class="nav-link"><span class="title">Waterfall</span></a> <ul class="nav bd-sidenav level4" style="display:none"></ul></li></ul></li><li class="nav-item"><a class="nav-link"><span class="title">Line</span> <span class="glyphicon glyphicon-menu-down"></span></a> <ul class="nav bd-sidenav level3" style="display:none"><li class="nav-item"><a href="/handbook/en/how-to/chart-types/line/basic-line" class="nav-link"><span class="title">Basic Line</span></a> <ul class="nav bd-sidenav level4" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/how-to/chart-types/line/stacked-line" class="nav-link"><span class="title">Stacked Line</span></a> <ul class="nav bd-sidenav level4" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/how-to/chart-types/line/area-line" class="nav-link"><span class="title">Area Chart</span></a> <ul class="nav bd-sidenav level4" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/how-to/chart-types/line/smooth-line" class="nav-link"><span class="title">Smoothed Line</span></a> <ul class="nav bd-sidenav level4" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/how-to/chart-types/line/step-line" class="nav-link"><span class="title">Step Line</span></a> <ul class="nav bd-sidenav level4" style="display:none"></ul></li></ul></li><li class="nav-item"><a class="nav-link"><span class="title">Pie</span> <span class="glyphicon glyphicon-menu-down"></span></a> <ul class="nav bd-sidenav level3" style="display:none"><li class="nav-item"><a href="/handbook/en/how-to/chart-types/pie/basic-pie" class="nav-link"><span class="title">Basic Pie</span></a> <ul class="nav bd-sidenav level4" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/how-to/chart-types/pie/doughnut" class="nav-link"><span class="title">Ring Style</span></a> <ul class="nav bd-sidenav level4" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/how-to/chart-types/pie/rose" class="nav-link"><span class="title">Rose Style</span></a> <ul class="nav bd-sidenav level4" style="display:none"></ul></li></ul></li><li class="nav-item"><a class="nav-link"><span class="title">Scatter</span> <span class="glyphicon glyphicon-menu-down"></span></a> <ul class="nav bd-sidenav level3" style="display:none"><li class="nav-item"><a href="/handbook/en/how-to/chart-types/scatter/basic-scatter" class="nav-link"><span class="title">Basic Scatter</span></a> <ul class="nav bd-sidenav level4" style="display:none"></ul></li></ul></li></ul></li><!----><li class="nav-item"><a class="nav-link"><span class="title">Cross Platform</span> <span class="glyphicon glyphicon-menu-up"></span></a> <ul class="nav bd-sidenav level2"><li class="nav-item"><a href="/handbook/en/how-to/cross-platform/server" aria-current="page" class="nav-link nuxt-link-exact-active nuxt-link-active"><span class="title">Server Side Rendering</span></a> <ul class="nav bd-sidenav level3" style="display:none"></ul></li></ul></li><li class="nav-item"><a class="nav-link"><span class="title">Data</span> <span class="glyphicon glyphicon-menu-down"></span></a> <ul class="nav bd-sidenav level2" style="display:none"><li class="nav-item"><a href="/handbook/en/how-to/data/dynamic-data" class="nav-link"><span class="title">Dynamic Data</span></a> <ul class="nav bd-sidenav level3" style="display:none"></ul></li><!----></ul></li><li class="nav-item"><a class="nav-link"><span class="title">Label</span> <span class="glyphicon glyphicon-menu-down"></span></a> <ul class="nav bd-sidenav level2" style="display:none"><li class="nav-item"><a href="/handbook/en/how-to/label/rich-text" class="nav-link"><span class="title">Rich Text</span></a> <ul class="nav bd-sidenav level3" style="display:none"></ul></li></ul></li><li class="nav-item"><a class="nav-link"><span class="title">Animation</span> <span class="glyphicon glyphicon-menu-down"></span></a> <ul class="nav bd-sidenav level2" style="display:none"><li class="nav-item"><a href="/handbook/en/how-to/animation/transition" class="nav-link"><span class="title">Data Transition</span></a> <ul class="nav bd-sidenav level3" style="display:none"></ul></li></ul></li><li class="nav-item"><a class="nav-link"><span class="title">Interaction</span> <span class="glyphicon glyphicon-menu-down"></span></a> <ul class="nav bd-sidenav level2" style="display:none"><li class="nav-item"><a href="/handbook/en/how-to/interaction/drag" class="nav-link"><span class="title">Drag</span></a> <ul class="nav bd-sidenav level3" style="display:none"></ul></li><!----><li class="nav-item"><a href="/handbook/en/how-to/interaction/coarse-pointer" class="nav-link"><span class="title">Intelligent Pointer Snapping</span></a> <ul class="nav bd-sidenav level3" style="display:none"></ul></li></ul></li></ul></li><li class="nav-item"><div class="nav-link"><span class="title">Best Practices</span></div> <ul class="nav bd-sidenav level1"><!----><li class="nav-item"><a href="/handbook/en/best-practices/canvas-vs-svg" class="nav-link"><span class="title">Canvas vs. SVG</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li><li class="nav-item"><a href="/handbook/en/best-practices/aria" class="nav-link"><span class="title">Aria</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li></ul></li><li class="nav-item"><div class="nav-link"><span class="title">Edit Handbook</span></div> <ul class="nav bd-sidenav level1"><li class="nav-item"><a href="/handbook/en/meta/edit-guide" class="nav-link"><span class="title">Edit Guide</span></a> <ul class="nav bd-sidenav level2" style="display:none"></ul></li></ul></li></ul></div> <div class="open-sidebar"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg></div></div> <div class="bd-content col-sm-7 pl-sm-2 col-12"><div class="post-content content"><div><div class="post-inner"><!----> <div class="nuxt-content"><article><h1 id="server-side-rendering" tabindex="-1">Server Side Rendering</h1> <p>Normally, Apache ECharts<sup>TM</sup> renders the chart dynamically in the browser and will re-render after user interactions. However, there are specific scenarios where we also need to render charts on the server side:</p> <ul><li>Reducing the FCP time and ensuring the chart is displayed immediately.</li> <li>Embedding charts in the environments such as Markdown, PDF that do not support scripts.</li></ul> <p>In these scenarios, ECharts offers both SVG and Canvas server-side rendering (SSR) solutions.</p> <table><thead><tr><th>Solution</th> <th>Rendering Result</th> <th>Pros</th></tr></thead> <tbody><tr><td>Serverside SVG Rendering</td> <td>SVG string</td> <td>Smaller than Canvas images;<br>Vector SVG images are not blurred;<br>Support for initial animation</td></tr> <tr><td>Serverside Canvas Rendering</td> <td>Image</td> <td>The image format is available for a wider range of scenarios, and is optional for scenarios that do not support SVG</td></tr></tbody></table> <p>In general, the server-side SVG rendering solution should be preferred, or if SVG is not applicable, the Canvas rendering solution can be considered.</p> <p>Server-side rendering also has some limitations, especially some operations related to interaction cannot be supported. Therefore, if you have interaction requirements, you can refer to "Server-Side Rendering with Hydration" below.</p> <h2 id="server-side-svg-rendering" tabindex="-1">Server-Side SVG Rendering</h2> <p>If you are using 5.3.0 and newer, we strongly recommend that you use the new zero-dependency server-side string based SVG rendering solution introduced in 5.3.0.</p> <div class="md-code-block"><div class="nuxt-content-highlight"><pre class="language-ts line-numbers"><code><span class="token keyword">const</span> echarts <span class="token operator">=</span> <span class="token keyword">require</span><span class="token punctuation">(</span><span class="token string">'echarts'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// In SSR mode the first container parameter is not required</span>
<span class="token keyword">const</span> chart <span class="token operator">=</span> echarts<span class="token punctuation">.</span><span class="token function">init</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
renderer<span class="token operator">:</span> <span class="token string">'svg'</span><span class="token punctuation">,</span> <span class="token comment">// must use SVG rendering mode</span>
ssr<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token comment">// enable SSR</span>
width<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span> <span class="token comment">// need to specify height and width</span>
height<span class="token operator">:</span> <span class="token number">300</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// use setOption as normal</span>
chart<span class="token punctuation">.</span><span class="token function">setOption</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
<span class="token comment">//...</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Output a string</span>
<span class="token keyword">const</span> svgStr <span class="token operator">=</span> chart<span class="token punctuation">.</span><span class="token function">renderToSVGString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> <!----> <div class="clipboard" data-v-479657ca><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6" data-v-479657ca><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6" data-v-479657ca><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" data-v-479657ca></path></svg></svg></div></div> <p>The overall code structure is the almost same as in the browser, starting with <code>init</code> to initialise a chart example and then setting the configuration items for the chart via <code>setOption</code>. However, the parameters passed to <code>init</code> will be different from those used in the browser.</p> <ul><li>Firstly, since the SVG is rendered on the server side is string based, we don't need a container to display the rendered content, so we can pass <code>null</code> or <code>undefined</code> as the first <code>container</code> parameter in the <code>init</code>.</li> <li>Then in the third parameter of <code>init</code> we need to tell ECharts that we need to enable server-side rendering mode by specifying <code>ssr: true</code> in the display. Then ECharts will know it needs to disable the animation loop and event modules.</li> <li>We also have to specify the height and width of the chart, so if your chart size needs to be responsive to the container, you may need to think about whether server-side rendering is appropriate for your scenario.</li></ul> <p>In the browser ECharts automatically renders the result to the page after <code>setOption</code> and then determines at each frame if there is an animation that needs to be redrawn, but in NodeJS we don't do this after setting <code>ssr: true</code>. Instead, we use <code>renderToSVGString</code> to render the current chart to an SVG string, which can then be returned to the front-end via HTTP Response or saved to a local file.</p> <p>Response to the browser</p> <div class="md-code-block"><div class="nuxt-content-highlight"><pre class="language-ts line-numbers"><code>res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
<span class="token string-property property">'Content-Type'</span><span class="token operator">:</span> <span class="token string">'application/xml'</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
res<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>chart<span class="token punctuation">.</span><span class="token function">renderToSVGString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> <!----> <div class="clipboard" data-v-479657ca><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6" data-v-479657ca><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6" data-v-479657ca><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" data-v-479657ca></path></svg></svg></div></div> <p>Or save to a local file</p> <div class="md-code-block"><div class="nuxt-content-highlight"><pre class="language-ts line-numbers"><code>fs<span class="token punctuation">.</span><span class="token function">writeFile</span><span class="token punctuation">(</span><span class="token string">'bar.svg'</span><span class="token punctuation">,</span> chart<span class="token punctuation">.</span><span class="token function">renderToSVGString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> <!----> <div class="clipboard" data-v-479657ca><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6" data-v-479657ca><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6" data-v-479657ca><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" data-v-479657ca></path></svg></svg></div></div> <p>Here is a complete server-side SVG rendering example in CodeSandbox.</p> <iframe src="https://codesandbox.io/embed/heuristic-leftpad-oq23t?autoresize=1&codemirror=1&fontsize=12&hidenavigation=1&&theme= dark" title="heuristic-leftpad-oq23t" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr- spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts" style="width:100%;height:400px;border:0;border-radius:4px;overflow:hidden"></iframe> <h3 id="animations-in-server-side-rendering" tabindex="-1">Animations in Server-side Rendering</h3> <p>As you can see in the example above, even using server-side rendering, ECharts can still provide animation effects, which are achieved by embedding CSS animations in the output SVG string. There is no need for additional JavaScript to play the animation.</p> <p>However, the limitations of CSS animation prevent us from implementing more flexible animations in server-side rendering, such as bar chart racing animations, label animations, and special effects animations in the <code>lines</code> series. Animation of some of the series, such as the <code>pie</code>, have been specially optimised for server-side rendering.</p> <p>If you don't want this animation, you can turn it off by setting <code>animation: false</code> when <code>setOption</code>.</p> <div class="md-code-block"><div class="nuxt-content-highlight"><pre class="language-ts line-numbers"><code><span class="token function">setOption</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
animation<span class="token operator">:</span> <span class="token boolean">false</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> <!----> <div class="clipboard" data-v-479657ca><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6" data-v-479657ca><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6" data-v-479657ca><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" data-v-479657ca></path></svg></svg></div></div> <h2 id="server-side-canvas-rendering" tabindex="-1">Server-side Canvas rendering</h2> <p>If you want the output to be an image rather than an SVG string, or if you're still using an older version, we'd recommend using <a href="https://github.com/Automattic/node-canvas">node-canvas</a> for server-side rendering, <a href="https://github.com/Automattic/node-canvas">node-canvas</a> is Canvas implementations on NodeJS that provide an interface that is almost identical to the Canvas in the browser.</p> <p>Here's a simple example</p> <div class="md-code-block"><div class="nuxt-content-highlight"><pre class="language-ts line-numbers"><code><span class="token keyword">var</span> echarts <span class="token operator">=</span> <span class="token keyword">require</span><span class="token punctuation">(</span><span class="token string">'echarts'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> createCanvas <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">require</span><span class="token punctuation">(</span><span class="token string">'canvas'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// In versions ealier than 5.3.0, you had to register the canvas factory with setCanvasCreator.</span>
<span class="token comment">// Not necessary since 5.3.0</span>
echarts<span class="token punctuation">.</span><span class="token function">setCanvasCreator</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">createCanvas</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> canvas <span class="token operator">=</span> <span class="token function">createCanvas</span><span class="token punctuation">(</span><span class="token number">800</span><span class="token punctuation">,</span> <span class="token number">600</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// ECharts can use the Canvas instance created by node-canvas as a container directly</span>
<span class="token keyword">const</span> chart <span class="token operator">=</span> echarts<span class="token punctuation">.</span><span class="token function">init</span><span class="token punctuation">(</span>canvas<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// setOption as normal</span>
chart<span class="token punctuation">.</span><span class="token function">setOption</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
<span class="token comment">//...</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Output the PNG image via Response</span>
res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
<span class="token string-property property">'Content-Type'</span><span class="token operator">:</span> <span class="token string">'image/png'</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
res<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token function">renderChart</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBuffer</span><span class="token punctuation">(</span><span class="token string">'image/png'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> <!----> <div class="clipboard" data-v-479657ca><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6" data-v-479657ca><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6" data-v-479657ca><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" data-v-479657ca></path></svg></svg></div></div> <p>Here is a complete example in CodeSandbox</p> <iframe src="https://codesandbox.io/embed/apache-echarts-canvas-ssr-demo-e340rt?autoresize=1&codemirror=1&fontsize=12& hidenavigation=1&&theme=dark" title="heuristic-leftpad-oq23t" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr- spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts" style="width:100%;height:400px;border:0;border-radius:4px;overflow:hidden"></iframe> <h3 id="loading-of-images" tabindex="-1">Loading of images</h3> <p><a href="https://github.com/Automattic/node-canvas">node-canvas</a> provides an <code>Image</code> implementation for image loading. If you use to images in your code, we can adapt them using the <code>setPlatformAPI</code> interface that was introduced in <code>5.3.0</code>.</p> <div class="md-code-block"><div class="nuxt-content-highlight"><pre class="language-ts line-numbers"><code>echarts<span class="token punctuation">.</span><span class="token function">setPlatformAPI</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
<span class="token comment">// Same with the old setCanvasCreator</span>
<span class="token function">createCanvas</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">createCanvas</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">loadImage</span><span class="token punctuation">(</span>src<span class="token punctuation">,</span> onload<span class="token punctuation">,</span> onerror<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> img <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Image</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// must be bound to this context.</span>
img<span class="token punctuation">.</span>onload <span class="token operator">=</span> <span class="token function">onload</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>img<span class="token punctuation">)</span><span class="token punctuation">;</span>
img<span class="token punctuation">.</span>onerror <span class="token operator">=</span> <span class="token function">onerror</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>img<span class="token punctuation">)</span><span class="token punctuation">;</span>
img<span class="token punctuation">.</span>src <span class="token operator">=</span> src<span class="token punctuation">;</span>
<span class="token keyword">return</span> img<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> <!----> <div class="clipboard" data-v-479657ca><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6" data-v-479657ca><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-6 w-6" data-v-479657ca><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" data-v-479657ca></path></svg></svg></div></div> <p>If you are using images from remote, we recommend that you prefetch the image via an http request to get <code>base64</code> before passing it on as the URL of the image, to ensure that the image is loaded when render.</p> <h2 id="server-side-rendering-with-hydration" tabindex="-1">Server-Side Rendering with Hydration</h2> <p>Features that cannot be supported by server-side rendering include</p> <ul><li>Dynamically changing data</li> <li>Highlighting the data item where the mouse is hovered</li> <li>Clicking on a legend to toggle whether the series is displayed or not</li> <li>Moving the mouse to show a tooltip</li> <li>Other interaction-related features</li></ul> <p>If you have such requirements, you can consider using server-side rendering to quickly output the first screen chart, then wait for <code>echarts.js</code> to finish loading and re-render the same chart on the client side, so that you can achieve normal interaction effects and dynamically change the data. Note that when rendering on the client side, you should turn on interactive components like <code>tooltip: { show: true }</code> and turn off the initial animation with <code>animation: 0</code> (the initial animation should be done by the SVG animation of the rendered result on the server side).</p> <p>Here is an example of building a CodeSandbox with SVG for server-side rendering and Canvas for client-side rendering. It is recommended to click "Open Sandbox" to learn the code implementation.</p> <blockquote><p>If you want to use Canvas for server-side rendering or SVG for client-side rendering, it's similar, so I won't go over it again.</p></blockquote> <iframe src="https://codesandbox.io/embed/apache-echarts-5-3-ssr-csr-0jvsdu?fontsize=14&hidenavigation=1&theme=dark" title="Apache ECharts 5.3 SSR + CSR" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts" style="width:100%;height:400px;border:0;border-radius:4px;overflow:hidden"></iframe> <p>As we can see, from the user experience point of view, there is almost no secondary rendering process, and the whole switching effect is very seamless. You can also use a library like <a href="https://www.npmjs.com/package/pace-js">pace-js</a> to display the loading progress bar during the loading of <code>echarts.js</code> as in the above example to solve the problem of no interactive feedback before the ECharts are fully loaded.</p></article></div></div> <div class="post-contributors"><h3><span class="inline-block align-middle">Contributors</span> <a target="_blank" href="https://github.com/apache/echarts-handbook/tree/master/contents/en/how-to/cross-platform/server.md" title="Edit this Document" class="inline-block align-middle text-sm"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-8 w-8 inline-block align-middle"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path></svg> <span class="inline-block align-middle">Edit this page on GitHub</span></a></h3> <div class="post-contributors-list"><a href="https://github.com/Ovilia" target="_blank" class="post-contributor"><img alt="Ovilia" src="https://avatars.githubusercontent.com/Ovilia?size=60" loading="lazy"> <span>Ovilia</span></a><a href="https://github.com/pissang" target="_blank" class="post-contributor"><img alt="pissang" src="https://avatars.githubusercontent.com/pissang?size=60" loading="lazy"> <span>pissang</span></a><a href="https://github.com/balloon72" target="_blank" class="post-contributor"><img alt="balloon72" src="https://avatars.githubusercontent.com/balloon72?size=60" loading="lazy"> <span>balloon72</span></a></div></div></div></div></div></div> <link rel="stylesheet" href="//fastly.jsdelivr.net/npm/highlight.js@9.12.0/styles/github-gist.min.css"></div></div></div></div><script>window.__NUXT__=function(e,t,i,r,n,a,d,o,l,s,c,h,p,m,g,u,b,f,v,y,w,C,I,S,G,Z,V,B,R,W,k,H,x,Y,X,F,J,A,K,N,z,L,T,P,M,j,E,D,Q,U,O,q,_,$,ee,te,ie,re){return{layout:"default",data:[{html:'<h1 id="server-side-rendering" tabindex="-1">Server Side Rendering</h1>\n<p>Normally, Apache ECharts<sup>TM</sup> renders the chart dynamically in the browser and will re-render after user interactions. However, there are specific scenarios where we also need to render charts on the server side:</p>\n<ul>\n<li>Reducing the FCP time and ensuring the chart is displayed immediately.</li>\n<li>Embedding charts in the environments such as Markdown, PDF that do not support scripts.</li>\n</ul>\n<p>In these scenarios, ECharts offers both SVG and Canvas server-side rendering (SSR) solutions.</p>\n<table>\n<thead>\n<tr>\n<th>Solution</th>\n<th>Rendering Result</th>\n<th>Pros</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Serverside SVG Rendering</td>\n<td>SVG string</td>\n<td>Smaller than Canvas images;<br>Vector SVG images are not blurred;<br>Support for initial animation</td>\n</tr>\n<tr>\n<td>Serverside Canvas Rendering</td>\n<td>Image</td>\n<td>The image format is available for a wider range of scenarios, and is optional for scenarios that do not support SVG</td>\n</tr>\n</tbody>\n</table>\n<p>In general, the server-side SVG rendering solution should be preferred, or if SVG is not applicable, the Canvas rendering solution can be considered.</p>\n<p>Server-side rendering also has some limitations, especially some operations related to interaction cannot be supported. Therefore, if you have interaction requirements, you can refer to &quot;Server-Side Rendering with Hydration&quot; below.</p>\n<h2 id="server-side-svg-rendering" tabindex="-1">Server-Side SVG Rendering</h2>\n<p>If you are using 5.3.0 and newer, we strongly recommend that you use the new zero-dependency server-side string based SVG rendering solution introduced in 5.3.0.</p>\n<md-code-block lang="ts" code="\'Y29uc3QgZWNoYXJ0cyA9IHJlcXVpcmUoJ2VjaGFydHMnKTsKCi8vIEluIFNTUiBtb2RlIHRoZSBmaXJzdCBjb250YWluZXIgcGFyYW1ldGVyIGlzIG5vdCByZXF1aXJlZApjb25zdCBjaGFydCA9IGVjaGFydHMuaW5pdChudWxsLCBudWxsLCB7CiAgcmVuZGVyZXI6ICdzdmcnLCAvLyBtdXN0IHVzZSBTVkcgcmVuZGVyaW5nIG1vZGUKICBzc3I6IHRydWUsIC8vIGVuYWJsZSBTU1IKICB3aWR0aDogNDAwLCAvLyBuZWVkIHRvIHNwZWNpZnkgaGVpZ2h0IGFuZCB3aWR0aAogIGhlaWdodDogMzAwCn0pOwoKLy8gdXNlIHNldE9wdGlvbiBhcyBub3JtYWwKY2hhcnQuc2V0T3B0aW9uKHsKICAvLy4uLgp9KTsKCi8vIE91dHB1dCBhIHN0cmluZwpjb25zdCBzdmdTdHIgPSBjaGFydC5yZW5kZXJUb1NWR1N0cmluZygpOw\'" line-highlights="\'\'" />\n<p>The overall code structure is the almost same as in the browser, starting with <code>init</code> to initialise a chart example and then setting the configuration items for the chart via <code>setOption</code>. However, the parameters passed to <code>init</code> will be different from those used in the browser.</p>\n<ul>\n<li>Firstly, since the SVG is rendered on the server side is string based, we don\'t need a container to display the rendered content, so we can pass <code>null</code> or <code>undefined</code> as the first <code>container</code> parameter in the <code>init</code>.</li>\n<li>Then in the third parameter of <code>init</code> we need to tell ECharts that we need to enable server-side rendering mode by specifying <code>ssr: true</code> in the display. Then ECharts will know it needs to disable the animation loop and event modules.</li>\n<li>We also have to specify the height and width of the chart, so if your chart size needs to be responsive to the container, you may need to think about whether server-side rendering is appropriate for your scenario.</li>\n</ul>\n<p>In the browser ECharts automatically renders the result to the page after <code>setOption</code> and then determines at each frame if there is an animation that needs to be redrawn, but in NodeJS we don\'t do this after setting <code>ssr: true</code>. Instead, we use <code>renderToSVGString</code> to render the current chart to an SVG string, which can then be returned to the front-end via HTTP Response or saved to a local file.</p>\n<p>Response to the browser</p>\n<md-code-block lang="ts" code="\'cmVzLndyaXRlSGVhZCgyMDAsIHsKICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL3htbCcKfSk7CnJlcy53cml0ZShjaGFydC5yZW5kZXJUb1NWR1N0cmluZygpKTsKcmVzLmVuZCgpOw\'" line-highlights="\'\'" />\n<p>Or save to a local file</p>\n<md-code-block lang="ts" code="\'ZnMud3JpdGVGaWxlKCdiYXIuc3ZnJywgY2hhcnQucmVuZGVyVG9TVkdTdHJpbmcoKSwgJ3V0Zi04Jyk7\'" line-highlights="\'\'" />\n<p>Here is a complete server-side SVG rendering example in CodeSandbox.</p>\n<iframe src="https://codesandbox.io/embed/heuristic-leftpad-oq23t?autoresize=1&codemirror=1&fontsize=12&hidenavigation=1&&theme= dark"\n style="width:100%; height:400px; border:0; border-radius: 4px; overflow:hidden;"\n title="heuristic-leftpad-oq23t"\n allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr- spatial-tracking"\n sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"\n ></iframe>\n<h3 id="animations-in-server-side-rendering" tabindex="-1">Animations in Server-side Rendering</h3>\n<p>As you can see in the example above, even using server-side rendering, ECharts can still provide animation effects, which are achieved by embedding CSS animations in the output SVG string. There is no need for additional JavaScript to play the animation.</p>\n<p>However, the limitations of CSS animation prevent us from implementing more flexible animations in server-side rendering, such as bar chart racing animations, label animations, and special effects animations in the <code>lines</code> series. Animation of some of the series, such as the <code>pie</code>, have been specially optimised for server-side rendering.</p>\n<p>If you don\'t want this animation, you can turn it off by setting <code>animation: false</code> when <code>setOption</code>.</p>\n<md-code-block lang="ts" code="\'c2V0T3B0aW9uKHsKICBhbmltYXRpb246IGZhbHNlCn0pOw\'" line-highlights="\'\'" />\n<h2 id="server-side-canvas-rendering" tabindex="-1">Server-side Canvas rendering</h2>\n<p>If you want the output to be an image rather than an SVG string, or if you\'re still using an older version, we\'d recommend using <a href="https://github.com/Automattic/node-canvas">node-canvas</a> for server-side rendering, <a href="https://github.com/Automattic/node-canvas">node-canvas</a> is Canvas implementations on NodeJS that provide an interface that is almost identical to the Canvas in the browser.</p>\n<p>Here\'s a simple example</p>\n<md-code-block lang="ts" code="\'dmFyIGVjaGFydHMgPSByZXF1aXJlKCdlY2hhcnRzJyk7CmNvbnN0IHsgY3JlYXRlQ2FudmFzIH0gPSByZXF1aXJlKCdjYW52YXMnKTsKCi8vIEluIHZlcnNpb25zIGVhbGllciB0aGFuIDUuMy4wLCB5b3UgaGFkIHRvIHJlZ2lzdGVyIHRoZSBjYW52YXMgZmFjdG9yeSB3aXRoIHNldENhbnZhc0NyZWF0b3IuCi8vIE5vdCBuZWNlc3Nhcnkgc2luY2UgNS4zLjAKZWNoYXJ0cy5zZXRDYW52YXNDcmVhdG9yKCgpID0-IHsKICByZXR1cm4gY3JlYXRlQ2FudmFzKCk7Cn0pOwoKY29uc3QgY2FudmFzID0gY3JlYXRlQ2FudmFzKDgwMCwgNjAwKTsKLy8gRUNoYXJ0cyBjYW4gdXNlIHRoZSBDYW52YXMgaW5zdGFuY2UgY3JlYXRlZCBieSBub2RlLWNhbnZhcyBhcyBhIGNvbnRhaW5lciBkaXJlY3RseQpjb25zdCBjaGFydCA9IGVjaGFydHMuaW5pdChjYW52YXMpOwoKLy8gc2V0T3B0aW9uIGFzIG5vcm1hbApjaGFydC5zZXRPcHRpb24oewogIC8vLi4uCn0pOwoKLy8gT3V0cHV0IHRoZSBQTkcgaW1hZ2UgdmlhIFJlc3BvbnNlCnJlcy53cml0ZUhlYWQoMjAwLCB7CiAgJ0NvbnRlbnQtVHlwZSc6ICdpbWFnZS9wbmcnCn0pOwpyZXMud3JpdGUocmVuZGVyQ2hhcnQoKS50b0J1ZmZlcignaW1hZ2UvcG5nJykpOwpyZXMuZW5kKCk7\'" line-highlights="\'\'" />\n<p>Here is a complete example in CodeSandbox</p>\n<iframe src="https://codesandbox.io/embed/apache-echarts-canvas-ssr-demo-e340rt?autoresize=1&codemirror=1&fontsize=12& hidenavigation=1&&theme=dark"\n style="width:100%; height:400px; border:0; border-radius: 4px; overflow:hidden;"\n title="heuristic-leftpad-oq23t"\n allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr- spatial-tracking"\n sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"\n ></iframe>\n<h3 id="loading-of-images" tabindex="-1">Loading of images</h3>\n<p><a href="https://github.com/Automattic/node-canvas">node-canvas</a> provides an <code>Image</code> implementation for image loading. If you use to images in your code, we can adapt them using the <code>setPlatformAPI</code> interface that was introduced in <code>5.3.0</code>.</p>\n<md-code-block lang="ts" code="\'ZWNoYXJ0cy5zZXRQbGF0Zm9ybUFQSSh7CiAgLy8gU2FtZSB3aXRoIHRoZSBvbGQgc2V0Q2FudmFzQ3JlYXRvcgogIGNyZWF0ZUNhbnZhcygpIHsKICAgIHJldHVybiBjcmVhdGVDYW52YXMoKTsKICB9LAogIGxvYWRJbWFnZShzcmMsIG9ubG9hZCwgb25lcnJvcikgewogICAgY29uc3QgaW1nID0gbmV3IEltYWdlKCk7CiAgICAvLyBtdXN0IGJlIGJvdW5kIHRvIHRoaXMgY29udGV4dC4KICAgIGltZy5vbmxvYWQgPSBvbmxvYWQuYmluZChpbWcpOwogICAgaW1nLm9uZXJyb3IgPSBvbmVycm9yLmJpbmQoaW1nKTsKICAgIGltZy5zcmMgPSBzcmM7CiAgICByZXR1cm4gaW1nOwogIH0KfSk7\'" line-highlights="\'\'" />\n<p>If you are using images from remote, we recommend that you prefetch the image via an http request to get <code>base64</code> before passing it on as the URL of the image, to ensure that the image is loaded when render.</p>\n<h2 id="server-side-rendering-with-hydration" tabindex="-1">Server-Side Rendering with Hydration</h2>\n<p>Features that cannot be supported by server-side rendering include</p>\n<ul>\n<li>Dynamically changing data</li>\n<li>Highlighting the data item where the mouse is hovered</li>\n<li>Clicking on a legend to toggle whether the series is displayed or not</li>\n<li>Moving the mouse to show a tooltip</li>\n<li>Other interaction-related features</li>\n</ul>\n<p>If you have such requirements, you can consider using server-side rendering to quickly output the first screen chart, then wait for <code>echarts.js</code> to finish loading and re-render the same chart on the client side, so that you can achieve normal interaction effects and dynamically change the data. Note that when rendering on the client side, you should turn on interactive components like <code>tooltip: { show: true }</code> and turn off the initial animation with <code>animation: 0</code> (the initial animation should be done by the SVG animation of the rendered result on the server side).</p>\n<p>Here is an example of building a CodeSandbox with SVG for server-side rendering and Canvas for client-side rendering. It is recommended to click &quot;Open Sandbox&quot; to learn the code implementation.</p>\n<blockquote>\n<p>If you want to use Canvas for server-side rendering or SVG for client-side rendering, it\'s similar, so I won\'t go over it again.</p>\n</blockquote>\n<iframe src="https://codesandbox.io/embed/apache-echarts-5-3-ssr-csr-0jvsdu?fontsize=14&hidenavigation=1&theme=dark"\n style="width:100%; height:400px; border:0; border-radius: 4px; overflow:hidden;"\n title="Apache ECharts 5.3 SSR + CSR"\n allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"\n sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"\n ></iframe>\n<p>As we can see, from the user experience point of view, there is almost no secondary rendering process, and the whole switching effect is very seamless. You can also use a library like <a href="https://www.npmjs.com/package/pace-js">pace-js</a> to display the loading progress bar during the loading of <code>echarts.js</code> as in the above example to solve the problem of no interactive feedback before the ECharts are fully loaded.</p>\n',postPath:"en/how-to/cross-platform/server",title:"Server Side Rendering - Cross Platform - How To Guides"}],fetch:{},error:null,state:{filled:!1,docVersion:"",ghVersion:"",visibleAffix:!1,homepage:{},adBlocked:!1,focusMode:!1,posts:{zh:[{title:"快速上手",dir:r},{title:"入门篇",dir:n,children:[{title:"获取 ECharts",dir:a},{title:"在项目中引入 ECharts",dir:d},{title:"资源列表",dir:o,draft:e},{title:"寻求帮助",dir:l},{title:"版本特性",dir:s,children:[{title:"ECharts 5 特性介绍",dir:c},{title:"v4 升级 v5 指南",dir:h},{title:5.2,dir:p},{title:5.3,dir:m},{title:5.4,dir:g}]}]},{title:"概念篇",dir:u,children:[{title:"图表容器及大小",dir:b},{title:"配置项",dir:f,draft:e},{title:"系列",dir:v,draft:e},{title:"样式",dir:y},{title:"数据集",dir:w},{title:"数据转换",dir:C},{title:"坐标系",dir:I,draft:e},{title:"坐标轴",dir:S},{title:"视觉映射",dir:i},{title:"图例",dir:G},{title:"事件与行为",dir:Z}]},{title:"应用篇",dir:V,children:[{title:"常用图表类型",dir:B,children:[{title:"柱状图",dir:"bar",children:[{title:"基础柱状图",dir:R},{title:"堆叠柱状图",dir:W},{title:"动态排序柱状图",dir:k},{title:"极坐标系柱状图",dir:H,draft:e},{title:"阶梯瀑布图",dir:x},{title:"视觉映射的柱状图",dir:i,draft:e}]},{title:"折线图",dir:Y,children:[{title:"基础折线图",dir:X},{title:"堆叠折线图",dir:F},{title:"区域面积图",dir:J},{title:"平滑曲线图",dir:A},{title:"阶梯线图",dir:K}]},{title:"饼图",dir:"pie",children:[{title:"基础饼图",dir:N},{title:"圆环图",dir:z},{title:"南丁格尔图(玫瑰图)",dir:L}]},{title:"散点图",dir:T,children:[{title:"基础散点图",dir:P}]}]},{title:M,dir:t,draft:e},{title:"跨平台方案",dir:j,children:[{title:"服务端渲染",dir:"server"},{title:"微信小程序",dir:"wechat-app"},{title:"百度智能小程序",dir:"baidu-app"}]},{title:"数据处理",dir:"data",children:[{title:"动态的异步数据",dir:E},{title:"数据下钻",dir:D,draft:e}]},{title:"标签",dir:"label",children:[{title:"富文本标签",dir:Q}]},{title:"动画",dir:U,children:[{title:"数据过渡动画",dir:O}]},{title:"交互",dir:q,children:[{title:"拖拽的实现",dir:"drag"},{title:"多图联动",dir:_,draft:e},{title:"智能指针吸附",dir:$}]}]},{title:"最佳实践",dir:ee,children:[{title:M,dir:t,draft:e},{title:te,dir:ie},{title:"无障碍访问",dir:"aria"}]},{title:"编辑本文档",dir:"meta",children:[{title:"文档编辑指南",dir:re}]}],en:[{title:"Get Started",dir:r},{title:"Basics",dir:n,children:[{title:"Download ECharts",dir:a},{title:"Import ECharts",dir:d},{title:"Resources",dir:o,draft:e},{title:"Get Help",dir:l},{title:"What's New",dir:s,children:[{title:"ECharts 5 Features",dir:c},{title:"Migration from v4 to v5",dir:h},{title:5.2,dir:p},{title:5.3,dir:m},{title:5.4,dir:g}]}]},{title:"Concepts",dir:u,children:[{title:"Chart Container",dir:b},{title:"Chart Option",dir:f,draft:e},{title:"Series",dir:v,draft:e},{title:"Style",dir:y},{title:"Dataset",dir:w},{title:"Data Transform",dir:C},{title:"Coordinate",dir:I,draft:e},{title:"Axis",dir:S},{title:"Visual Mapping",dir:i},{title:"Legend",dir:G},{title:"Event and Action",dir:Z}]},{title:"How To Guides",dir:V,children:[{title:"Common Charts",dir:B,children:[{title:"Bar",dir:"bar",children:[{title:"Basic Bar",dir:R},{title:"Stacked Bar",dir:W},{title:"Bar Racing",dir:k},{title:"Bar Polar",dir:H,draft:e},{title:"Waterfall",dir:x}]},{title:"Line",dir:Y,children:[{title:"Basic Line",dir:X},{title:"Stacked Line",dir:F},{title:"Area Chart",dir:J},{title:"Smoothed Line",dir:A},{title:"Step Line",dir:K}]},{title:"Pie",dir:"pie",children:[{title:"Basic Pie",dir:N},{title:"Ring Style",dir:z},{title:"Rose Style",dir:L}]},{title:"Scatter",dir:T,children:[{title:"Basic Scatter",dir:P}]}]},{title:"Mobile",dir:t,draft:e},{title:"Cross Platform",dir:j,children:[{title:"Server Side Rendering",dir:"server"}]},{title:"Data",dir:"data",children:[{title:"Dynamic Data",dir:E},{title:"Drilldown",dir:D,draft:e}]},{title:"Label",dir:"label",children:[{title:"Rich Text",dir:Q}]},{title:"Animation",dir:U,children:[{title:"Data Transition",dir:O}]},{title:"Interaction",dir:q,children:[{title:"Drag",dir:"drag"},{title:"Connect",dir:_,draft:e},{title:"Intelligent Pointer Snapping",dir:$}]}]},{title:"Best Practices",dir:ee,children:[{title:"Mobile Optimization",dir:t,draft:e},{title:te,dir:ie},{title:"Aria",dir:"aria"}]},{title:"Edit Handbook",dir:"meta",children:[{title:"Edit Guide",dir:re}]}]},config:{routerBase:"/handbook",rootPath:"https://echarts.apache.org/handbook/",exampleViewPath:"https://echarts.apache.org/examples/${lang}/view.html?c=",exampleEditorPath:"https://echarts.apache.org/examples/${lang}/editor.html?c=",mainSitePath:"https://echarts.apache.org/",optionPath:"https://echarts.apache.org/option.html#",gitRepo:"apache/echarts-handbook"},i18n:{routeParams:{}}},serverRendered:e,routePath:"/en/how-to/cross-platform/server",config:{_app:{basePath:"/handbook/",assetsPath:"/handbook/_nuxt/",cdnURL:null}}}}(!0,"mobile","visual-map","get-started","basics","download","import","resource","help","release-note","v5-feature","v5-upgrade-guide","5-2-0","5-3-0","5-4-0","concepts","chart-size","options","series","style","dataset","data-transform","coordinate","axis","legend","event","how-to","chart-types","basic-bar","stacked-bar","bar-race","polar-bar","waterfall","line","basic-line","stacked-line","area-line","smooth-line","step-line","basic-pie","doughnut","rose","scatter","basic-scatter","移动端优化","cross-platform","dynamic-data","drilldown","rich-text","animation","transition","interaction","connect","coarse-pointer","best-practices","Canvas vs. SVG","canvas-vs-svg","edit-guide")</script><script src="/handbook/_nuxt/4d2a12b.js" defer></script><script src="/handbook/_nuxt/js/43cd67c0cf5a9d972051.js" defer></script><script src="/handbook/_nuxt/js/9d86a6602b3f4dd6c979.js" defer></script><script src="/handbook/_nuxt/js/fa73816a85b29fbf7562.js" defer></script><script src="/handbook/_nuxt/js/b964c20bb1562bc48da6.js" defer></script><script src="/handbook/_nuxt/js/60d2f1dbd961abb7604b.js" defer></script>
<script type="text/javascript">document.getElementById("nav-doc").className="active"</script>
<script src="https://fastly.jsdelivr.net/npm/jquery@2.2.4/dist/jquery.min.js"></script>
<script src="https://fastly.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="https://fastly.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js"></script>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-141228404-1"></script>
<script>var _hmt=_hmt||[];function gtag(){dataLayer.push(arguments)}!function(){var e=document.createElement("script"),t=(e.src="https://hm.baidu.com/hm.js?54b918eee37cb8a7045f0fd0f0b24395",document.getElementsByTagName("script")[0]);t.parentNode.insertBefore(e,t)}(),window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","UA-141228404-1")</script>
</body>
</html>