Providing an opinionated & "Go To" Vite configuration for building WordPress blocks & traditional WordPress development with WP Interactivity API support and HMR & Vite DevServer integration.
- Compiles and outputs JavaScript, CSS, and other assets directly into WordPress-ready formats.
- Glob options to configure input paths.
- Complete Vite development server & HMR (Hot Module Replacement) integration.
- JSX/React code supported in
.jsfiles instead of using.jsx. - Support for WP Interactivity API blocks.
- Scripts with
@wordpress/interactivityimports will be compiled as modules. - The Vite development server will enable HMR for WP Interactivity API blocks.
- Scripts with
- Automatically externalizes WordPress globals like
wpand libraries likeReactto reduce bundle sizes.- Includes a preset of globals for wp dependencies and other common libraries in WordPress like react, react-dom, jquery, lodash etc.. (see src/globals.ts) with option to add additional globals.
- Uses
rollup-plugin-external-globalsplugin under the hood to ensure that globals are not imported for non-modules in compiled files but are instead defined externally.
- Paths in (block).json files like
file:./index.jswill be resolved with hashed file names whenmanifestis enabled. - Automatically reloads PHP files during development.
- Preserved folder structure in the output directory.
- Use vite
developmentmode to compile unminified with sourcemaps (sourcemaps are also included duringservecommand) - All configurations can be overridden using Vite's default configuration options.
Install the plugin via npm:
npm install --save-dev vite-wordpressor yarn
yarn add -D vite-wordpressAdd the plugin to your vite.config.js (no other Vite configurations needed):
import { ViteWordPress } from 'vite-wordpress';
export default {
plugins: [
ViteWordPress({
base: '/wp-content/plugins/my-plugin',
input: ['main.js'],
}),
],
};See all options here.
project-root/
├── src/
│ ├── js
│ │ └── main.js
│ ├── css
│ │ └── main.pcss
│ └── blocks
│ └── example-block
│ ├─ style.pcss (imported into index.js)
│ └─ index.js
├── build/
│ ├── js
│ │ └── main.js
│ ├── css
│ │ └── main.css
│ └── blocks
│ └── example-block
│ ├─ index.css
│ └─ index.js
├── vite.config.js
└── package.json
Vite config for the given example.
import { ViteWordPress } from 'vite-wordpress';
export default {
plugins: [
ViteWordPress({
base: '/wp-content/plugins/my-plugin',
input: ['js/*.js', 'css/*.pcss', 'blocks/*/*.js'],
}),
],
};Project examples (WordPress plugins) can be found here:
- Dynamic block: https://github.com/mrOttoW/vite-wordpress-plugin-block-example
- WP Interactivity API block: https://github.com/mrOttoW/vite-wordpress-plugin-interactivity-block-example
Install the vite-wordpress-php composer package.
composer require mrottow/vite-wordpressThe vite-wordpress node package can be used in hand with the vite-wordpress-php composer package to
integrate Vite's development server and HMR into WordPress, as well as manage the manifest file (if enabled), which can be used by simply adding
the following into your plugin or theme.
(new ViteWordPress\DevServer())->register();Aside to the integration, vite-wordpress exposes the plugin's configurations & a map of the latest build on the development server which is used by vite-wordpress-php
to automatically detect all enqueued scripts and template paths from the project through hooks and resolves these to source files served by the development
server. It updates script tags from these specific scripts to use as modules and injects Vite's client to enable HMR (Hot Module Replacement).
It's compatible with a traditional setup with vite-wordpress without the need for a manifest (non-hashed) but also works well with a manifest.
You can read more about this on the repository's README page.
Use https://github.com/mrOttoW/vite-php-asset-file to include a hash, manage dependencies identified in the code, and handle imported CSS assets.
Example project structure:
project-root/
├── src/
│ ├─ custom-slider.pcss (imported into custom-slider.js)
│ └─ custom-slider.js
├── build/
│ ├─ custom-slider.css
│ ├─ custom-slider.js
│ └─ custom-slider.asset.php
...
Example of registering and enqueueing the asset file based on the given example within a theme.
$asset_file = require get_stylesheet_directory() . 'build/custom-slider.asset.php';
wp_register_script(
'my-custom-slider',
get_stylesheet_directory_uri() . 'build/custom-slider.js',
$asset_file['dependencies'],
$asset_file['version'],
);
foreach ( $asset_file['assets'] as $css_handle => $css_path ) {
wp_register_style(
$css_handle,
get_stylesheet_directory_uri() . "build/{$css_path}",
[],
$asset_file['version']
);
}
wp_enqueue_script('my-custom-slider')Alternatively you can use the manifest and hashed file names for cache busting.
The manifest enabler in the plugin will add the manifest file but also add hash to file names.
export default {
plugins: [
ViteWordPress({
base: '/wp-content/plugins/my-plugin',
input: ['main.js'],
+ manifest: true
}),
],
};
You can use the Manifest Resolver from vite-wordpress-php to handle reading and accessing the Vite manifest file and additionally integrates it into the dev server.
use ViteWordPress\DevServer;
use ViteWordPress\Manifest;
$manifest = Manifest::create( 'absolute/path/to/manifest.json' ); // Also works with a PHP manifest file.
// When using the dev server you need to include the manifest.
( new DevServer( $manifest ) )->register();
// Enqueue scripts hook.
add_action( 'wp_enqueue_scripts', function () {
$file_name = Manifest::get_file( 'app.js' );
wp_enqueue_script( 'my-app', get_stylesheet_directory() . "build/{$file_name}" );
} );vite-wordpress ensures that JSON files are emitted as assets instead of being converted into JavaScript files.
This keeps the block.json file readable and compatible with functions like register_block_type() in WordPress.
It is also crucial for the block.json file to retain its original name to remain accessible in WordPress,
preventing it from being hashed when the manifest option is enabled.
Additionally, all URLs found in the block.json file will automatically be resolved to their corresponding hashed filenames.
For example the following block.json configurations:
{
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style.css",
"render": "file:./render.php",
"viewScript": "file:./view.js"
}Will include the hashed file names after compilation.
{
"editorScript": "file:./index.BFKxLtHH.js",
"editorStyle": "file:./index.BvpkZCOy.css",
"style": "file:./style.WLomad7Q.css",
"render": "file:./render.Aelou6by.php",
"viewScript": "file:./view.BQK8SocZ.js"
}The following plugin also allows you to generate a PHP manifest file that is compatible with the DevServer:
https://github.com/mrOttoW/vite-php-manifest
vite-wordpress also provides out-of-the-box support for development with the
WP Interactivity API.
Any scripts that import @wordpress/interactivity (e.g., view scripts) will be compiled as modules, allowing them to
be resolved by the WordPress import map.
Additionally, vite-wordpress ensures that the development server ignores these static imports, allowing them to be resolved by WordPress rather than by Vite.
This will prevent errors from Vite's internal vite:import-analysis plugin failing the resolve import.
A project example (WordPress plugin) can be found here: https://github.com/mrOttoW/vite-wordpress-plugin-interactivity-block-example
Let's say you have the following project:
project-root/
├── classes/
│ ├── Plugin.php
│ ├── Helpers.php
│ ├── Fonts.php
│ └── Integration.php
├── templates/
│ ├── table.php
│ ├── button.php
│ └── card.php
├── src/
│ ├── js
│ │ └── main.js
│ ├── css
│ │ └── main.pcss
│ └── assets/
│ ├── svg/
│ │ ├── star.svg
│ │ └── coffee.svg
│ ├── images/
│ │ ├── background.png
│ │ └── logo.png
│ └── fonts/
│ └── arial.woff
├── vite.config.js
....
And you have various PHP functions that retrieve asset files from the assets folder, used across different template files or classes like:
<?php
echo Helpers::get_image('logo.png');
echo Helpers::get_svg('coffee.svg');
echo $fonts->get_font('arial.woff')You can use the following plugin to identify and emit assets referenced in PHP functions or callers during the build process. This ensures that Vite compiles only the assets used throughout the project:
https://github.com/mrOttoW/vite-php-asset-callers
The plugin parses PHP code to locate embedded assets, such as image files, SVGs, fonts, or other resources. It then processes and emits these assets for compilation in the final bundle.
Type: string
Default: 'build'
Directory for output files.
Type: string
Default: 'src'
Directory for source files.
Type: string
Default: ''
Example: '/wp-content/themes/my-theme'
Sets the base public path for generating URLs for assets in CSS/JS. If set, it will be appended with the outDir during the build command (e.g., /wp-content/themes/my-theme/{outDir}).
This is also used to link source files to build files during development.
Type: string[]
Default: []
List of input files relative to srcDir with glob options.
Type: string
Default: 'pcss'
CSS extension used for uncompiled files.
Type: boolean | string
Default: false
Generate a manifest file. Accepts true, false, or a custom path (this will also add a hash to all compiled files).
Type: boolean
Default: true
Preserve folder structure in the output. If set to false, all files are flattened into a single directory.
Type: object
Default: {}
Maps module names to global variables to mark them as external dependencies (in addition to preset globals).
Type: object
Default: {}
Define path aliases.
Type: string | string[] | false
Default: 'es2017'
Esbuild target.
Type: boolean
Default: true
Enable or disable code wrappers for JavaScript chunks.
Type: string | function
Default: document.addEventListener('DOMContentLoaded', () => {'use strict';
Code wrapper banner to prepend to output JS files.
Type: string | function
Default: });
Code wrapper footer to append to output JS files.
