Step-by-Step Guide to building a custom custom charts dashboard block for Gutenberg using SolidJS high-performance reactive components
Leveraging SolidJS for High-Performance Gutenberg Charting Blocks
Enterprise-grade dashboards demand not only robust data aggregation but also a performant and responsive user interface. Traditional JavaScript charting libraries, when integrated into WordPress’s Gutenberg editor, can introduce significant performance bottlenecks, impacting both editor experience and frontend rendering. This guide details the construction of a custom Gutenberg block for displaying charts, utilizing SolidJS for its exceptional reactivity and minimal overhead, thereby ensuring a fluid and efficient user experience.
Project Setup and Dependencies
We’ll begin by setting up a standard WordPress plugin structure and installing the necessary development tools. This involves Node.js, npm/yarn, and the WordPress `@wordpress/scripts` package for managing build processes.
First, create a new plugin directory within your WordPress installation’s wp-content/plugins/ folder. For this example, we’ll name it custom-charts-block.
Navigate into this new directory and initialize a Node.js project:
cd wp-content/plugins/custom-charts-block npm init -y
Next, install the essential WordPress scripts package and SolidJS:
npm install @wordpress/scripts solid-js --save-dev
In your package.json, add the following scripts to manage the build process:
{
"name": "custom-charts-block",
"version": "1.0.0",
"description": "A custom Gutenberg block for displaying charts using SolidJS.",
"main": "build/index.js",
"scripts": {
"build": "wp-scripts build",
"start": "wp-scripts start"
},
"keywords": ["wordpress", "gutenberg", "block", "solidjs", "charts"],
"author": "Antigravity",
"license": "GPL-2.0-or-later",
"dependencies": {
"solid-js": "^1.8.15"
},
"devDependencies": {
"@wordpress/scripts": "^27.6.0"
}
}
Create a src directory at the root of your plugin. Inside src, create an index.js file. This will be the entry point for your Gutenberg block registration.
Gutenberg Block Registration and Editor Component
We’ll use the @wordpress/blocks package to register our custom block. The editor component will be a React component (as Gutenberg’s editor is React-based) that internally renders our SolidJS chart component.
In src/index.js, register the block:
// src/index.js
import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import Edit from './edit';
import save from './save';
registerBlockType('custom-charts/block', {
title: __('Custom Charts Block', 'custom-charts-block'),
icon: 'chart-bar', // WordPress dashicon
category: 'widgets',
attributes: {
chartType: {
type: 'string',
default: 'bar',
},
chartData: {
type: 'string', // Storing as JSON string for simplicity
default: '{"labels": ["January", "February", "March"], "datasets": [{"label": "Sales", "data": [10, 20, 15]}]}',
},
chartOptions: {
type: 'string',
default: '{}',
},
},
edit: Edit,
save: save,
});
Now, create src/edit.js for the block’s editor interface. This component will manage the block’s attributes and render the SolidJS chart preview.
// src/edit.js
import { useBlockProps } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
import { createSignal, For, Show } from 'solid-js';
import { render } from 'solid-js/web';
import ChartComponent from './ChartComponent'; // Our SolidJS chart component
const Edit = ({ attributes, setAttributes }) => {
const blockProps = useBlockProps();
const { chartType, chartData, chartOptions } = attributes;
const [data, setData] = createSignal(JSON.parse(chartData));
const [options, setOptions] = createSignal(JSON.parse(chartOptions));
// In a real-world scenario, you'd have controls here to edit chartType, data, and options.
// For this example, we'll assume they are set and focus on rendering the SolidJS component.
return (
Chart Preview
{/* Add controls for chart type, data input, options input here */}
);
};
export default Edit;
The src/save.js file defines how the block’s content is saved to the database. It should output HTML that can be rendered on the frontend.
// src/save.js
import { useBlockProps } from '@wordpress/block-editor';
const save = ({ attributes }) => {
const blockProps = useBlockProps.save();
const { chartType, chartData, chartOptions } = attributes;
// We'll render the chart on the frontend using a separate script that initializes SolidJS.
// For now, we save the necessary data as data attributes.
return (
{/* Placeholder for the chart */}
);
};
export default save;
Implementing the SolidJS Chart Component
This is where the core of our high-performance charting logic resides. We’ll create a reusable SolidJS component that takes chart configuration as props and renders the chart. For this example, we’ll use a simple placeholder; in a production environment, you’d integrate a lightweight charting library compatible with SolidJS or a custom SVG rendering solution.
Create src/ChartComponent.jsx:
// src/ChartComponent.jsx
import { createEffect, onMount } from 'solid-js';
const ChartComponent = (props) => {
let chartContainer;
// In a real application, you would initialize a charting library here.
// For demonstration, we'll simulate chart rendering.
const renderChart = () => {
if (!chartContainer) return;
// Clear previous content
chartContainer.innerHTML = '';
// Simulate chart rendering based on props
const canvas = document.createElement('canvas');
canvas.width = chartContainer.clientWidth;
canvas.height = chartContainer.clientHeight;
const ctx = canvas.getContext('2d');
if (!ctx) return;
ctx.fillStyle = '#f0f0f0';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#333';
ctx.font = '16px Arial';
ctx.textAlign = 'center';
ctx.fillText(`Chart Type: ${props.type}`, canvas.width / 2, canvas.height / 2 - 20);
ctx.fillText(`Data: ${JSON.stringify(props.data.labels)}`, canvas.width / 2, canvas.height / 2 + 20);
chartContainer.appendChild(canvas);
console.log('Chart rendered with:', props.type, props.data, props.options);
};
// Use createEffect to re-render when props change
createEffect(() => {
renderChart();
});
// Use onMount to ensure the DOM element is available
onMount(() => {
renderChart();
});
return (
Loading chart...
);
};
export default ChartComponent;
Note the use of createEffect and onMount from SolidJS. createEffect is crucial for reactivity, ensuring the chart updates whenever its props (type, data, options) change. onMount guarantees that the DOM element is ready before attempting to render.
Frontend Chart Initialization
On the frontend, we need a script to find our saved blocks and initialize the SolidJS chart. This script will parse the data attributes we saved and render the chart using our ChartComponent.
Create src/frontend.js:
// src/frontend.js
import { createRoot } from 'solid-js';
import { render } from 'solid-js/web';
import ChartComponent from './ChartComponent';
document.addEventListener('DOMContentLoaded', () => {
const chartBlocks = document.querySelectorAll('.custom-chart-frontend');
chartBlocks.forEach(blockElement => {
const chartType = blockElement.dataset.chartType;
const chartData = JSON.parse(blockElement.dataset.chartData);
const chartOptions = JSON.parse(blockElement.dataset.chartOptions);
// Create a mount point within the block element
const mountPoint = document.createElement('div');
mountPoint.style.width = '100%';
mountPoint.style.height = '100%';
blockElement.appendChild(mountPoint);
// Render the SolidJS component into the mount point
const dispose = render(() =>
createRoot(() => )
, mountPoint);
// Optional: Store dispose function if you need to unmount later
blockElement.dataset.solidDispose = dispose;
});
});
This script uses solid-js/web‘s render function to mount the SolidJS component into the DOM. It finds all elements with the class custom-chart-frontend, extracts the chart data from data-* attributes, and renders the ChartComponent.
Build Process and Plugin Activation
Now, compile your JavaScript assets. Run the build command from your plugin’s root directory:
npm run build
This command will process your src/index.js and src/frontend.js files, transpiling JSX and modern JavaScript into a format compatible with browsers, and outputting the results to the build/ directory. It will also bundle the SolidJS dependencies.
You’ll need to enqueue your compiled JavaScript files. Create a custom-charts-block.php file at the root of your plugin directory:
<?php
/**
* Plugin Name: Custom Charts Block
* Description: A custom Gutenberg block for displaying charts using SolidJS.
* Version: 1.0.0
* Author: Antigravity
* License: GPL-2.0-or-later
* Text Domain: custom-charts-block
*/
function custom_charts_block_register_assets() {
// Enqueue editor assets
wp_register_script(
'custom-charts-block-editor-script',
plugins_url( 'build/index.js', __FILE__ ),
array( 'wp-blocks', 'wp-element', 'wp-editor', 'wp-i18n' ),
filemtime( plugin_dir_path( __FILE__ ) . 'build/index.js' )
);
// Enqueue frontend assets
wp_register_script(
'custom-charts-block-frontend-script',
plugins_url( 'build/frontend.js', __FILE__ ),
array(), // No dependencies needed for frontend script initialization
filemtime( plugin_dir_path( __FILE__ ) . 'build/frontend.js' )
);
}
add_action( 'init', 'custom_charts_block_register_assets' );
function custom_charts_block_render_frontend() {
// Enqueue frontend script only when the block is present on the page.
// A more robust solution would involve checking for the block's presence.
wp_enqueue_script( 'custom-charts-block-frontend-script' );
}
add_action( 'wp_enqueue_scripts', 'custom_charts_block_render_frontend' );
function custom_charts_block_register_block() {
// Ensure the block is registered via JavaScript in src/index.js
// This PHP file primarily handles asset enqueuing.
}
add_action( 'init', 'custom_charts_block_register_block' );
?>
Activate the “Custom Charts Block” plugin in your WordPress admin area. You should now be able to add the “Custom Charts Block” to your posts or pages. The preview in the editor will render using SolidJS, and the frontend will also initialize the charts dynamically.
Performance Considerations and Advanced Integration
SolidJS’s performance stems from its fine-grained reactivity and compilation strategy, which generates highly optimized vanilla JavaScript. Unlike virtual DOM-based libraries, SolidJS compiles JSX into direct DOM manipulations, minimizing runtime overhead.
For production, consider these optimizations:
- Code Splitting: Use Webpack’s code splitting features (integrated with
@wordpress/scripts) to load chart components only when needed, especially if you have multiple chart types. - Lazy Loading: Implement lazy loading for the SolidJS chart component within the editor and on the frontend to improve initial page load times.
- Data Fetching: For dynamic data, implement efficient data fetching strategies. In the editor, you might use
@wordpress/data. On the frontend, consider REST API endpoints or GraphQL. - Charting Library Choice: Select a charting library that has minimal dependencies and good performance characteristics. Libraries like Chart.js (with a SolidJS wrapper) or custom SVG solutions can be effective. For extreme performance, consider WebGL-based solutions if your data volume warrants it.
- Server-Side Rendering (SSR): While SolidJS excels client-side, for SEO and initial perceived performance, explore options for server-rendering the initial chart state. This typically involves rendering the SolidJS component on the server and passing the initial state to the client.
By integrating SolidJS, you’re not just building a Gutenberg block; you’re architecting a performant, reactive charting solution that enhances both the content creation workflow and the end-user experience on the frontend. This approach is particularly valuable for enterprise applications where dashboard responsiveness and scalability are paramount.