wordpress-vite
v0.1.0
Published
WordPress plugin for Vite.
Maintainers
Readme
WordPress Vite Plugin
Introduction
Vite is a modern frontend build tool that provides an extremely fast development environment and bundles your code for production.
This plugin configures Vite for use with a WordPress theme.
Installing the WordPress Plugin
Run the following command in a terminal inside your project:
npm install -D wordpress-viteConfiguring Vite
Vite is configured via a vite.config.js file in the root of your project, or in this case, your theme. You are free to customize this file based on your needs.
The WordPress Vite plugin requires you to specify the entry points for your application. These may be JavaScript of CSS files, and include preprocessed languages such as TypeScript, JSX, TSX and Sass.
import { defineConfig } from 'vite';
import wordpress from 'wordpress-vite';
export default defineConfig({
plugins: [wordpress(['src/scss/main.scss', 'src/js/main.js'])],
});Loading Your Scripts and Styles
Currently, this plugin requires you to create a file to make sure your assets are correctly enqueued. This means setting up logic for when you are serving your assets and when you are building your assets.
Create a vite.php file in your functions folder and import it in your functions.php file, or copy and paste the following code directly into your functions.php file. It switches automatically: when the Vite dev server is running it writes a hot file into your theme, and its removal on shutdown switches the theme back to the built assets — no constants or configuration needed.
Update $entry_points to match the input array in your vite.config.js. Note that str_ends_with() requires PHP 8.0 or higher.
<?php
if ( file_exists(get_template_directory() . '/hot') ) {
add_action('wp_enqueue_scripts', 'vite_serve_assets');
} else {
add_action('wp_enqueue_scripts', 'vite_build_assets');
}
function vite_serve_assets(): void {
$vite_server = trim(file_get_contents(get_template_directory() . '/hot'));
$entry_points = [ 'src/scss/main.scss', 'src/js/main.js' ];
// Add Vite client to <head> tag
add_action('wp_head', function () use ($vite_server) {
echo '<script type="module" src="' . esc_url($vite_server . '/@vite/client') . '"></script>';
});
foreach ( $entry_points as $entry_point ) {
if ( str_ends_with($entry_point, '.scss') ) {
add_action('wp_head', function () use ($vite_server, $entry_point) {
echo '<link rel="stylesheet" href="' . esc_url($vite_server . '/' . $entry_point) . '" />';
});
}
if ( str_ends_with($entry_point, '.js') ) {
add_action('wp_head', function () use ($vite_server, $entry_point) {
echo '<script type="module" crossorigin src="' . esc_url($vite_server . '/' . $entry_point) . '"></script>';
});
}
}
}
function vite_build_assets(): void {
$manifest_path = get_template_directory() . '/build/manifest.json';
$manifest = file_exists($manifest_path) ? json_decode(file_get_contents($manifest_path), true) : null;
if ( ! is_array($manifest) ) {
return;
}
$module_handles = [];
foreach ( $manifest as $entry ) {
// Only enqueue entry points; chunks are loaded by the entries that import them.
if ( empty($entry['isEntry']) ) {
continue;
}
$handle = 'vite-' . sanitize_title($entry['file']);
$path = get_template_directory_uri() . '/build/' . $entry['file'];
if ( str_ends_with($entry['file'], '.css') ) {
wp_enqueue_style($handle, $path, [], null);
}
if ( str_ends_with($entry['file'], '.js') ) {
wp_enqueue_script($handle, $path, [], null, true);
$module_handles[] = $handle;
}
// CSS imported inside a JS entry ends up in that entry's "css" array.
foreach ( $entry['css'] ?? [] as $css_file ) {
wp_enqueue_style('vite-' . sanitize_title($css_file), get_template_directory_uri() . '/build/' . $css_file, [], null);
}
}
// Vite builds ES modules, so the script tags need type="module".
add_filter('script_loader_tag', function ($tag, $handle, $src) use ($module_handles) {
if ( in_array($handle, $module_handles, true) ) {
return '<script type="module" crossorigin src="' . esc_url($src) . '"></script>' . "\n";
}
return $tag;
}, 10, 3);
}Telling the Plugin About Your Site URL (Optional)
The dev server banner and the /index.html splash page display your site's URL. You can provide it in a vite.settings.json file in the same directory as your vite.config.js:
{
"app_url": "http://my-site.test"
}Alternatively, set an APP_URL environment variable. If neither is present, the dev server still runs normally.
HTTPS During Development
If your local WordPress site is served over HTTPS, the Vite dev server must be too, or the browser will block the assets as mixed content. There are two ways to configure this:
Herd or Valet certificates. Set
detectTlstotrue(to derive the hostname from your project folder and the configured TLD) or to your site's hostname, and optionally pick the environment explicitly:wordpress({ input: ['src/scss/main.scss', 'src/js/main.js'], detectTls: 'my-site.test', // or true devEnvironment: 'auto', // 'herd' | 'valet' | 'xampp' | 'docker' | false })Your own certificate files (e.g. from
mkcert), via environment variables in a.envfile:APP_URL=https://my-site.test VITE_DEV_SERVER_KEY=/path/to/my-site.test-key.pem VITE_DEV_SERVER_CERT=/path/to/my-site.test.pem
If no TLS configuration is found, the dev server falls back to plain HTTP and the hot file will contain an http:// URL, so the PHP snippet above works for both schemes without changes.
Running Vite
There are two ways you can run Vite. You may run the development server via the dev command, which is useful while developing locally. The development server will automatically detect changes to your files and instantly reflect them in any open browser windows.
Or, running the build command will version and bundle your application's assets and get them ready for you to deploy to production:
# Run the Vite development server
npm run dev
# Build and version the assets for production
npm run buildDisclaimer
This plugin is heavily based on the 'laravel-vite-plugin'. Much of the code from this application is the same, except for a few modifications made specifically for WordPress projects.
