Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Vite For Wp Laravel Package

kucrut/vite-for-wp

Vite for WP integrates the Vite build tool with WordPress, giving theme and plugin developers fast HMR in development and simple manifest-based asset loading in production. It handles enqueueing scripts and styles with minimal configuration and no build headaches.

Deep Wiki
Context7

Getting Started

kucrut/vite-for-wp is a small Composer library plus an optional companion Vite plugin. It solves one narrow problem well: mapping a Vite entry point to the correct WordPress wp_enqueue_script() / wp_enqueue_style() calls in both development (Vite dev server + HMR) and production (built manifest).

Minimal setup:

composer require kucrut/vite-for-wp
npm install --save-dev vite

A plain Vite config is enough; the companion npm plugin mainly reduces boilerplate around manifest paths and base URLs.

// vite.config.js
import { defineConfig } from 'vite';

export default defineConfig({
  base: '/wp-content/plugins/my-plugin/dist/',
  build: {
    outDir: 'dist',
    emptyOutDir: true,
    manifest: true,
    rollupOptions: {
      input: 'src/main.js',
    },
  },
  server: {
    cors: true,
    strictPort: true,
  },
});

Then enqueue from PHP:

require_once __DIR__ . '/vendor/autoload.php';

add_action( 'wp_enqueue_scripts', function () {
    \Kucrut\Vite\enqueue_asset(
        __DIR__ . '/dist',
        'src/main.js',
        [
            'handle'       => 'my-plugin',
            'dependencies' => [ 'wp-element' ],
            'in-footer'    => true,
        ]
    );
} );

The first practical use case is usually an admin settings screen or a small React/Vue app where you want Vite’s fast HMR instead of @wordpress/scripts. Look first at the package README, then at the generated dist/manifest.json and dist/hot files—those two files explain almost all runtime behavior.

Development workflow:

npm run dev     # writes dist/hot, serves assets from localhost
npm run build   # writes manifest + hashed assets

The PHP helper checks for dist/hot; if present, it enqueues from the Vite dev server and adds the Vite client. If absent, it reads the manifest and enqueues the built files.

Implementation Patterns

Hook-specific enqueues. Do not enqueue everything globally. Use the hook that matches the screen:

add_action( 'admin_enqueue_scripts', function ( $hook ) {
    if ( 'toplevel_page_my-plugin' !== $hook ) {
        return;
    }

    \Kucrut\Vite\enqueue_asset(
        __DIR__ . '/dist',
        'src/admin.js',
        [
            'handle'       => 'my-plugin-admin',
            'dependencies' => [ 'wp-element', 'wp-components', 'wp-i18n' ],
        ]
    );
} );

For the block editor, use enqueue_block_editor_assets for editor-only code and enqueue_block_assets for code needed in both editor and frontend.

Multiple entries. Call the helper once per entry with a unique handle:

\Kucrut\Vite\enqueue_asset( __DIR__ . '/dist', 'src/frontend.js', [
    'handle' => 'my-plugin-frontend',
] );

\Kucrut\Vite\enqueue_asset( __DIR__ . '/dist', 'src/editor.js', [
    'handle'       => 'my-plugin-editor',
    'dependencies' => [ 'wp-blocks', 'wp-element', 'wp-components' ],
] );

Keep handles prefixed. Reusing a core handle such as react or wp-element can cause hard-to-debug override behavior.

CSS handling. The normal pattern is to import CSS from your JS entry:

import './style.css';

Vite records the emitted CSS in the manifest, and the helper enqueues it alongside the script. For a standalone stylesheet, make it a separate Vite entry or enqueue the built file yourself with wp_enqueue_style().

Passing data to JS. Use the handle you defined:

wp_localize_script( 'my-plugin-admin', 'MyPluginData', [
    'ajaxUrl' => admin_url( 'admin-ajax.php' ),
    'nonce'   => wp_create_nonce( 'my-plugin' ),
] );

wp_add_inline_script() also works, but remember module scripts are deferred. Inline “before” scripts still execute as classic scripts and may run before your module code.

Translations. Treat the enqueued handle like any other WordPress script handle:

wp_set_script_translations(
    'my-plugin-admin',
    'my-plugin',
    __DIR__ . '/languages'
);

Theme usage. The same pattern works in a theme; pass the theme’s dist path:

