WPDev.one
Gutenberg React & PHP Advanced Last Updated: Jan 3, 2025

Building Dynamic Blocks: The Complete Guide to Server-Side Rendering

Learn how to bridge the gap between React state and PHP rendering. We cover render_callback, attribute handling, hydration strategies, and when to choose dynamic over static blocks.

WordPress Team
Senior WordPress Engineers
Advertisement (728x90)

When building custom blocks for the Gutenberg editor, you generally have two options: static rendering (via the save method) or dynamic rendering (via PHP). While static blocks are great for performance, dynamic blocks are essential when content needs to change without manually updating every post.

Why Choose Server-Side Rendering?

Dynamic blocks render on the server using PHP. This means:

  • Content updates automatically across all posts when you change the HTML structure or logic.
  • Access to WordPress functions like WP_Query, get_posts, get_the_terms, and any custom functions.
  • Complex logic stays in PHP where it's often easier to maintain for backend developers.
  • Database queries can be performed at render time, ensuring fresh data.
  • Template flexibility - you can use theme templates or custom PHP logic.

Performance Consideration

Dynamic blocks can have a slight performance impact on the frontend since they require PHP processing on every page load. Use caching (like WP Rocket or object caching) to mitigate this. For high-traffic sites, consider combining dynamic rendering with static caching strategies.

When to Use Dynamic Blocks

Use dynamic blocks when:

  • Content needs to be generated from database queries (recent posts, related content, etc.)
  • You need to access WordPress functions that aren't available in JavaScript
  • The block output needs to change based on user permissions or context
  • You're building blocks that display data from custom post types or taxonomies
  • The HTML structure might change and you want to update all instances automatically

Use static blocks when:

  • Content is user-entered and doesn't need server-side processing
  • Performance is critical and you want to minimize PHP processing
  • The block output is simple and unlikely to change

Step 1: Registering the Block

First, we define our block metadata in block.json. The key difference here is we don't need a save function in our JavaScript, and we specify a render callback.

block.json

Key points about this configuration:

  • "render": "file:./render.php" - This tells WordPress to use the PHP file for rendering instead of JavaScript's save function.
  • "html": false - Prevents users from editing the HTML directly, which is important for dynamic blocks.
  • No save function needed - The block is always rendered server-side.

Step 2: The PHP Rendering Logic

Instead of writing HTML in JavaScript, we create a render.php file. This file has access to the $attributes, $content, and $block variables automatically.

render.php

This setup is cleaner than the old render_callback method because it separates the view logic from the registration logic. Notice how we:

  • Use setup_postdata() to make WordPress template functions work correctly
  • Escape all output using esc_html(), esc_url(), and wp_kses_post()
  • Reset post data with wp_reset_postdata() to avoid side effects
  • Check for post existence before rendering

Step 3: Registering the Block in PHP

Now we need to register the block in PHP. This is typically done in your theme's functions.php or a plugin file.

functions.php

WordPress will automatically:

  • Read the block.json file
  • Enqueue the editor JavaScript (if you have an editor.js file)
  • Use the render.php file for frontend rendering
  • Handle all the block registration automatically

Step 4: Creating the Editor Interface

Even though the block renders server-side, you still need JavaScript for the editor experience. This allows users to select posts, toggle options, and see a preview.

editor.js

Advanced Patterns

Using WP_Query in Dynamic Blocks

One of the biggest advantages of dynamic blocks is the ability to use WP_Query for complex queries.

render.php (Advanced)

Caching Strategies

Since dynamic blocks execute PHP on every page load, caching is crucial for performance. Here are some strategies:

render.php (with caching)

Best Practices

  • Always escape output - Use esc_html(), esc_url(), esc_attr(), and wp_kses_post()
  • Reset post data - Always call wp_reset_postdata() after custom queries
  • Check for existence - Verify posts, terms, and other data exist before rendering
  • Use caching - Implement object caching for expensive queries
  • Provide fallbacks - Show helpful messages when data isn't available
  • Sanitize attributes - Validate and sanitize all user input in attributes
  • Use proper HTML structure - Follow semantic HTML and accessibility guidelines

Common Pitfalls

  • Forgetting to reset post data - This can break other blocks or theme functions
  • Not escaping output - Security risk and can break HTML structure
  • Heavy queries without caching - Can slow down page loads significantly
  • Not handling empty states - Blocks should gracefully handle missing data
  • Mixing static and dynamic rendering - Don't try to use both save() and render.php

Conclusion

Dynamic blocks are a powerful way to create flexible, data-driven blocks in Gutenberg. By leveraging PHP's full capabilities, you can build blocks that automatically update across your site and integrate seamlessly with WordPress's ecosystem.

Remember: use dynamic blocks when you need server-side processing, database queries, or content that should update automatically. For simple, user-entered content, static blocks are still the better choice for performance.

Advertisement (Responsive)