|
1 | 1 | import { TableOfContent } from '@sb/components'; |
2 | 2 | import { Meta, Canvas } from '@storybook/addon-docs/blocks'; |
3 | 3 | import { Footer } from '@sb/components'; |
4 | | -import { MessageStrip } from '../../webComponents/MessageStrip/index'; |
| 4 | +import { MessageStrip } from '../../../webComponents/MessageStrip/index.js'; |
5 | 5 | import * as ComponentStories from './AnalyticalTable.stories'; |
6 | 6 |
|
7 | | -<Meta title="Data Display / AnalyticalTable / Recipes" /> |
| 7 | +<Meta title="Data Display / AnalyticalTable / FAQ" /> |
8 | 8 |
|
9 | | -# AnalyticalTable Recipes |
| 9 | +# AnalyticalTable FAQ |
10 | 10 |
|
11 | 11 | <TableOfContent /> |
12 | 12 |
|
| 13 | +## Why is the AnalyticalTable slow in development mode? |
| 14 | + |
| 15 | +When using the `AnalyticalTable` (or other virtualized components) in development mode, you may experience noticeable performance degradation compared to production builds. This is expected behavior caused by the combination of **React's dev mode overhead** and **browser debugger instrumentation**. |
| 16 | + |
| 17 | +### Why Dev Mode is Slower |
| 18 | + |
| 19 | +#### React Dev Mode Overhead |
| 20 | + |
| 21 | +React's development build includes significant overhead: |
| 22 | + |
| 23 | +- **Strict Mode double-rendering**: Components, `useEffect`, and callback refs render an additional time to help detect side effects |
| 24 | +- **Validation checks**: Hooks order, prop types, deprecated API usage |
| 25 | +- **Extended error messages**: Component stack traces for better debugging |
| 26 | +- **Extra code paths**: Development-only warnings and diagnostics |
| 27 | + |
| 28 | +For a virtualized table that frequently mounts and unmounts cells during scrolling, this overhead compounds quickly. |
| 29 | + |
| 30 | +#### Browser Debugger Instrumentation |
| 31 | + |
| 32 | +Chromium-based browsers (Chrome, Edge, Brave, etc.) instrument async operations heavily in dev mode via the V8 engine - even when DevTools is closed. Firefox and Safari have significantly lighter debugger overhead in dev mode for example. |
| 33 | + |
| 34 | +### Recommendations |
| 35 | + |
| 36 | +#### High Impact |
| 37 | + |
| 38 | +1. **Use Firefox or Safari for development**: These browsers have significantly lighter debugger overhead in dev mode. |
| 39 | + |
| 40 | +2. **Test with production builds**: When working on performance-sensitive features, test with a production build to get accurate performance metrics. |
| 41 | + |
| 42 | +3. **Disable React Strict Mode** (temporarily): If dev mode performance is severely impacting your workflow, you can temporarily disable Strict Mode in development. Note that Strict Mode helps catch bugs, so re-enable it periodically. |
| 43 | + |
| 44 | +4. **Memoize props that require it**: Props marked with "Must be memoized" (e.g., `columns`) need a stable reference. Define them outside the component or use `useMemo`/`useCallback` to prevent unnecessary recalculations. |
| 45 | + |
| 46 | +#### Medium Impact |
| 47 | + |
| 48 | +5. **Disable React DevTools extension**: The React DevTools browser extension adds performance overhead and has been observed to cause small memory leaks. |
| 49 | + |
| 50 | +6. **Consider memoizing expensive Cell components**: If you have custom `Cell` renderers with expensive computations or deep component trees, wrapping them with `React.memo()` can help by creating render boundaries. However, avoid over-memoization - for simple cells, the overhead of memoization may outweigh the benefits. |
| 51 | + |
| 52 | +7. **Use [direct imports](?path=/docs/knowledge-base-faq--docs#why-use-direct-imports-via-package-export-maps)**: Since tree shaking is not available for most bundlers in dev mode, use direct imports to reduce initial load. |
| 53 | + |
| 54 | +#### Lower Impact |
| 55 | + |
| 56 | +8. **Keep DevTools closed**: When not actively debugging, keep DevTools closed to reduce overhead from source map parsing, DOM mutation observers, and memory tracking. |
| 57 | + |
| 58 | +9. **Deactivate UI5 Web Components animations in dev mode**: Animations cause components to recalculate multiple times. While we debounce frequent state changes, disabling animations can help. |
| 59 | + |
| 60 | +### Summary |
| 61 | + |
| 62 | +Dev mode slowness for virtualized components is expected behavior, not a bug. In production builds, the `AnalyticalTable` performs well. For the best development experience with heavy tables, consider using Firefox or Safari, or testing with production builds when performance is critical. |
| 63 | + |
| 64 | +<details> |
| 65 | +<summary>Example: Performance Trace Comparison</summary> |
| 66 | + |
| 67 | +The following table shows a performance trace comparison from an investigation into dev mode performance ([GitHub issue #8234](https://github.com/SAP/ui5-webcomponents-react/issues/8234)). Your results may vary depending on your implementation, but the general pattern holds: |
| 68 | + |
| 69 | +| Metric | Chrome DEV | Chrome PROD | Firefox DEV | |
| 70 | +| --------------- | ---------- | ----------- | ----------- | |
| 71 | +| Trace file size | 561 MB | 3.3 MB | 6.3 MB | |
| 72 | +| Event count | ~millions | ~14,600 | ~3,700 | |
| 73 | + |
| 74 | +Firefox in dev mode has similar overhead to Chrome in prod mode - both are lightweight. Chromium-based browsers in dev mode are the outlier with massive V8 debugger instrumentation. |
| 75 | + |
| 76 | +For more context, see the [detailed findings comment](https://github.com/SAP/ui5-webcomponents-react/issues/8234#issuecomment-3971742068) and [production environment performance videos](https://github.com/SAP/ui5-webcomponents-react/issues/8234#issuecomment-3960465202) showing table performance (inside a complex container) on high-end, medium-range, and low-end devices. |
| 77 | + |
| 78 | +</details> |
| 79 | + |
13 | 80 | ## How to add your own plugin hooks? |
14 | 81 |
|
15 | 82 | The `AnalyticalTable` internally uses all plugin hooks of the [react-table v7](https://github.com/TanStack/table/blob/v7/docs/src/pages/docs/api/overview.md) except for `usePagination` and hooks that change the layout. |
16 | 83 | If you pass a `react-table` hook to the `tableHooks` prop of the `AnalyticalTable` you will most likely experience some side effects or even break the table completely. We therefore strongly recommend to just not do it ;). |
17 | 84 | If you encounter a functionality that should be available with `react-table` hooks, but isn't in the `AnalyticalTable` please open an issue in GitHub. |
18 | 85 |
|
19 | 86 | <MessageStrip |
20 | | - type="Warning" |
21 | | - hideCloseButton |
22 | | - children={`Plugin hooks can manipulate the internal table instance. Please use with caution!`} |
| 87 | + type="Warning" |
| 88 | + hideCloseButton |
| 89 | + children={`Plugin hooks can manipulate the internal table instance. Please use with caution!`} |
23 | 90 | /> |
24 | 91 |
|
25 | 92 | For adding custom plugin hooks you can use the following code snippet. |
@@ -438,8 +505,8 @@ For multi-line content or custom components that don't handle ellipsis, truncati |
438 | 505 | ### Example |
439 | 506 |
|
440 | 507 | <details> |
441 | | - <summary>Show Example</summary> |
442 | | - <Canvas of={ComponentStories.EllipsisExamples} /> |
| 508 | + <summary>Show Example</summary> |
| 509 | + <Canvas of={ComponentStories.EllipsisExamples} /> |
443 | 510 | </details> |
444 | 511 |
|
445 | 512 | <br /> |
|
0 commit comments