Skip to content

Commit a3f570a

Browse files
committed
doc: add doc for ssr apache/echarts#18381
1 parent 007afe8 commit a3f570a

File tree

7 files changed

+266
-32
lines changed

7 files changed

+266
-32
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Apache ECharts 5.5.0 Features
2+
3+
## Enhanced ESM Support
4+
5+
This feature is a significant change to the default ESM package, specifically designed for developer testing and Node.js usage in module customization scenarios.
6+
7+
Previously, ECharts only exported `*.esm` files in npm (in the lib directory of the npm package). While this worked well in bundlers, it didn’t perform as well in the Node.js runtime and some Node.js-based testing frameworks like vitest and jest.
8+
9+
With this new feature, we’ve made several changes to improve this:
10+
11+
- Added `"type": "module"` to package.json
12+
- Added `"exports": {...}"` to package.json
13+
- Added some `package.json` files to the sub-directory, which only contain `"type": "commonjs"`.
14+
15+
These changes mean that files like `echarts/core.js` can now be resolved as ESM in environments like pure Node.js, vitest, jest, and create-react-app.
16+
17+
Please note that if using `"exports"`, the files that are not declared in "exports" will be invisible from outside any more. Also, the path must start with `'.'`.
18+
19+
We’ve also ensured that this new feature is compatible with a variety of environments, including runtime (node / vitest / jest(create-react-app) / ssr / …) and bundlers (webpack / rollup / vite / esbuild / …).
20+
21+
We’re excited about this new feature and believe it will significantly improve the developer experience.

contents/en/how-to/cross-platform/server.md

Lines changed: 107 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,17 @@ Server-side rendering also has some limitations, especially some operations rela
1818

1919
## Server-Side SVG Rendering
2020

21-
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.
21+
### Server-Side SVG Rendering
22+
23+
> Version Update:
24+
>
25+
> - 5.3.0: Introduced a new zero-dependency server-side string based SVG rendering solution, and support for initial animation
26+
> - 5.5.0: Added a lightweight client runtime, which allows some interaction without the need to load the full ECharts on the client side
27+
28+
We introduced a new zero-dependency server-side string based SVG rendering solution in 5.3.0.
2229

2330
```ts
31+
// Server-side code
2432
const echarts = require('echarts');
2533

2634
// In SSR mode the first container parameter is not required
@@ -48,24 +56,24 @@ The overall code structure is the almost same as in the browser, starting with `
4856

4957
- 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 `null` or `undefined` as the first `container` parameter in the `init`.
5058
- Then in the third parameter of `init` we need to tell ECharts that we need to enable server-side rendering mode by specifying `ssr: true` in the display. Then ECharts will know it needs to disable the animation loop and event modules.
51-
- 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.
59+
- 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.
5260

53-
In the browser ECharts automatically renders the result to the page after `setOption` 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 `ssr: true`. Instead, we use `renderToSVGString` 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.
61+
In the browser ECharts automatically renders the result to the page after `setOption` and then determines at each frame if there is an animation that needs to be redrawn, but in Node.js we don't do this after setting `ssr: true`. Instead, we use `renderToSVGString` 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.
5462

5563
Response to the browser
5664

5765
```ts
5866
res.writeHead(200, {
5967
'Content-Type': 'application/xml'
6068
});
61-
res.write(chart.renderToSVGString());
69+
res.write(svgStr); // svgStr is the result of chart.renderToSVGString()
6270
res.end();
6371
```
6472

6573
Or save to a local file
6674

6775
```ts
68-
fs.writeFile('bar.svg', chart.renderToSVGString(), 'utf-8');
76+
fs.writeFile('bar.svg', svgStr, 'utf-8');
6977
```
7078

7179
Here is a complete server-side SVG rendering example in CodeSandbox.
@@ -77,7 +85,7 @@ Here is a complete server-side SVG rendering example in CodeSandbox.
7785
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
7886
></iframe>
7987
80-
### Animations in Server-side Rendering
88+
#### Animations in Server-side Rendering
8189

8290
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.
8391

