kucrut / vite-for-wp Goto Github PK
View Code? Open in Web Editor NEWVite integration for WordPress plugins and themes development.
License: GNU General Public License v2.0
Vite integration for WordPress plugins and themes development.
License: GNU General Public License v2.0
Hey Dzikri! Hope you're well.
I see version 0.8 is not yet released. The main
branch contains some fixes for bugs that I've experienced, primarily the duplication of the React preamble script when more than one asset is enqueued on the page.
Is there a plan to release version 0.8?
Heyup!
Thanks for the plugin! Since I am working with ddev/ddev as my development environment, I was wondering if you have any suggestions to get it working there. I've tried to follow the instructions of this blogpost, sadly with no luck. Here's a reproduction repo: https://github.com/timothyoesch/ddev-vite-for-wp
Thanks for your help!
Hello there!
After installing the latest version of this plugin I got the following error:
The requested module '.../@kucrut/vite-for-wp/src/exports/index.js' does not provide an export named 'v4wp'
As I can see this release indeed doesn't export the following method.
Can you please take a look at it?
Thank you in advance.
Hi,
how can I implement this in the wordpress admin part for a plugin?
I'm developing plugin solely with React for it's administration and settings.
When I enqueue script (generated to some .js) it works just fine, but my dynamic imports from JSX cease to work properly even if generated .js file has correct reference to them
Hi there!
Thanks a lot for this nice module. Very helpful!
I noticed that the vite server doesn't seem to be killed once the process is exited (Ctrl+C).
Because if I start vite again, the port will increment.
e.g.:
$ yarn dev # Local: http://127.0.0.1:5173/
# ˆC
$ yarn dev # Local: http://127.0.0.1:5174/
# ˆC
Hi, I'm trying to use this package together with other packages like unocss.
I created the vite.config.js
file used like this
import path from 'node:path'
import create_config from '@kucrut/vite-for-wp'
import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
import Vue from '@vitejs/plugin-vue'
import Unocss from 'unocss/vite'
import type { UserConfig } from 'vite'
import { AnuComponentResolver } from 'anu-vue'
export default create_config({
client: 'client/main.ts',
settings: 'settings/main.ts',
}, 'dist', {
resolve: {
alias: {
'~/client/': `${path.resolve(__dirname, 'client')}/`,
'~/settings/': `${path.resolve(__dirname, 'settings')}/`,
},
},
build: {
target: 'esnext',
},
plugins: [
Vue({ reactivityTransform: true }),
Unocss(),
Components({
dirs: [
'client/components',
'settings/components',
],
resolvers: [
AnuComponentResolver(),
],
}),
AutoImport({
imports: [
{
'vue': ['ref', 'computed', 'reactive', 'onMounted'],
'@vueuse/core': ['useLocalStorage'],
},
],
vueTemplate: true,
dirs: [
'settings/composables',
'client/composables',
],
eslintrc: { enabled: true },
}),
],
} as UserConfig)
While in the plugin.php
file in the root directory of the plugin
add_action('admin_enqueue_scripts', static function () : void {
enqueue_asset(__DIR__ . '/frontend/dist', 'settings/main.ts', ['in-footer' => true]);
});
this works fine in development environment, but every time i run the build command, unocss stops working.
Where am I wrong?
Or will any vite template be ready for block development
https://developer.wordpress.org/block-editor/getting-started/devenv/nodejs-development-environment/
Does your plugin has ability to load dotenv variables from .env file?
I ran into some problems with multiple outputs that depended on same internal imports. Not sure if it's Vite itself or the @vitejs/plugin-vue that splits up the js/css of vue components that is being reused in multiple output files. The js file are getting imported asynchronically in runtime. But the split css for the component is never imported. This is only a problem in production, the vite dev server handles it just fine.
I manage to fix this with a wp filter. (Thanks for adding these filters in the source code btw). But this should perhaps be added in a future update? Unless this is vue specific, but I dont think it is.
function vfw_production_assets(array $assets, object $manifest, string $entry, array $options): ?array
{
$url = \Kucrut\Vite\prepare_asset_url( $manifest->dir );
$item = $manifest->data->{$entry};
if ( ! empty( $item->imports ) ) {
foreach ( $item->imports as $import ) {
$import_item = $manifest->data->{$import};
if ( ! empty( $import_item->css ) ) {
foreach ( $import_item->css as $css_file_path ) {
$slug = strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $css_file_path), '-'));
// Including a slug based on the actual css file in the handle ensures it wont be registered more than once.
$style_handle = "{$options['handle']}-{$slug}";
if ( wp_register_style( $style_handle, "{$url}/{$css_file_path}", $options['css-dependencies'], null, $options['css-media'] ) ) {
$assets['styles'][] = $style_handle;
}
}
}
}
}
return $assets;
}
add_filter( 'vite_for_wp__production_assets', fn ( ...$args ) => vfw_production_assets( ...$args ), 10, 4 );
To clarify a bit more. The two input files in vite.config.js is "admin.ts" and "admin_menu.ts". Both uses the Vue component Menu.vue.
The manifest.js file looks like this:
{
"Menu.css": {
"file": "assets/Menu-c4e73a0f.css",
"src": "Menu.css"
},
"_Menu.vue_vue_type_script_setup_true_lang-91a54a7b.js": {
"css": [
"assets/Menu-c4e73a0f.css"
],
"file": "assets/Menu.vue_vue_type_script_setup_true_lang-91a54a7b.js",
"imports": [
"_runtime-dom.esm-bundler-17b5f22b.js"
]
},
"_runtime-dom.esm-bundler-17b5f22b.js": {
"file": "assets/runtime-dom.esm-bundler-17b5f22b.js"
},
"resources/js/admin.ts": {
"file": "assets/admin-45447c50.js",
"imports": [
"_runtime-dom.esm-bundler-17b5f22b.js",
"_Menu.vue_vue_type_script_setup_true_lang-91a54a7b.js"
],
"isEntry": true,
"src": "resources/js/admin.ts"
},
"resources/js/admin_menu.css": {
"file": "assets/admin_menu-c4837d8c.css",
"src": "resources/js/admin_menu.css"
},
"resources/js/admin_menu.ts": {
"css": [
"assets/admin_menu-c4837d8c.css"
],
"file": "assets/admin_menu-5fa266d6.js",
"imports": [
"_runtime-dom.esm-bundler-17b5f22b.js",
"_Menu.vue_vue_type_script_setup_true_lang-91a54a7b.js"
],
"isEntry": true,
"src": "resources/js/admin_menu.ts"
}
}
_runtime-dom.esm-bundler-17b5f22b.js
(Vue.js framework) and _Menu.vue_vue_type_script_setup_true_lang-91a54a7b.js
(Menu.vue) are being imported async in admin_menu-5fa266d6.js
or admin-45447c50.js
which vite for wp is already registering. With my filter above assets/Menu-c4e73a0f.css
is now also being registered.
Not sure if I'm missing something obvious here, but I'm using your package for a larger Vue3 project that has dynamic imports.
So $item = $manifest->data->{$entry}
in load_production_asset()
might have an array of dynamicImports
.
These dynamic imports, in turn, have manifest entries that list CSS dependencies of their own.
I thought that Vite would have code to automatically load and inject this CSS into the page when the dynamic import is requested. It actually does so in development mode, but in production builds, those CSS files fail to load.
As a workaround, I'm currently using the vite_for_wp__production_assets
WP filter to recursively scan and queue any potential dynamic CSS dependencies but I'm sure it must be a Vite build option that is set incorrectly that's causing the problem.
My plugin has the assets inside the plugin/assets/dev
folder. The entry point is the plugin/assets/dev/application.js
file that has imports for the scss and js (jsx files)
my-plugin/
├ assets/
| └ dev/
| ├ scripts/
| ├ styles/
| └ application.js
├ package.json
├ plugin.php
└ vite.config.js
The production build will create a assets/public
folder with the correct manifest and compiled files (CSS looks ok, I don't get any errors in JS ones, but the admin doesn't render so I need to check what happens here, probably some react stuff).
The thing is, when I run npm run dev
to run the vite
command, all I get in the public folder is the vite-dev-server.json
file with
{"base":"/","origin":"http://localhost:5174","port":5174,"plugins":[]}
in it. No assets get bundled 🤷🏼♂️
What am I missing?
I cannot disable sourcemap adding sourcemap: false
Hi,
I was wondering if you would consider adding an option to avoid executing the following:
buildEnd() {
rmSync(manifest_file, { force: true });
}
The issue arises when built files are committed to source control and manifest.json is used to load assets in WordPress. If the development server is run with the intention of making modifications, which might not be committed to production, it results in the removal of manifest.json. This disrupts the existing asset loading. Consequently, I have to either run the production script to restore it or use Git to recover the file after running the development script. It would be more convenient to leave the repository unchanged after running development, simply to avoid unnecessary actions.
See #86 (comment)
I'm trying to use the package.
I followed the steps in the README.md
file and created an vite.config.js
file that looks like:
import create_config from "@kucrut/vite-for-wp";
export default create_config("src/scripts/main.ts", "dist/scripts");
I also created a src/inc/Assets.php
in my plugin that looks like:
<?php
namespace CUSTOMPLUGIN;
use Kucrut\Vite;
class Assets
{
public function __construct()
{
add_action('wp_enqueue_scripts', [$this, 'CUSTOM_PLUGIN_enqueue_scripts_styles']);
}
public function CUSTOM_PLUGIN_enqueue_scripts_styles()
{
// wp_enqueue_script(CUSTOM_PLUGIN_HANDLE, CUSTOM_PLUGIN_URI . 'dist/assets/main.9470b65c.js', [], CUSTOM_PLUGIN_VERSION, true);
Vite\enqueue_asset(
CUSTOM_PLUGIN_URI . 'dist',
CUSTOM_PLUGIN_URI . 'src/scripts/main.ts',
[
'handle' => CUSTOM_PLUGIN_HANDLE,
'version' => CUSTOM_PLUGIN_VERSION,
'in-footer' => true,
]
);
}
}
new Assets();
and import it into my main plugin file
<?php
/**
* Plugin Name: Custom Plugin
* Description: Custom plugin
* Version: 0.0.1
* Text Domain: custom-plugin
*/
defined('WPINC') || die;
// Constants.
const CUSTOM_PLUGIN_VERSION = '0.0.1';
const CUSTOM_PLUGIN_FILE = __FILE__;
define('CUSTOM_PLUGIN_DIR', plugin_dir_path(CUSTOM_PLUGIN_FILE));
define('CUSTOM_PLUGIN_URI', plugin_dir_url(CUSTOM_PLUGIN_FILE));
define('CUSTOM_PLUGIN_HANDLE', 'am-paraphraser');
// Composer.
require_once CUSTOM_PLUGIN_DIR . 'vendor/autoload.php';
require_once CUSTOM_PLUGIN_DIR . 'src/inc/Assets.php';
But then my script is not showing in the frontend.
Am I missing something?
Thanks.
Hey.
I can't see my plugin in the list of plugins in Wordpress. Is it possible that you can put a test plugin on your GitHub so I can download it and see what I'm doing wrong.
I'm trying to make a plugin that uses vite react and load it in wordpress. But I do something wrong here :)
EDIT:
I see you made Catatan. But if you have time, can you make a basic vite-react plugin with this method that loads the react app in a footer?
When I install PHP package composer require kucrut/vite-for-wp
, there are lots of files and folders inside kucrut/vite-for-wp
which are not needed. I believe only vite-for-wp.php
and composer files are needed.
Hello,
I am grateful for your contributions. 🙏
I found a bug after I run `yarn build‵
"kucrut/vite-for-wp": "^0.8.0"
manifest.json
will be created in dist/.vite
directory which is WRONG
function get_manifest will try to find the manifest file in __DIR__ . '/js/dist'
, NOT in __DIR__ . '/js/dist/.vite'
That will cause an error, lead to empty assets, so the built js won't be enqueue.
"kucrut/vite-for-wp": "^0.5.2"
It seems the manifest.json
will be created in dist/.vite
in vite 5
reference
nystudio107/craft-vite#77
https://www.drupal.org/project/vite/issues/3401054
I faced this issue while using @radix-ui/<some-component>
which the wp_scripts()
plugin.
The generated output did not account for the dependency's dependency (radix-ui depending on react).
The specific error shown in console says something like import url of react is invalid and if you go check the generated js (without minify) you can see that it is including some import * as React$1 from "react"
which after some debugging I found out where only appearing while including the code that uses radix-ui.
After some trial and error I found out that there are some specific includes set to the rollup-plugin-external-globals
config inside wp-scripts.js
and after checking the documentation there seems to be no need for this, commenting it out did fix the issue and the globals were correctly defined.
This is useful if you are willing to integrate shadcn components in your plugin. Can't tell if also happens with other dependencies that also depend on react but might be the case.
So far that change has not caused any side effect on my project but surely you had a reason for that and maybe a fix can be figured out from there.
At vite5 manifest file is located at /dist/.vite directory.
So this code does not work.
add_action( 'wp_enqueue_scripts', function (): void {
Vite\enqueue_asset(
__DIR__ . '/dist',
'assets/main.js',
[
'handle' => 'my-script-handle',
'dependencies' => ['jquery'], // Optional script dependencies. Defaults to empty array.
'css-dependencies' => [], // Optional style dependencies. Defaults to empty array.
'css-media' => 'all', // Optional.
'css-only' => false, // Optional. Set to true to only load style assets in production mode.
'in-footer' => true, // Optional. Defaults to false.
]
);
} );
And I think
/**
* Load production asset
*
* @since 0.1.0
*
* @param object $manifest Asset manifest.
* @param string $entry Entrypoint to enqueue.
* @param array $options Enqueue options.
*
* @return array|null Array containing registered scripts & styles or NULL if there was an error.
*/
function load_production_asset( object $manifest, string $entry, array $options ): ?array {
$url = prepare_asset_url( $manifest->dir );
So I think that asset_url and manifest->dir should be distinct.
By the way, I really like your project. Thanks.
npm add -D vite @kucrut/vite-for-wp
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: smfw@1.0.0
npm ERR! Found: vite@5.1.4
npm ERR! node_modules/vite
npm ERR! dev vite@"^5.1.4" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer vite@"^4.4.11" from @kucrut/[email protected]
npm ERR! node_modules/@kucrut/vite-for-wp
npm ERR! dev @kucrut/vite-for-wp@"*" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
Thank you for this tool. It's amazing!
For webpack WP has a plugin dependency-extraction-webpack-plugin that bundles all the WP dependencies that are loaded externally.
Here is the related discussion on Vite repo: vitejs/vite#9411
Could we have that missing piece?
I am ready to help build such a feature, but unfortunately, I am not an expert on the build tools.
When associating some inline script for a handle using wp_add_inline_script
with $position
set to 'before'
, it results in failure of setting type="module"
for the script handle. Rather the type="module"
is added to the inline script, not the entrypoint.
add_action( 'wp_enqueue_scripts', function (): void {
Vite\enqueue_asset(
__DIR__ . '/js/dist',
'js/src/main.ts',
[
'handle' => 'my-script-handle',
]
);
} );
// Add the inline script for the handle
wp_add_inline_script(
'my-script-handle',
sprintf( 'var myPluginData = %s;', $var, wp_json_encode( [ 'someData' => 'someValue' ] ) ),
'before'
);
vite
The script should load correctly.
It fails with an error in the console - Uncaught SyntaxError: Cannot use import statement outside a module
set_script_type_attribute
function assumes that there is only one <script>
tag rendered.
Lines 113 to 117 in bce4607
The fact is that the $tag
can contain more than one script handles:
<script id="my-script-handle-js-before">
var myPluginData = {"someData":"someValue"};
</script>
<script src="http://localhost:5173/js/src/main.ts" id="my-script-handle-js"></script>
So, when using $processor->next_tag( 'script' )
, it selects the first script, which is not desired here.
script_loader_tag
filter passes a third argument as $src
, which can be used to check if it matches the src
attribute of the script.
function set_script_type_attribute( string $target_handle, string $tag, string $handle, string $src ): string {
if ( $target_handle !== $handle ) {
return $tag;
}
$processor = new WP_HTML_Tag_Processor( $tag );
$script_fount = false;
do {
$script_fount = $processor->next_tag( 'script' );
} while ($processor->get_attribute( 'src' ) !== $src );
if ( $script_fount ) {
$processor->set_attribute( 'type', 'module' );
}
return $processor->get_updated_html();
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.