88
99import type { Metafile , OutputFile , PluginBuild } from 'esbuild' ;
1010import { readFile } from 'node:fs/promises' ;
11- import path from 'node:path' ;
11+ import { dirname , join , relative } from 'node:path' ;
12+ import { LoadResultCache , createCachedLoad } from '../load-result-cache' ;
1213import { ComponentStylesheetBundler } from './component-stylesheets' ;
1314import {
1415 JIT_NAMESPACE_REGEXP ,
@@ -34,7 +35,7 @@ async function loadEntry(
3435 skipRead ?: boolean ,
3536) : Promise < { path : string ; contents ?: string } > {
3637 if ( entry . startsWith ( 'file:' ) ) {
37- const specifier = path . join ( root , entry . slice ( 5 ) ) ;
38+ const specifier = join ( root , entry . slice ( 5 ) ) ;
3839
3940 return {
4041 path : specifier ,
@@ -44,7 +45,7 @@ async function loadEntry(
4445 const [ importer , data ] = entry . slice ( 7 ) . split ( ';' , 2 ) ;
4546
4647 return {
47- path : path . join ( root , importer ) ,
48+ path : join ( root , importer ) ,
4849 contents : Buffer . from ( data , 'base64' ) . toString ( ) ,
4950 } ;
5051 } else {
@@ -66,6 +67,7 @@ export function setupJitPluginCallbacks(
6667 stylesheetBundler : ComponentStylesheetBundler ,
6768 additionalResultFiles : Map < string , { outputFiles ?: OutputFile [ ] ; metafile ?: Metafile } > ,
6869 inlineStyleLanguage : string ,
70+ loadCache ?: LoadResultCache ,
6971) : void {
7072 const root = build . initialOptions . absWorkingDir ?? '' ;
7173
@@ -84,12 +86,12 @@ export function setupJitPluginCallbacks(
8486 return {
8587 // Use a relative path to prevent fully resolved paths in the metafile (JSON stats file).
8688 // This is only necessary for custom namespaces. esbuild will handle the file namespace.
87- path : 'file:' + path . relative ( root , path . join ( path . dirname ( args . importer ) , specifier ) ) ,
89+ path : 'file:' + relative ( root , join ( dirname ( args . importer ) , specifier ) ) ,
8890 namespace,
8991 } ;
9092 } else {
9193 // Inline data may need the importer to resolve imports/references within the content
92- const importer = path . relative ( root , args . importer ) ;
94+ const importer = relative ( root , args . importer ) ;
9395
9496 return {
9597 path : `inline:${ importer } ;${ specifier } ` ,
@@ -99,45 +101,54 @@ export function setupJitPluginCallbacks(
99101 } ) ;
100102
101103 // Add a load callback to handle Component stylesheets (both inline and external)
102- build . onLoad ( { filter : / ./ , namespace : JIT_STYLE_NAMESPACE } , async ( args ) => {
103- // skipRead is used here because the stylesheet bundling will read a file stylesheet
104- // directly either via a preprocessor or esbuild itself.
105- const entry = await loadEntry ( args . path , root , true /* skipRead */ ) ;
104+ build . onLoad (
105+ { filter : / ./ , namespace : JIT_STYLE_NAMESPACE } ,
106+ createCachedLoad ( loadCache , async ( args ) => {
107+ // skipRead is used here because the stylesheet bundling will read a file stylesheet
108+ // directly either via a preprocessor or esbuild itself.
109+ const entry = await loadEntry ( args . path , root , true /* skipRead */ ) ;
110+
111+ let stylesheetResult ;
112+
113+ // Stylesheet contents only exist for internal stylesheets
114+ if ( entry . contents === undefined ) {
115+ stylesheetResult = await stylesheetBundler . bundleFile ( entry . path ) ;
116+ } else {
117+ stylesheetResult = await stylesheetBundler . bundleInline (
118+ entry . contents ,
119+ entry . path ,
120+ inlineStyleLanguage ,
121+ ) ;
122+ }
123+
124+ const { contents, resourceFiles, errors, warnings, metafile, referencedFiles } =
125+ stylesheetResult ;
126+
127+ additionalResultFiles . set ( entry . path , { outputFiles : resourceFiles , metafile } ) ;
106128
107- let stylesheetResult ;
108-
109- // Stylesheet contents only exist for internal stylesheets
110- if ( entry . contents === undefined ) {
111- stylesheetResult = await stylesheetBundler . bundleFile ( entry . path ) ;
112- } else {
113- stylesheetResult = await stylesheetBundler . bundleInline (
114- entry . contents ,
115- entry . path ,
116- inlineStyleLanguage ,
117- ) ;
118- }
119-
120- const { contents, resourceFiles, errors, warnings, metafile } = stylesheetResult ;
121-
122- additionalResultFiles . set ( entry . path , { outputFiles : resourceFiles , metafile } ) ;
123-
124- return {
125- errors,
126- warnings,
127- contents,
128- loader : 'text' ,
129- } ;
130- } ) ;
129+ return {
130+ errors,
131+ warnings,
132+ contents,
133+ loader : 'text' ,
134+ watchFiles : referencedFiles && [ ...referencedFiles ] ,
135+ } ;
136+ } ) ,
137+ ) ;
131138
132139 // Add a load callback to handle Component templates
133140 // NOTE: While this callback supports both inline and external templates, the transformer
134141 // currently only supports generating URIs for external templates.
135- build . onLoad ( { filter : / ./ , namespace : JIT_TEMPLATE_NAMESPACE } , async ( args ) => {
136- const { contents } = await loadEntry ( args . path , root ) ;
142+ build . onLoad (
143+ { filter : / ./ , namespace : JIT_TEMPLATE_NAMESPACE } ,
144+ createCachedLoad ( loadCache , async ( args ) => {
145+ const { contents, path } = await loadEntry ( args . path , root ) ;
137146
138- return {
139- contents,
140- loader : 'text' ,
141- } ;
142- } ) ;
147+ return {
148+ contents,
149+ loader : 'text' ,
150+ watchFiles : [ path ] ,
151+ } ;
152+ } ) ,
153+ ) ;
143154}
0 commit comments