From 60a41df2db39cc057436271679381a533e473f69 Mon Sep 17 00:00:00 2001 From: Rami Yushuvaev <92088692+rami-elementor@users.noreply.github.com> Date: Fri, 21 Jun 2024 06:02:45 -0700 Subject: [PATCH] Add "Widget Output Caching" (#278) --- src/.vuepress/sidebars/widgets.js | 1 + src/widgets/index.md | 1 + src/widgets/widget-output-caching.md | 186 +++++++++++++++++++++++++++ src/widgets/widget-rendering.md | 1 + src/widgets/widget-structure.md | 2 + 5 files changed, 191 insertions(+) create mode 100644 src/widgets/widget-output-caching.md diff --git a/src/.vuepress/sidebars/widgets.js b/src/.vuepress/sidebars/widgets.js index 4c026f95..10d62330 100644 --- a/src/.vuepress/sidebars/widgets.js +++ b/src/.vuepress/sidebars/widgets.js @@ -46,6 +46,7 @@ module.exports = [ 'rendering-repeaters', 'rendering-html-attribute', 'rendering-inline-editing', + 'widget-output-caching', ] }, ] diff --git a/src/widgets/index.md b/src/widgets/index.md index aa9220de..e9ea4067 100644 --- a/src/widgets/index.md +++ b/src/widgets/index.md @@ -32,6 +32,7 @@ Learn more about widget anatomy and how to create your own: * [Rendering Repeater](./rendering-repeaters/) * [Rendering HTML Attribute](./rendering-html-attribute/) * [Rendering Inline Editing](./rendering-inline-editing/) + * [Widget Output Caching](./widget-output-caching/) ## Code Examples diff --git a/src/widgets/widget-output-caching.md b/src/widgets/widget-output-caching.md new file mode 100644 index 00000000..93776b4a --- /dev/null +++ b/src/widgets/widget-output-caching.md @@ -0,0 +1,186 @@ +## Widget Output Caching + + + +Elementor offers a feature to minimize the impact of widgets on page performance. For widgets that generate static output, Elementor can cache the HTML, avoiding the need to render it each time the page loads. + +By default, Elementor does not cache widget outputs and renders all widgets on the page with every page load. However, developers can enable HTML output caching for widgets to enhance loading speeds. + +## Widgets Rendering Mechanism + +During page load, Elementor renders all widgets to generate the required markup. The more widgets the page has, the slower the rendering process. + +To optimize this, Elementor's widget caching mechanism can be employed. This mechanism renders a widget once, caches the output, and uses the cached version for subsequent page loads. This reduces server memory usage by 99% and improves Time To First Byte (TTFB) on the frontend. + +### Content Types + +Widgets can return two types of output: + +* **Static Content** - return the same content each time, for every user. +* **Dynamic Content** - return content that may change based on different parameters. + +A static content example is a heading widget that consistently returns the text from a control. Since the output is identical for all users, it can be cached. + +In contrast, dynamic content involves logic that alters the output based on different conditions. For example, a widget that includes a PHP function to display the user's name will show different results for different users, thus the widget should not cache the output. + +An extreme case of dynamic content is a widget that displays a random number on each page load. Such a widget should not cache its output. + +The widget caching mechanism in Elementor is sophisticated and includes several exceptions to avoid inappropriate caching. For instance, if one of the widget controls uses a dynamic tag or has a display condition, Elementor will bypass the cache, fully rendering the widget. + +### Caching Output + +To enhance widget performance by caching static content, apply the following method to the widget class: + +```php +class Elementor_Test_Widget extends \Elementor\Widget_Base { + + protected function is_dynamic_content() { + return false; + } + +} +``` + +Using the code above, the widget instructs Elementor to cache its output if it generates static content. + +By default, all widgets are treated as dynamic and are not cached. If you are not sure, avoid using this method. + +### Exceptions + +The widget caching mechanism in Elementor is sophisticated and includes several exceptions to avoid inappropriate caching. For instance, if one of the widget controls uses a dynamic tag or has a display condition, Elementor will bypass the cache, fully rendering the widget. + +## Examples + +### A Widget With a Static Output + +Let's say you have a widget with a single control in which the users can set a "title". The render function will always render the same HTML for all the users, therefore the output can be cached: + +```php {4-6,38-40,51-53} +start_controls_section( + 'section_content', + [ + 'label' => esc_html__( 'Content', 'textdomain' ), + 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'title', + [ + 'label' => esc_html__( 'Title', 'textdomain' ), + 'type' => \Elementor\Controls_Manager::TEXT, + 'placeholder' => esc_html__( 'Enter your title', 'textdomain' ), + ] + ); + + $this->end_controls_section(); + + } + + protected function render() { + $settings = $this->get_settings_for_display(); + + if ( empty( $settings['title'] ) ) { + return; + } + ?> +

+ +

+ + <# + if ( '' === settings.title ) { + return; + } + #> +

+ {{{ settings.title }}} +

+ start_controls_section( + 'section_content', + [ + 'label' => esc_html__( 'Content', 'textdomain' ), + 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'title', + [ + 'label' => esc_html__( 'Title', 'textdomain' ), + 'type' => \Elementor\Controls_Manager::TEXT, + 'placeholder' => esc_html__( 'Enter your title', 'textdomain' ), + ] + ); + + $this->end_controls_section(); + + } + + protected function render() { + $settings = $this->get_settings_for_display(); + + if ( empty( $settings['title'] ) ) { + return; + } + + if ( is_user_logged_in() ) { + $greeting = esc_html__( 'Hi logged in user!', 'textdomain' ) . ' '; + } + ?> +

+ +

+ + <# + if ( '' === settings.title ) { + return; + } + + if ( document.body.classList.contains( 'logged-in' ) ) { + greeting = 'Hi logged in user! '; + } + #> +

+ {{{ greeting + settings.title }}} +

+