A WordPress plugin with Preact frontend integration using Vite.
This plugin provides the basic setup to integrate a Preact application into a WordPress site. It enables you to create modern and reactive interfaces using Preact technology within WordPress and use them through shortcodes.
- β‘ Preact + Vite: Fast builds and lightweight application
- π TypeScript: Static typing for enhanced code safety
- π¦ Build System: Automated generation of optimized files
- π― Shortcode Support: Easy integration with WordPress pages/posts
- π PHP β Frontend Communication: Seamless data passing from backend to frontend
- PHP >= 7.4
- WordPress 6.0+
- Node.js >= 18
- Composer
cd wp-content/plugins/
# Place the plugin files herecomposer installcd frontend
npm installTo work on the frontend with hot reload:
cd frontend
npm run devThis will start the Vite development server on the default port (5173).
IMPORTANT
When working in development mode, data passed from PHP (backend) to the frontend via wp_localize_script will not be available, as Vite serves the files directly. To test PHP β Frontend communication, you'll need to do a temporary production build or implement an alternative solution to inject the data during development.
The current solution creates fallbacks for all values passed from PHP (backend) to the frontend. In this example, the strings constant located in frontend/src/core/config.ts has fallbacks for demonstration purposes.
To compile the frontend for production:
cd frontend
npm run buildThis will generate optimized files in the assets/ folder:
assets/js/wp-preact-plugin.jsassets/css/wp-preact-plugin.css
To create a ZIP file ready for distribution:
composer buildor
php Build.phpThis will create the build/wp-preact-plugin.zip file containing only the necessary files to run the plugin on a WordPress site.
- Access the WordPress admin panel
- Go to Plugins β Installed Plugins
- Activate Wordpress Preact Plugin
In any page or post, add the shortcode:
[wp_preact_plugin]
This will render the Preact application at the desired location.
wp-preact-plugin/
βββ main.php # Main plugin file
βββ index.php # Security file
βββ Build.php # Build script
βββ build-config.json # Build configuration
βββ composer.json # PHP dependencies
β
βββ includes/ # PHP classes
β βββ shortcodes/
β βββ wp-preact-shortcode.php # Shortcode implementation
β
βββ frontend/ # Preact application
β βββ package.json # Node dependencies
β βββ vite.config.ts # Vite configuration
β βββ tsconfig.json # TypeScript configuration
β β
β βββ public/ # Static files
β β βββ vite.svg
β β
β βββ src/ # Source code
β βββ main.tsx # Entry point
β βββ app.tsx # Main component
β βββ app.css # Global styles
β β
β βββ core/
β β βββ config.ts # App configuration
β β
β βββ components/
β βββ SimpleCounter/ # Example component
β βββ index.tsx
β βββ styles.css
β
βββ assets/ # Compiled files (generated)
β βββ css/
β β βββ wp-preact-plugin.css
β βββ js/
β βββ wp-preact-plugin.js
β
βββ build/ # ZIP builds (generated)
β βββ wp-preact-plugin.zip
β
βββ vendor/ # PHP dependencies (generated)
Data is passed via wp_localize_script:
// ...
wp_localize_script(
'wp-preact-plugin-js',
'wp_preact_plugin_args', // global JS variable
array(
'root' => 'wp_preact_plugin_root',
'assets_url' => WPPreactPlugin::get_asset_url(''),
'strings' => array(
'example' => 'This is an example value from PHP',
'start_counter' => 123,
),
)
);
// ...Data is accessed via window.wp_preact_plugin_args:
// Remember to always update the Window interface when
// data or strings are added, removed, or changed
// in the backend. This ensures proper TypeScript typing.
declare global {
interface Window {
wp_preact_plugin_args: {
root: string;
assets_url: string;
strings: {
example: string;
start_counter: number;
}
}
}
}
const wpPreactPluginArgs = window.wp_preact_plugin_args || {};
const root = document.getElementById(wpPreactPluginArgs.root || "app") as HTMLElement;
// If you don't provide strings from PHP, use these defaults to avoid
// undefined errors in the app. This is useful for development using
// `npm run dev` command. To see the real strings from PHP, use
// `npm run build` and load the plugin in WordPress.
const strings = wpPreactPluginArgs.strings || {
example: "Default example string",
start_counter: 0,
}
export const appConfig = Object.freeze({
root,
baseAssetsUrl: wpPreactPluginArgs.assets_url,
strings: strings,
});import { appConfig } from './core/config';
// Access strings
<h1>{appConfig.strings.example}</h1>
<span>{appConfig.strings.start_counter}</span>
// Access assets URL (essential for static files
// like images, fonts, etc. located in /frontend/public)
<img src={`${appConfig.baseAssetsUrl}/image.jpg`} />The main.php file registers the plugin in WordPress and defines basic information.
The WPPreactPluginShortcode class in includes/shortcodes/wp-preact-shortcode.php:
- Registers scripts and styles
- Creates the
[wp_preact_plugin]shortcode - Renders the
<div id="wp_preact_plugin_root"> - Enqueues scripts only when the shortcode is used
Vite compiles the TypeScript/Preact code into single JavaScript and CSS files that are loaded in WordPress.
The main.tsx mounts the Preact application in the div created by the shortcode.
- Create a new folder in
frontend/src/components/:
mkdir frontend/src/components/MyComponent- Create the
index.tsxfile:
import { useState } from 'preact/hooks';
import './styles.css';
export function MyComponent() {
return (
<div>
<h2>My Component</h2>
</div>
);
}- Create
styles.css(optional):
/* Component styles */- Import in
app.tsx:
import { MyComponent } from './components/MyComponent';
export function App() {
return (
<div>
<MyComponent />
</div>
);
}To pass different data for each shortcode instance:
/**
* Shortcode callback function
* @param array $atts Shortcode attributes
* @return string HTML output of the shortcode
*/
public function shortcode_callback($atts)
{
// Enqueue registered scripts and styles only when shortcode is used
wp_enqueue_style('wp-preact-plugin-css');
wp_enqueue_script('wp-preact-plugin-js');
// Pass data and strings to frontend via wp_localize_script
wp_localize_script(
'wp-preact-plugin-js',
'wp_preact_plugin_args',
array(
'root' => 'wp_preact_plugin_root',
'assets_url' => WPPreactPlugin::get_asset_url(''),
'strings' => array(
'example' => 'This is an example value from PHP',
'start_counter' => 123,
'data_from_atts' => isset($atts['data']) ? $atts['data'] : 'default value',
'another_data_from_atts' => isset($atts['another_data']) ? $atts['another_data'] : 'another default value',
),
)
);
// ...
}[wp_preact_plugin data_from_atts="some data value from atts..." another_data_from_atts="another data value from atts..."]
The build-config.json file controls what is included in the final ZIP:
{
// Include only necessary files and folders
"include": ["main.php", "index.php", "includes", "assets"],
// Exclude Vite HTML file. This file is not needed in the WordPress plugin (production).
"exclude": ["assets/index.html"]
}- include: Files/folders to include
- exclude: Files/folders to remove from the build
- WordPress Plugin API
- Composer (dependency manager)
- Symfony Components (Filesystem, Finder, Console)
- Preact: Lightweight UI library (React alternative)
- TypeScript: JavaScript superset with static typing
- Vite: Modern and fast build tool
- @preact/preset-vite: Vite preset for Preact
- Make sure you ran
npm run buildin the frontend folder - Check if files exist in
assets/js/andassets/css/
- Run
npm installagain in the frontend folder - Check versions in
package.json
- Verify the plugin is in the
wp-content/plugins/folder - Confirm the
main.phpfile exists
- Run
composer installto install PHP dependencies - Check permissions for the
build/folder
This project is licensed under the MIT License. See the LICENSE file for more details.
Contributions are welcome! Feel free to open issues or pull requests.
