22
33namespace App \Providers ;
44
5- use Illuminate \Foundation \Vite ;
6- use Illuminate \Support \HtmlString ;
7- use Illuminate \Support \Js ;
85use Illuminate \Support \ServiceProvider ;
96
107class AppServiceProvider extends ServiceProvider
@@ -16,157 +13,7 @@ class AppServiceProvider extends ServiceProvider
1613 */
1714 public function register ()
1815 {
19- $ this ->app ->singleton (Vite::class, fn () => new class extends Vite
20- {
21- /**
22- * The prefetching strategy to use.
23- *
24- * @var 'waterfall'|'aggressive'
25- */
26- protected $ prefetchStrategy = 'waterfall ' ;
27-
28- /**
29- * When using the "waterfall" strategy, the count of assets to load at one time.
30- *
31- * @param int
32- */
33- protected $ prefetchChunks = 3 ;
34-
35- /**
36- * Set the prefetching strategy.
37- *
38- * @param 'waterfall'|'aggressive' $strategy
39- * @param ...mixed $config
40- */
41- public function usePrefetchStrategy (string $ strategy , mixed ...$ config ): static
42- {
43- $ this ->prefetchStrategy = $ strategy ;
44-
45- if ($ strategy === 'waterfall ' ) {
46- $ this ->prefetchChunks = $ config [0 ] ?? 3 ;
47- }
48-
49- return $ this ;
50- }
51-
52- /**
53- * Generate Vite tags for an entrypoint.
54- *
55- * @param string|string[] $entrypoints
56- * @param string|null $buildDirectory
57- * @return \Illuminate\Support\HtmlString
58- */
59- public function __invoke ($ entrypoints , $ buildDirectory = null )
60- {
61- $ manifest = $ this ->manifest ($ buildDirectory ??= $ this ->buildDirectory );
62- $ base = parent ::__invoke ($ entrypoints , $ buildDirectory );
63-
64- if ($ this ->isRunningHot ()) {
65- return $ base ;
66- }
67-
68- return collect ($ entrypoints )
69- ->flatMap (fn ($ entrypoint ) => collect ($ manifest [$ entrypoint ]['dynamicImports ' ] ?? [])
70- ->map (fn ($ import ) => $ manifest [$ import ])
71- ->filter (fn ($ chunk ) => str_ends_with ($ chunk ['file ' ], '.js ' ) || str_ends_with ($ chunk ['file ' ], '.css ' ))
72- ->flatMap ($ resolveImportChunks = function ($ chunk ) use (&$ resolveImportChunks , $ manifest ) {
73- return collect ([...$ chunk ['imports ' ] ?? [], ...$ chunk ['dynamicImports ' ] ?? []])
74- ->reduce (
75- fn ($ chunks , $ import ) => $ chunks ->merge (
76- $ resolveImportChunks ($ manifest [$ import ])
77- ),
78- collect ([$ chunk ])
79- )
80- ->merge (collect ($ chunk ['css ' ] ?? [])->map (
81- fn ($ css ) => collect ($ manifest )->first (fn ($ chunk ) => $ chunk ['file ' ] === $ css ) ?? [
82- 'file ' => $ css ,
83- ],
84- ));
85- })
86- ->map (function ($ chunk ) use ($ buildDirectory , $ manifest ) {
87- return collect ([
88- ...$ this ->resolvePreloadTagAttributes (
89- $ chunk ['src ' ] ?? null ,
90- $ url = $ this ->assetPath ("{$ buildDirectory }/ {$ chunk ['file ' ]}" ),
91- $ chunk ,
92- $ manifest ,
93- ),
94- 'rel ' => 'prefetch ' ,
95- 'href ' => $ url ,
96- ])->reject (
97- fn ($ value ) => in_array ($ value , [null , false ], true )
98- )->mapWithKeys (fn ($ value , $ key ) => [
99- $ key = (is_int ($ key ) ? $ value : $ key ) => $ value === true ? $ key : $ value ,
100- ])->all ();
101- })
102- ->reject (fn ($ attributes ) => isset ($ this ->preloadedAssets [$ attributes ['href ' ]])))
103- ->unique ('href ' )
104- ->values ()
105- ->pipe (fn ($ assets ) => with (Js::from ($ assets ), fn ($ assets ) => match ($ this ->prefetchStrategy ) {
106- 'waterfall ' => new HtmlString ($ base .<<<HTML
107-
108- <script>
109- window.addEventListener('load', () => window.setTimeout(() => {
110- const linkTemplate = document.createElement('link')
111- linkTemplate.rel = 'prefetch'
112-
113- const makeLink = (asset) => {
114- const link = linkTemplate.cloneNode()
115-
116- Object.keys(asset).forEach((attribute) => {
117- link.setAttribute(attribute, asset[attribute])
118- })
119-
120- return link
121- }
122-
123- const loadNext = (assets, count) => window.setTimeout(() => {
124- const fragment = new DocumentFragment
125-
126- while (count > 0) {
127- const link = makeLink(assets.shift())
128- fragment.append(link)
129- count--
130-
131- if (assets.length) {
132- link.onload = () => loadNext(assets, 1)
133- link.error = () => loadNext(assets, 1)
134- }
135- }
136-
137- document.head.append(fragment)
138- })
139-
140- loadNext( {$ assets }, {$ this ->prefetchChunks })
141- }))
142- </script>
143- HTML ),
144- 'aggressive ' => new HtmlString ($ base .<<<HTML
145-
146- <script>
147- window.addEventListener('load', () => window.setTimeout(() => {
148- const linkTemplate = document.createElement('link')
149- linkTemplate.rel = 'prefetch'
150-
151- const makeLink = (asset) => {
152- const link = linkTemplate.cloneNode()
153-
154- Object.keys(asset).forEach((attribute) => {
155- link.setAttribute(attribute, asset[attribute])
156- })
157-
158- return link
159- }
160-
161- const fragment = new DocumentFragment
162- {$ assets }.forEach((asset) => fragment.append(makeLink(asset)))
163- document.head.append(fragment)
164- }))
165- </script>
166- HTML ),
167- }));
168- }
169- });
16+ //
17017 }
17118
17219 /**
0 commit comments