npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rafiahmedd/wp-vite

v1.0.5

Published

Vite plugin for WordPress plugin and theme development

Readme

WP Vite

Vite integration for WordPress plugin and theme development.
Dev/prod aware · React HMR · Vite 4 & 5 · PSR-4 · Zero config needed.


Requirements

| Tool | Version | |------|---------| | PHP | ≥ 8.0 | | WordPress | ≥ 5.8 (6.2+ for HTML Tag Processor; falls back gracefully) | | Vite | ≥ 4.0 | | Node | ≥ 18 |


Installation

PHP (Composer)

composer require rafiahmedd/wp-vite

JS (npm / pnpm / yarn)

npm install -D @rafiahmedd/wp-vite

Quick Start

1 — Configure Vite

Create vite.config.js in your plugin/theme root:

import { wpVite } from '@rafiahmedd/wp-vite';

export default {
    plugins: [
        wpVite({
            input:  'src/main.ts',  // entry point
            outDir: 'dist',         // output directory
        }),
    ],
};

Add scripts to package.json:

{
    "scripts": {
        "dev":   "vite",
        "build": "vite build"
    }
}

2 — Enqueue in PHP

<?php

add_action( 'wp_enqueue_scripts', function (): void {
    wp_vite_enqueue(
        __DIR__ . '/dist',
        'src/main.ts',
        [
            'handle'    => 'my-plugin',
            'in-footer' => true,
        ]
    );
} );

3 — Develop and build

npm run dev    # start HMR dev server
npm run build  # build for production

That's it. The PHP side automatically detects whether you're in dev or prod mode.


How It Works

Development mode

When npm run dev is running, the Vite plugin writes a dist/vite-dev-server.json file:

{
    "origin":  "http://localhost:5173",
    "base":    "/",
    "plugins": ["vite:react-refresh", "wp-vite"]
}

The PHP package finds this file and serves assets directly from the Vite dev server — giving you instant HMR.

When the dev server stops, the file is automatically removed.

Production mode

After npm run build, Vite writes either:

  • Vite 5+: dist/.vite/manifest.json
  • Vite 4: dist/manifest.json

The PHP package detects whichever format is present and uses it to resolve hashed filenames for scripts and styles.


PHP API

wp_vite_enqueue( $buildDir, $entry, $options )

Register and enqueue a Vite entry point.

wp_vite_enqueue(
    __DIR__ . '/dist',
    'src/main.tsx',
    [
        'handle'           => 'my-plugin',           // required
        'dependencies'     => [ 'wp-element' ],      // script deps
        'css-dependencies' => [ 'wp-components' ],   // style deps
        'css-media'        => 'all',                 // CSS media attribute
        'css-only'         => false,                 // true = no JS tag
        'in-footer'        => true,                  // load in footer
    ]
);

wp_vite_register( $buildDir, $entry, $options )

Register only — returns handles you can enqueue yourself later.

$assets = wp_vite_register( __DIR__ . '/dist', 'src/main.ts', [
    'handle' => 'my-plugin',
] );

// $assets = [ 'scripts' => [ 'my-plugin' ], 'styles' => [ 'my-plugin-main' ] ]

wp_enqueue_script( 'my-plugin' );
wp_enqueue_style( 'my-plugin-main' );

OOP alternative

If you prefer namespaced calls:

use WpVite\AssetManager;

AssetManager::enqueue( __DIR__ . '/dist', 'src/main.tsx', [ 'handle' => 'my-plugin' ] );
AssetManager::register( __DIR__ . '/dist', 'src/admin.ts', [ 'handle' => 'my-admin' ] );

React Support

Install the React plugin:

npm install -D @vitejs/plugin-react
npm install react react-dom

Update vite.config.js:

import { wpVite } from '@rafiahmedd/wp-vite';
import react from '@vitejs/plugin-react';

export default {
    plugins: [
        wpVite({ input: 'src/main.jsx', outDir: 'dist' }),
        react(),
    ],
};

React Fast Refresh (HMR) is injected automatically during development.


Externalising WordPress Packages (smaller bundles)