\Kucrut\Vite\enqueue_asset(
    get_template_directory() . '/dist',
    'src/main.js',
    [ 'handle' => 'my-theme' ]
);

Wrap it once. In a real plugin you will call this from several hooks. A small wrapper keeps paths and handle naming consistent:

function my_plugin_enqueue_asset( string $entry, array $options = [] ): void {
    \Kucrut\Vite\enqueue_asset(
        __DIR__ . '/dist',
        $entry,
        $options + [
            'handle' => 'my-plugin-' . sanitize_key( basename( $entry, '.js' ) ),
        ]
    );
}

Use the dev/prod split as intended. Run npm run dev while developing PHP/JS, and npm run build before deploying. The helper’s hot-file detection means you generally do not need environment flags or WP_DEBUG checks in application code.

Gotchas and Tips

A stale dist/hot file is the most common failure. If Vite is stopped but dist/hot remains, WordPress keeps trying to load http://localhost:5173/... and the site appears broken. Add dist/hot to .gitignore, exclude it from deployment artifacts, and delete it in CI before packaging. Treat the presence of dist/hot as a deployment error.

Manifest location differs across Vite versions. Vite 5+ defaults to .vite/manifest.json, while older setups and many examples expect dist/manifest.json. If the helper cannot find the manifest, confirm where Vite wrote it. Setting build.manifest: 'manifest.json' or using the companion Vite plugin avoids the mismatch. Always verify the actual file on disk after the first build.

Base URL and symlinked plugins. The PHP helper derives the public URL from the build directory path. If the plugin lives outside wp-content, is symlinked into place, or WordPress is installed in a subdirectory, URL resolution can break. Keep dist under the plugin/theme directory, set Vite’s base to the real public URL, and test with the same symlink/proxy setup you use locally.

WordPress dependencies are not ES modules. Listing wp-element as a dependency loads the global wp.element, but it does not make import { createElement } from '@wordpress/element' resolve in the browser. Either bundle the WordPress packages into your entry, or externalize them and convert the imports to globals with an additional Rollup/Vite plugin. This is the biggest conceptual gap when moving from @wordpress/scripts to Vite.

Only declare dependencies that are registered on that hook. Listing wp-components on a frontend page may produce a missing dependency and prevent your script from printing. Keep frontend, admin, and editor dependency lists separate.

Module scripts are deferred. Your entry code runs after HTML parsing, similar to defer. That is usually what you want, but inline classic scripts that assume your module has already initialized will race it. Use explicit events or expose initialization functions on window.

CORS, ports, and HTTPS. Vite’s dev server runs on a different origin from WordPress. If your WordPress site is HTTPS and Vite is HTTP, the browser will block the module. Use Vite’s HTTPS support or a local proxy. In Docker, set server.host appropriately and make sure the hot file contains a URL the browser can reach, not a container-internal hostname. strictPort: true avoids surprises when port 5173 is already occupied.

React Fast Refresh needs the preamble. @vitejs/plugin-react normally injects a refresh preamble through Vite’s HTML transform, which WordPress does not use. If React HMR fails with a refresh-runtime error, you likely need to output the preamble yourself before the module script. Simpler projects often skip Fast Refresh and rely on full reloads.

Beware duplicate Composer autoloads. The package exposes namespaced functions such as Kucrut\Vite\enqueue_asset. If two plugins each bundle their own copy and both autoload the function file, PHP can fatal with a redeclaration error. Guard the require or share a single vendor directory across plugins. This is a general Composer files autoload issue, not specific to this package.

Deploy the built output, not the source. Production needs dist/manifest.json, hashed JS/CSS assets, and any fonts/images referenced by the build. Do not ship dist/hot, and do not rely on npm run dev output in production.

Cache busting is automatic. The manifest contains hashed filenames, so you do not need to pass a manual version. If you wrap or re-enqueue assets yourself, preserve the manifest-derived version or you will lose cache invalidation.

Debugging checklist. If assets do not load: confirm the hook fires, confirm the entry key exactly matches the Vite input key, inspect dist/hot and dist/manifest.json, check the browser network tab for the resolved URL, and verify the script tag has type="module". The helper adds the module type for its own handles via script_loader_tag; manually enqueued scripts will not get that treatment.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource