diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 74f7839..6e04fef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,7 @@ jobs: - '8.1' - '8.2' - '8.3' + - '8.4' steps: - uses: shivammathur/setup-php@2.30.4 with: diff --git a/composer.json b/composer.json index c2a5746..a9b5cbe 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "license": "MPL-2.0", "description": "a lightweight PHP-backend integration for the Vite frontend build tool", "scripts": { - "test": "XDEBUG_MODE=coverage php test/test.php" + "test": "XDEBUG_MODE=coverage php test/test.php -v" }, "autoload": { "psr-4": { diff --git a/src/Manifest.php b/src/Manifest.php index 4640fd4..3a8e816 100644 --- a/src/Manifest.php +++ b/src/Manifest.php @@ -120,6 +120,17 @@ public function preloadFonts(): void ]; } + /** + * Register MIME types for preloading stylesheets. + */ + public function preloadStyles(): void + { + $this->preload_types = [ + ...$this->preload_types, + 'css' => ['type' => 'text/css', 'as' => 'style'], + ]; + } + /** * Create preload, CSS and JS tags for the specified entry point script(s). * @@ -208,6 +219,16 @@ private function createPreloadTags(array $chunks): string // Preload assets: + ['extension' => $extension] = pathinfo($chunk->file); + + if (isset($this->preload_types[$extension])) { + $preload = $this->preload_types[$extension]; + $type = $preload['type']; + $as = $preload['as']; + + $tags[] = "base_path}{$chunk->file}\" />"; + } + foreach ($chunk->assets as $asset) { $type = substr($asset, strrpos($asset, '.') + 1); @@ -235,6 +256,10 @@ private function createStyleTags(array $chunks): string foreach ($chunk->css as $css) { $tags[] = "base_path}{$css}\" />"; } + + if (str_ends_with($chunk->file, '.css') && $chunk->isEntry) { + $tags[] = "base_path}{$chunk->file}\" />"; + } } return implode("\n", $tags); @@ -248,7 +273,7 @@ private function createScriptTags(array $chunks): string $tags = []; foreach ($chunks as $chunk) { - if ($chunk->isEntry) { + if (str_ends_with($chunk->file, '.js') && $chunk->isEntry) { $tags[] = ""; } } @@ -267,7 +292,8 @@ private function findImportedChunks(array $entries): array throw new RuntimeException("Entry not found in manifest: {$entry}"); } - if (! $chunk->isEntry) { + // only check .js and .css files, because images dont get the "isEntry" information in the manifest + if ((str_ends_with($chunk->file, '.js') || str_ends_with($chunk->file, '.css')) && ! $chunk->isEntry) { throw new RuntimeException("Chunk is not an entry point: {$entry}"); } diff --git a/test/fixtures/manifest.json b/test/fixtures/manifest.json index f1da3df..0e0134e 100644 --- a/test/fixtures/manifest.json +++ b/test/fixtures/manifest.json @@ -39,5 +39,25 @@ "css": [ "assets/shared.a834bfc3.css" ] + }, + "public/scss/themes/admin/admin.scss": { + "file": "assets/admin-B8_LVhy3.css", + "src": "public/scss/themes/admin/admin.scss", + "isEntry": true, + "names": [ + "admin.css" + ] + }, + "public/css/plus.css": { + "file": "assets/plus-DwWFnKP0.css", + "src": "public/css/plus.css", + "isEntry": true, + "names": [ + "plus.css" + ] + }, + "public/img/favicon.ico": { + "file": "assets/favicon-zR_S-YMI.ico", + "src": "public/img/favicon.ico" } } diff --git a/test/test.php b/test/test.php index 18140a8..0437681 100644 --- a/test/test.php +++ b/test/test.php @@ -98,8 +98,9 @@ function () { ); $vite->preloadImages(); + $vite->preloadStyles(); - $tags = $vite->createTags("main.js", "consent-banner.js"); + $tags = $vite->createTags("main.js", "consent-banner.js", "public/scss/themes/admin/admin.scss", "public/css/plus.css", "public/img/favicon.ico"); eq( explode("\n", $tags->preload), @@ -111,6 +112,9 @@ function () { '', // Preload `views/foo.js` entry point script: '', + '', + '', + '', ], ); @@ -123,6 +127,8 @@ function () { '', // CSS imported by the consent-banner entry point script: '', + '', + '', ] );