WordPress ships React, jQuery, and all @wordpress/* packages as global scripts. You can tell Vite to exclude them from your bundle using the wpScripts() plugin:

import { wpVite, wpScripts } from '@rafiahmedd/wp-vite';
import react from '@vitejs/plugin-react';

export default {
    plugins: [
        wpVite({ input: 'src/main.jsx', outDir: 'dist' }),
        wpScripts(),   // exclude react, react-dom, @wordpress/* from bundle
        react(),
    ],
};

Then declare the handles as dependencies on the PHP side:

wp_vite_enqueue( __DIR__ . '/dist', 'src/main.jsx', [
    'handle'       => 'my-plugin',
    'dependencies' => [ 'react', 'react-dom', 'wp-element' ],
] );

Customising the externals map

// Add extra globals
wpScripts({ lodash: '_', 'my-lib': 'MyLib' });

// Remove an entry from the defaults (include react in your bundle)
wpScripts({ react: false, 'react-dom': false });

Default externals map:

| Package | Global | |---------|--------| | jquery | jQuery | | react | React | | react-dom | ReactDOM | | react-dom/client | ReactDOM | | @wordpress/api-fetch | wp.apiFetch | | @wordpress/blocks | wp.blocks | | @wordpress/block-editor | wp.blockEditor | | @wordpress/components | wp.components | | @wordpress/compose | wp.compose | | @wordpress/data | wp.data | | @wordpress/element | wp.element | | @wordpress/hooks | wp.hooks | | @wordpress/i18n | wp.i18n | | @wordpress/notices | wp.notices | | @wordpress/url | wp.url |


Multiple Entry Points

Each entry must be enqueued separately:

// vite.config.js
wpVite({
    input: {
        main:  'src/main.ts',
        admin: 'src/admin.ts',
    },
    outDir: 'dist',
});
// plugin.php
wp_vite_enqueue( __DIR__ . '/dist', 'src/main.ts',  [ 'handle' => 'my-plugin-frontend' ] );
wp_vite_enqueue( __DIR__ . '/dist', 'src/admin.ts', [ 'handle' => 'my-plugin-admin' ] );

Available Filters (WordPress)

| Filter | Description | |--------|-------------| | wp_vite_manifest_data | Modify raw manifest data after it's read from disk. | | wp_vite_registered_assets | Alter the array of registered handles after any mode. | | wp_vite_dev_assets | Alter handles registered in development mode. | | wp_vite_prod_assets | Alter handles registered in production mode. |

Example — inject window.MyPlugin before the script runs:

add_filter( 'wp_vite_registered_assets', function ( array $assets ): array {
    if ( in_array( 'my-plugin', $assets['scripts'], true ) ) {
        wp_add_inline_script(
            'my-plugin',
            'window.MyPlugin = ' . wp_json_encode( [ 'ajax' => admin_url( 'admin-ajax.php' ) ] ) . ';',
            'before'
        );
    }

    return $assets;
} );

Directory Structure

This package

wp-vite/
├── .github/workflows/ci.yml     CI — PHP 8.0–8.3, Node 18–22
├── example/
│   ├── plugin-usage.php         PHP usage examples (5 patterns)
│   └── vite.config.js           Vite config examples (5 variants)
├── js/src/index.js              Vite plugin — wpVite() + wpScripts()
├── src/                         PSR-4 namespace: WpVite\
│   ├── AssetManager.php         register() / enqueue() — core logic
│   ├── AssetOptions.php         Typed readonly value object for options
│   ├── DevServer.php            @vite/client + React Refresh preamble
│   ├── Manifest.php             Manifest reader, cache, Vite 4+5 support
│   ├── ScriptModuleFilter.php   type="module" injection (WP 6.2+ + fallback)
│   ├── UrlResolver.php          Filesystem path → public WordPress URL
│   └── functions.php            wp_vite_enqueue() / wp_vite_register()
├── tests/
│   ├── Stubs/wordpress.php      WP function stubs — no WP install needed
│   ├── Unit/                    One test class per src/ class (7 files)
│   ├── WpViteTestCase.php       Base case with manifest fixture helpers
│   └── bootstrap.php
├── types/index.d.ts             TypeScript declarations for the JS plugin
├── .editorconfig
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile                     make test / lint / fix / check / clean
├── README.md
├── SECURITY.md
├── composer.json
├── package.json
├── phpcs.xml.dist
└── phpunit.xml.dist

Your plugin/theme (consuming this package)

your-plugin/
├── dist/                        ← build output (git-ignored)
│   ├── .vite/
│   │   └── manifest.json        ← Vite 5 production manifest
│   ├── manifest.json            ← Vite 4 production manifest (fallback)
│   └── vite-dev-server.json     ← written on `npm run dev`, auto-deleted
├── src/
│   └── main.tsx
├── composer.json
├── package.json
├── plugin.php
└── vite.config.js

Developer Commands

make install        # composer install + npm ci
make test           # PHPUnit (no coverage)
make test-coverage  # PHPUnit + HTML coverage report (needs Xdebug)
make lint           # PHPCS check
make fix            # PHPCBF auto-fix
make check          # lint + test (same as CI)
make clean          # remove vendor/, node_modules/, coverage/
make js-check       # verify JS plugin syntax with Node

Or via Composer:

composer test
composer lint
composer fix
composer check

License

MIT