8
8
9
9
import type { Metafile , OutputFile , PluginBuild } from 'esbuild' ;
10
10
import { 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' ;
12
13
import { ComponentStylesheetBundler } from './component-stylesheets' ;
13
14
import {
14
15
JIT_NAMESPACE_REGEXP ,
@@ -34,7 +35,7 @@ async function loadEntry(
34
35
skipRead ?: boolean ,
35
36
) : Promise < { path : string ; contents ?: string } > {
36
37
if ( entry . startsWith ( 'file:' ) ) {
37
- const specifier = path . join ( root , entry . slice ( 5 ) ) ;
38
+ const specifier = join ( root , entry . slice ( 5 ) ) ;
38
39
39
40
return {
40
41
path : specifier ,
@@ -44,7 +45,7 @@ async function loadEntry(
44
45
const [ importer , data ] = entry . slice ( 7 ) . split ( ';' , 2 ) ;
45
46
46
47
return {
47
- path : path . join ( root , importer ) ,
48
+ path : join ( root , importer ) ,
48
49
contents : Buffer . from ( data , 'base64' ) . toString ( ) ,
49
50
} ;
50
51
} else {
@@ -66,6 +67,7 @@ export function setupJitPluginCallbacks(
66
67
stylesheetBundler : ComponentStylesheetBundler ,
67
68
additionalResultFiles : Map < string , { outputFiles ?: OutputFile [ ] ; metafile ?: Metafile } > ,
68
69
inlineStyleLanguage : string ,
70
+ loadCache ?: LoadResultCache ,
69
71
) : void {
70
72
const root = build . initialOptions . absWorkingDir ?? '' ;
71
73
@@ -84,12 +86,12 @@ export function setupJitPluginCallbacks(
84
86
return {
85
87
// Use a relative path to prevent fully resolved paths in the metafile (JSON stats file).
86
88
// 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 ) ) ,
88
90
namespace,
89
91
} ;
90
92
} else {
91
93
// 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 ) ;
93
95
94
96
return {
95
97
path : `inline:${ importer } ;${ specifier } ` ,
@@ -99,45 +101,54 @@ export function setupJitPluginCallbacks(
99
101
} ) ;
100
102
101
103
// 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 } ) ;
106
128
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
+ ) ;
131
138
132
139
// Add a load callback to handle Component templates
133
140
// NOTE: While this callback supports both inline and external templates, the transformer
134
141
// 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 ) ;
137
146
138
- return {
139
- contents,
140
- loader : 'text' ,
141
- } ;
142
- } ) ;
147
+ return {
148
+ contents,
149
+ loader : 'text' ,
150
+ watchFiles : [ path ] ,
151
+ } ;
152
+ } ) ,
153
+ ) ;
143
154
}
0 commit comments