Example of Vite integration with a WordPress theme, made to be easily used in other themes.
- support for different use cases:
- multiple entry points
- CSS-only entry points
- conditionally included entry points (on the PHP side)
- nested dependencies (any level)
- dynamic imports (with nested dependencies too)
- dev server with auto-reload
- no need to define constants or env variables and change them every time you switch between
prodanddevbuilds. The theme uses the browserSync header to check if it works on the dev server - works with Docker
- automatic modulepreload links for dependencies
- ability to load compiled styles into the Gutenberg editor
- ability to define a local WP host in .env file and not store it in git
- SCSS, Autoprefixer (optional)
- easy to integrate with an existing theme
- compatible with PHP 7.4+
The theme contains a small amount of content that is used primarily to verify that the build is working correctly.
There are only a few files related to the asset compilation. The main files are inc/vite-assets.php, vite.config.js,
and frontend-config.json.
- Install packages
npm install vite vite-plugin-browser-sync sass autoprefixer --save-dev. sass and autoprefixer are optional. - Copy
inc/vite-assets.phpto your theme and include it infunctions.php.
require get_template_directory() . '/inc/vite-assets.php';- Copy
postcss.config.cjsand.browserslistrcif you need Autoprefixer. - Copy
vite.config.jsto the root of the theme. Replacebuild.rollupOptions.inputwith your theme entry points. - Copy
.env.exampleas.envand change thePROXY_SOURCEvariable to the domain where your local WP site is running (ONLY used in DEV mode). This value is used to specify a proxy for browserSync in cases where the theme is used in WP instances running on different domains. If you don't need this, just hardcode your domain inplugins.VitePluginBrowserSync.bs.proxy.targetoption invite.config.js - Copy
frontend-config.jsto the theme root. Change thethemeNamevalue to the name of the theme folder, which will be inside the running WP instance. The folder name may be different if the theme is mounted to a Docker container, for example. Change other values only if they conflict with something in your theme:distFolder- change if this folder is already used for other purposes, it will be used asbuild.outDirvite optionviteServerPort- port where the vite dev server emits its assets (on localhost)devModeProxyHeader- custom header name, which is used to check dev mode
- Create a function
theme_get_entry_points_for_current_page()(example infunctions.php) that returns a list of entry points that need to be included on the current page. If you want to use a function with a different name, use filter with the name of your function:
add_filter('theme_assets_entry_points_function',
function () {
return 'your_function_name';
}
);- Add
import 'vite/modulepreload-polyfill';to the beginning of the main js entry point of the theme (example insrc/js/main-entry point.js) - Add scripts to
package.json:
"scripts": {
"start": "vite"
"build": "vite build",
},# start dev server
npm start
# build for production
npm run buildTheme relies on manifest.json in prod mode, so npm run build must be run at least once
Add the path to the source file in two places:
build.rollupOptions.inputinvite.config.js- add an entry to the option object where value is the path to the file (relative to the config), likepage_1: 'src/js/page-1-entrypoint.js', wherepage_1is arbitrary name- your
theme_get_entry_points_for_current_page()function - add a string with the path to the returned array. The path must be the same as inbuild.rollupOptions.input
// absolute path
background-image: url('/wp-content/themes/theme/assets/img/wp-logo.png');
// path from a scss variable + image
background-image: url('#{$img-path}/wp-logo.png');
background-image: url($img-path + '/wp-logo.png');
// custom function that adds an absolute path
background-image: img-url('wp-logo.png');It is possible to use an alias (defined in vite.config.js) if you want vite to handle an asset (copy to dist,
serve on dev server host, add hash to filename, etc.)
background-image: url('@img/wp-logo.png'); // vite alias as prefixWhen the dev server starts, it runs on its host (localhost:3005) simultaneously with the local WP instance (mywebsite.local). BrowserSync (localhost:3000) uses WP host (mywebsite.local) as a proxy, replaces all WP links (mywebsite.local) with its own (localhost:3000), and adds a custom header to all the requests. This header is used on the PHP side to replace the origin of all the dynamic scripts and styles (handled by vite) with the dev server host (localhost:3005).
To access website via LAN (Wi-Fi) network, enable server.host: true in vite.config.js and start the server.
Then replace localhost with your external ip (like 192.169.0.100) in theme_enqueue_vite_assets() (in vite-assets.php).
This could be automated with vite-plugin-dev-manifest that specifies an external host in its config
Example in theme_output_js_data() in functions.php
Example in theme_add_editor_styles() in functions.php