@@ -6,6 +6,7 @@ import type { Nitro } from "nitro/types";
66import type { PublicAsset } from "nitro/types" ;
77import { relative , resolve } from "pathe" ;
88import { joinURL , withTrailingSlash } from "ufo" ;
9+ import { runParallel } from "../../utils/parallel.ts" ;
910
1011const readAssetHandler : Record <
1112 Exclude < Nitro [ "options" ] [ "serveStatic" ] | "true" | "false" , boolean > ,
@@ -30,41 +31,56 @@ export default function publicAssets(nitro: Nitro) {
3031 absolute : false ,
3132 dot : true ,
3233 } ) ;
33- for ( const id of files ) {
34- let mimeType =
35- mime . getType ( id . replace ( / \. ( g z | b r ) $ / , "" ) ) || "text/plain" ;
36- if ( mimeType . startsWith ( "text" ) ) {
37- mimeType += "; charset=utf-8" ;
38- }
39- const fullPath = resolve ( nitro . options . output . publicDir , id ) ;
40- const assetData = await fsp . readFile ( fullPath ) ;
41- const etag = createEtag ( assetData ) ;
42- const stat = await fsp . stat ( fullPath ) ;
43-
44- const assetId = joinURL (
45- nitro . options . baseURL ,
46- decodeURIComponent ( id )
47- ) ;
4834
49- let encoding ;
50- if ( id . endsWith ( ".gz" ) ) {
51- encoding = "gzip" ;
52- } else if ( id . endsWith ( ".br" ) ) {
53- encoding = "br" ;
54- }
55-
56- assets [ assetId ] = {
57- type : nitro . _prerenderMeta ?. [ assetId ] ?. contentType || mimeType ,
58- encoding,
59- etag,
60- mtime : stat . mtime . toJSON ( ) ,
61- size : stat . size ,
62- path : relative ( nitro . options . output . serverDir , fullPath ) ,
63- data :
64- nitro . options . serveStatic === "inline"
65- ? assetData . toString ( "base64" )
66- : undefined ,
67- } ;
35+ const { errors } = await runParallel (
36+ new Set ( files ) ,
37+ async ( id ) => {
38+ let mimeType =
39+ mime . getType ( id . replace ( / \. ( g z | b r ) $ / , "" ) ) || "text/plain" ;
40+ if ( mimeType . startsWith ( "text" ) ) {
41+ mimeType += "; charset=utf-8" ;
42+ }
43+ const fullPath = resolve ( nitro . options . output . publicDir , id ) ;
44+ const [ assetData , stat ] = await Promise . all ( [
45+ fsp . readFile ( fullPath ) ,
46+ fsp . stat ( fullPath ) ,
47+ ] ) ;
48+
49+ const etag = createEtag ( assetData ) ;
50+
51+ const assetId = joinURL (
52+ nitro . options . baseURL ,
53+ decodeURIComponent ( id )
54+ ) ;
55+
56+ let encoding ;
57+ if ( id . endsWith ( ".gz" ) ) {
58+ encoding = "gzip" ;
59+ } else if ( id . endsWith ( ".br" ) ) {
60+ encoding = "br" ;
61+ }
62+
63+ assets [ assetId ] = {
64+ type : nitro . _prerenderMeta ?. [ assetId ] ?. contentType || mimeType ,
65+ encoding,
66+ etag,
67+ mtime : stat . mtime . toJSON ( ) ,
68+ size : stat . size ,
69+ path : relative ( nitro . options . output . serverDir , fullPath ) ,
70+ data :
71+ nitro . options . serveStatic === "inline"
72+ ? assetData . toString ( "base64" )
73+ : undefined ,
74+ } ;
75+ } ,
76+ { concurrency : 25 }
77+ ) ;
78+
79+ if ( errors . length > 0 ) {
80+ throw new Error (
81+ `Failed to process public assets:\n${ errors . join ( "\n" ) } ` ,
82+ { cause : errors }
83+ ) ;
6884 }
6985
7086 return `export default ${ JSON . stringify ( assets , null , 2 ) } ;` ;
0 commit comments