@@ -91,9 +99,9 @@ setOption({
9199
});
92100
```
93101

94-
## Server-side Canvas rendering
102+
### Server-side Canvas rendering
95103

96-
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 [node-canvas](https://github.com/Automattic/node-canvas) for server-side rendering, [node-canvas](https://github.com/Automattic/node-canvas) is Canvas implementations on NodeJS that provide an interface that is almost identical to the Canvas in the browser.
104+
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 [node-canvas](https://github.com/Automattic/node-canvas) for server-side rendering, [node-canvas](https://github.com/Automattic/node-canvas) is Canvas implementations on Node.js that provide an interface that is almost identical to the Canvas in the browser.
97105

98106
Here's a simple example
99107

@@ -139,7 +147,7 @@ Here is a complete example in CodeSandbox
139147
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
140148
></iframe>
141149
142-
### Loading of images
150+
#### Loading of images
143151

144152
[node-canvas](https://github.com/Automattic/node-canvas) provides an `Image` implementation for image loading. If you use to images in your code, we can adapt them using the `setPlatformAPI` interface that was introduced in `5.3.0`.
145153

@@ -162,12 +170,18 @@ echarts.setPlatformAPI({
162170

163171
If you are using images from remote, we recommend that you prefetch the image via an http request to get `base64` before passing it on as the URL of the image, to ensure that the image is loaded when render.
164172

165-
## Server-Side Rendering with Hydration
173+
## Server-Side Rendering and Hydration
174+
175+
### Solution A: Server-Side Rendering with a lazy-loading ECharts on the Client Side
176+
177+
With the latest version of ECharts, the server-side rendering solution can do the following things along with rendering the chart:
178+
179+
- Support for initial animation (i.e., the animation that is played when the chart is first rendered)
180+
- Highlighting styles (i.e., the highlighting effect when the mouse moves over a bar in a bar chart)
166181

167-
Features that cannot be supported by server-side rendering include
182+
But there are features that cannot be supported by server-side rendering:
168183

169184
- Dynamically changing data
170-
- Highlighting the data item where the mouse is hovered
171185
- Clicking on a legend to toggle whether the series is displayed or not
172186
- Moving the mouse to show a tooltip
173187
- Other interaction-related features
@@ -186,3 +200,84 @@ Here is an example of building a CodeSandbox with SVG for server-side rendering
186200
></iframe>
187201
188202
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 [pace-js](https://www.npmjs.com/package/pace-js) to display the loading progress bar during the loading of `echarts.js` as in the above example to solve the problem of no interactive feedback before the ECharts are fully loaded.
203+
204+
Using server-side rendering with client-side rendering along with a lazy-loading `echarts.js` on the client side is a good solution for scenarios where the first screen needs to be rendered quickly and then the interaction needs to be supported. However, it takes some time to load the `echarts.js` and before it is fully loaded, there is no interactive feedback, in which case, a "Loading" text might be displayed to the user. This is a commonly recommended solution for scenarios where the first screen needs to be rendered quickly and then the interaction needs to be supported.
205+
206+
### Solution B: Server-Side Rendering with a lightweight client runtime
207+
208+
Solution A provides a way for implementing complete interactions, but in some scenarios, we don't need complex interactions, we just hope to be able to perform some simple interactions on the client side based on server-side rendering, such as: clicking the legend to toggle whether the series is displayed. In this case, can we avoid loading at least a few hundred KBs of ECharts code on the client side?
209+
210+
Starting from version v5.5.0, if the chart only needs the following effects and interactions, it can be achieved through server-side SVG rendering + client-side lightweight runtime:
211+
212+
- Initial chart animation (implementation principle: the SVG rendered by the server comes with CSS animation)
213+
- Highlight style (implementation principle: the SVG rendered by the server comes with CSS animation)
214+
- Dynamically changing data (implementation principle: the lightweight runtime requests the server for secondary rendering)
215+
- Click the legend to toggle whether the series is displayed (implementation principle: the lightweight runtime requests the server for secondary rendering)
216+
217+
```html
218+
<div id="chart-container" style="width:800px;height:600px"></div>
219+
220+
<script src="https://cdn.jsdelivr.net/npm/echarts/ssr/client/dist/index.js"></script>
221+
<script>
222+
const ssrClient = window['echarts-ssr-client'];
223+
224+
let isSeriesShown = {
225+
a: true,
226+
b: true
227+
};
228+
229+
function updateChart(svgStr) {
230+
const container = document.getElementById('chart-container');
231+
container.innerHTML = svgStr;
232+
233+
// Use the lightweight runtime to give the chart interactive capabilities
234+
ssrClient.hydrate(main, {
235+
on: {
236+
click: (params) => {
237+
if (params.ssrType === 'legend') {
238+
// Click the legend element, request the server for secondary rendering
239+
isSeriesShown[params.seriesName] = !isSeriesShown[params.seriesName];
240+
$.get('...?series=' + JSON.stringify(isSeriesShown)).then(svgStr => {
241+
updateChart(svgStr);
242+
});
243+
}
244+
}
245+
}
246+
});
247+
}
248+
249+
// Get the SVG string rendered by the server through an AJAX request
250+
$.get('...').then(svgStr => {
251+
updateChart(svgStr);
252+
});
253+
</script>
254+
```
255+
256+
The server side performs secondary rendering based on the information passed by the client about whether each series is displayed (`isSeriesShown`) and returns a new SVG string. The server-side code [is the same as above](#server-side-svg-rendering), and will not be repeated.
257+
258+
> About state recording: Compared with pure client-side rendering, developers need to record and maintain some additional information (such as whether each series is displayed in this example). This is inevitable because HTTP requests are stateless. If you want to implement a state, either the client records the state and passes it like the above example, or the server retains the state (for example, through a session, but it requires more server memory and more complex destruction logic, so it is not recommended).
259+
260+
Using server-side SVG rendering plus client-side lightweight runtime, the advantage is that the client no longer needs to load hundreds of KBs of ECharts code, only needs to load a less than 4KB lightweight runtime code; and from the user experience, very little is sacrificed (supports initial animation, mouse highlighting). The disadvantage is that it requires a certain development cost to maintain additional state information, and it does not support interactions with high real-time requirements (such as displaying tooltips when moving the mouse). Overall, **it is recommended to use it in environments with very strict requirements for code volume**.
261+
262+
## Decide the Rendering Solution According to the Scenario
263+
264+
Above, we introduced several different rendering solutions, including:
265+
266+
- Client-side rendering
267+
- Server-side SVG rendering
268+
- Server-side Canvas rendering
269+
- Client-side lightweight runtime rendering
270+
271+
These four rendering methods can be used in combination. Let's summarize their respective applicable scenarios:
272+
273+
| Rendering Solution | Loading Volume | Loss of Function and Interaction | Relative Development Workload | Recommended Scenario |
274+
| --- | --- | --- | --- | --- |
275+
| Client-side rendering | ~1000KB | None | Minimum | The first screen load time is not sensitive, and there is a high demand for complete functionality and interaction |
276+
| Client-side rendering ([partial package importing](basics/import#shrinking-bundle-size) on demand) | >400KB | Large: the packages not included cannot use the corresponding functions | Small | The first screen load time is not sensitive, there is no strict requirement for code volume but hope to be as small as possible, only use a small part of ECharts functions, no server resources |
277+
| One-time server-side SVG rendering | ~20KB | Large: unable to dynamically change data, does not support legend toggle series display, does not support tooltips and other interactions with high real-time requirements | Medium | The first screen load time is sensitive, low demand for complete functionality and interaction |
278+
| One-time server-side Canvas rendering | ~200KB | Largest: the same as above and does not support initial animation, larger image volume, blurry when enlarged | Medium | The first screen load time is sensitive, low demand for complete functionality and interaction, platform restrictions cannot use SVG |
279+
| Server-side SVG rendering plus client-side ECharts lazy loading | ~20KB + 1000KB | Medium: cannot interact before lazy loading is completed | Medium | The first screen load time is sensitive, high demand for complete functionality and interaction, the chart is best not needed for interaction immediately after loading |
280+
| Server-side SVG rendering plus client-side lightweight runtime | ~20KB + 4KB, an additional ~20KB per update request | Medium: Cannot implement interactions with high real-time requirements | Large (need to maintain chart status, define client-server interface protocol) | The first screen load time is sensitive, low demand for complete functionality and interaction, very strict requirements for code volume, not strict requirements for interaction real-time |
281+
| Server-side SVG rendering plus client-side ECharts lazy loading, using lightweight runtime before lazy loading is completed | ~20KB + 4KB + 1000KB | Small: Cannot perform complex interactions before lazy loading is completed | Largest | The first screen load time is sensitive, high demand for complete functionality and interaction, sufficient development time |
282+
283+
Of course, there are some other combination possibilities, but the most common ones are the above. I believe that if you understand the characteristics of these rendering solutions, you can choose the appropriate solution based on your own scenario.

contents/en/how-to/interaction/drag.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ myChart.setOption({
8787
});
8888
```
8989

