kucrut / vite-for-wp

Vite integration for WordPress plugins and themes development.
GNU General Public License v2.0
260 stars 29 forks source link

CSS files are not handled as entrypoints #107

Open leifniem opened 2 months ago

leifniem commented 2 months ago

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:

https://github.com/kucrut/vite-for-wp/blob/df5a0a7f8aae1eed2d03a3fa4d33f5b6a5fb484a/vite-for-wp.php#L299-L333

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 :)

leifniem commented 2 months ago

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'];
    }
  }
groenroos commented 1 month ago

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!