kucrut/vite-for-wp

It fails when a handle has `wp_add_inline_script` associated with it

irshadahmad21 opened this issue · 0 comments

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.

Steps:

  • Use this code
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'
);
  • Run vite
  • Go to the page where the script is supposed to load

Expected behavior:

The script should load correctly.

Actual behavior:

It fails with an error in the console - Uncaught SyntaxError: Cannot use import statement outside a module

Reason

set_script_type_attribute function assumes that there is only one <script> tag rendered.

vite-for-wp/vite-for-wp.php

Lines 113 to 117 in bce4607

$processor = new WP_HTML_Tag_Processor( $tag );
if ( $processor->next_tag( 'script' ) ) {
$processor->set_attribute( 'type', 'module' );
}

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.

Solution

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();
}