90-
In the code above, API [convertToPixel](api.html#echartsInstance.convertToPixel) is used to convert data to its "pixel coodinate", based on which each graphic elements can be rendered on canvas. The term "pixel coodinate" means the coordinate is in canvas pixel, whose origin is the top-left of the canvas. In the sentence `myChart.convertToPixel('grid', dataItem)`, the first parameter `'grid'` indicates that `dataItem` should be converted in the first [grid component (cartesian)](${optionPath}grid).
90+
In the code above, API [convertToPixel](${mainSitePath}api.html#echartsInstance.convertToPixel) is used to convert data to its "pixel coodinate", based on which each graphic elements can be rendered on canvas. The term "pixel coodinate" means the coordinate is in canvas pixel, whose origin is the top-left of the canvas. In the sentence `myChart.convertToPixel('grid', dataItem)`, the first parameter `'grid'` indicates that `dataItem` should be converted in the first [grid component (cartesian)](${optionPath}grid).
9191

9292
**Notice:** `convertToPixel` should not be called before the first time that `setOption` called. Namely, it can only be used after coordinate systems (grid/polar/...) initialized.
9393

contents/zh/basics/import.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ myChart.setOption({
8383
8484
我们在示例编辑页的“完整代码”标签提供了非常方便的生成按需引入代码的功能。这个功能会根据当前的配置项动态生成最小的按需引入的代码。你可以直接在你的项目中使用。
8585

86+
> v5.5.0 版本开始使用 ESM 作为默认的模块规范,查看可能的 [Breaking Changes](https://github.com/apache/echarts/pull/19513#issuecomment-1916237700) 以及 [Pull Request](https://github.com/apache/echarts/pull/19513)
87+
8688
## 在 TypeScript 中按需引入
8789

8890
对于使用了 TypeScript 来开发 ECharts 的开发者,我们提供了类型接口来组合出最小的 `EChartsOption` 类型。这个更严格的类型可以有效帮助你检查出是否少加载了组件或者图表。
@@ -106,7 +108,7 @@ import { LabelLayout, UniversalTransition } from 'echarts/features';
106108
import { CanvasRenderer } from 'echarts/renderers';
107109
import type {
108110
// 系列类型的定义后缀都为 SeriesOption
109-
BarSeriesOption,
111+
BarSeriesOption,
110112
LineSeriesOption
111113
} from 'echarts/charts';
112114
import type {
@@ -116,8 +118,8 @@ import type {
116118
GridComponentOption,
117119
DatasetComponentOption
118120
} from 'echarts/components';
119-
import type {
120-
ComposeOption,
121+
import type {
122+
ComposeOption,
121123
} from 'echarts/core';
122124

123125
// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Apache ECharts 5.5.0 特性介绍
2+
3+
## 增强的 ESM 支持
4+
5+
为了让开发者在测试和 Node.js 环境使用更方便,我们在这个版本中对 ESM 的识别问题进行了优化。
6+
7+
以前,ECharts 只在 npm(npm 包的 lib 目录中)导出 `*.esm` 文件。虽然这在 bundlers 环境表现良好,但 Node.js 环境和一些基于 Node.js 的测试框架(如 vitest 和 jest)中的表现并不理想。
8+
9+
有了这个新功能,我们做了几个改变以改善这个问题:
10+
11+
-`package.json` 中添加了 `"type": "module"`
12+
-`package.json` 中添加了 `"exports": {...}`
13+
- 在子目录中添加了一些只包含 `"type": "commonjs"``package.json` 文件
14+
15+
这些改变意味着,像 echarts/core.js 这样的文件现在可以在像纯 Node.js、vitest、jest 和create-react-app 这样的环境中解析为 ESM。
16+
17+
请注意,如果使用 "exports",那么在 "exports" 中未声明的文件将无法从外部访问。此外,路径必须以 ’.' 开头。
18+
19+
我们还确保了这个新功能与各种环境兼容,包括运行时(Node.js/vitest/jest(create-react-app)/ssr/…)和打包器(webpack / rollup / vite / esbuild / …)。
20+
21+
我们相信它将显著提高开发人员的体验,因此很高兴地为大家介绍这个新功能。

0 commit comments

Comments
 (0)