kucrut/vite-for-wp

CSS files are not handled as entrypoints

leifniem opened this issue · 2 comments

I ran into the issue, that my SCSS was not being added to the markup and struggled to find out why.

Please correct me if i am wrong, but it seems that the following code (which was the only one handling CSS i could find) only handles CSS imported in scripts, which is why css and imports are missing for direct entries:

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

Lines 299 to 333 in df5a0a7

if ( ! empty( $item->imports ) ) {
// Recursive inline function to deeply check for .css files.
$check_imports = function ( array $imports ) use ( &$check_imports, &$assets, $manifest, $url, $options ): void {
foreach ( $imports as $import ) {
$import_item = $manifest->data->{$import};
if ( ! empty( $import_item->imports ) ) {
$check_imports( $import_item->imports );
}
if ( ! empty( $import_item->css ) ) {
register_stylesheets( $assets, $import_item->css, $url, $options );
}
}
};
$check_imports( $item->imports );
}
if ( ! empty( $item->css ) ) {
register_stylesheets( $assets, $item->css, $url, $options );
}
/**
* Filter registered production assets
*
* @param array $assets Registered assets.
* @param object $manifest Manifest object.
* @param string $entry Entrypoint file.
* @param array $options Enqueue options.
*/
$assets = apply_filters( 'vite_for_wp__production_assets', $assets, $manifest, $entry, $options );
return $assets;
}

I manually added the code to the vite-for-wp.php file, but i am not really comfortable with writing PHP, nor am i sure if the solution i had is too dirty for a PR, therefore i will add it in a separate comment below.

Thank you for your work :)

I manually added the following conditional to get it working:

  if ($options["css-only"] || str_ends_with($src, '.css')) {
    // Don't worry about browser caching as the version is embedded in the file name.
    // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
    if (wp_register_style($options['handle'], $src, $options['css-dependencies'], null)) {
      $assets['styles'][] = $options['handle'];
    }
  }

Also ran into this issue! Turns out the issue is that in production mode, the CSS files get erroneously enqueued as <script> tags, which of course doesn't work.

I was able to fix this without having to modify the source (and thus, still be able to use Composer), by using a filter:

function my_fix_scss_imports($assets, $manifest, $entry, $options) {
	$url = Vite\prepare_asset_url( $manifest->dir );
	$item = $manifest->data->{$entry};
	$src = "{$url}/{$item->file}";

	if (str_ends_with($src, '.css')) {
		// Don't worry about browser caching as the version is embedded in the file name.
		// phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
		if (wp_register_style($options['handle'], $src, $options['css-dependencies'], null)) {
			$assets['styles'][] = $options['handle'];
		}
	}

	return $assets;
}
add_filter( 'vite_for_wp__production_assets', 'my_fix_scss_imports', 10, 4 );

This will enqueue the <style> tags for any .css assets.

However, it will still enqueue the <script> tags, too. To remove those, set 'css-only' to true when enqueueing the asset.

If you enqueue the assets dynamically, you can sniff the filename, e.g.:

function load_asset($filename) {
	$file = explode('.', $filename);

	Vite\enqueue_asset(
		'dist',
		$filename,
		[
			'handle' => $file[0],
			'css-only' => in_array(end($file), ['scss', 'css']),
		]
	);
}

However, ideally this issue would of course be fixed in the original source!