1
1
const path = require ( 'path' ) ;
2
2
const { createHash } = require ( 'crypto' ) ;
3
- const { readFile, appendFile } = require ( 'fs/promises' ) ;
3
+ const { readFile, writeFile , unlink } = require ( 'fs/promises' ) ;
4
4
const {
5
5
getLogger,
6
6
buildInjectCode,
@@ -36,8 +36,8 @@ const buildCssModulesJs = async ({ fullPath, options, build }) => {
36
36
const bundleConfig = {
37
37
filename : fullPath ,
38
38
code : originCss ,
39
- minify : true ,
40
- sourceMap : ! options . inject ,
39
+ minify : false ,
40
+ sourceMap : true ,
41
41
cssModules : true ,
42
42
analyzeDependencies : false
43
43
} ;
@@ -179,8 +179,10 @@ const onLoadModulesCss = async (build, options, args) => {
179
179
180
180
log ( `loading ${ rpath } ${ args . suffix } ` ) ;
181
181
182
- log ( `checking cache for` , rpath ) ;
183
- const cached = await cache . get ( absPath ) ;
182
+ const useCache = build . initialOptions . watch ;
183
+
184
+ useCache && log ( `checking cache for` , rpath ) ;
185
+ const cached = useCache && ( await cache . get ( absPath ) ) ;
184
186
if ( cached ) {
185
187
log ( 'return build cache for' , rpath ) ;
186
188
return cached ;
@@ -208,8 +210,11 @@ const onLoadModulesCss = async (build, options, args) => {
208
210
contents : js ,
209
211
loader : 'js'
210
212
} ;
211
- await cache . set ( absPath , result , originCss ) ;
212
- log ( `add build result to cache for ${ rpath } ` ) ;
213
+
214
+ if ( useCache ) {
215
+ await cache . set ( absPath , result , originCss ) ;
216
+ log ( `add build result to cache for ${ rpath } ` ) ;
217
+ }
213
218
214
219
return result ;
215
220
} ;
@@ -275,13 +280,82 @@ const onLoadBuiltModulesCss = async ({ pluginData }, build) => {
275
280
* @param {import('esbuild').BuildResult } result
276
281
*/
277
282
const onEnd = async ( build , options , result ) => {
278
- const { buildId, buildRoot, cache } = build . context ;
283
+ const { initialOptions, context, esbuild } = build ;
284
+ const { buildId, buildRoot } = context ;
279
285
const log = getLogger ( build ) ;
280
286
281
- if ( options . inject === true || typeof options . inject === 'string' ) {
287
+ if ( options . inject ) {
288
+ const {
289
+ charset = 'utf8' ,
290
+ outdir,
291
+ sourceRoot,
292
+ sourcemap,
293
+ sourcesContent,
294
+ entryPoints,
295
+ minify,
296
+ logLevel,
297
+ format,
298
+ target,
299
+ external,
300
+ publicPath
301
+ } = initialOptions ;
302
+ const absOutdir = path . isAbsolute ( outdir ) ? outdir : path . resolve ( buildRoot , outdir ) ;
303
+
304
+ const transformCss = async ( css ) => {
305
+ const r = await esbuild . transform ( css , {
306
+ charset,
307
+ loader : 'css' ,
308
+ sourcemap : false ,
309
+ minify : true ,
310
+ logLevel,
311
+ format,
312
+ target
313
+ } ) ;
314
+ return r . code ;
315
+ } ;
316
+
317
+ const buildJs = async ( entryName , entryPath , jsCode ) => {
318
+ const r = ( p ) => `./${ path . relative ( absOutdir , p ) . split ( path . sep ) . join ( path . posix . sep ) } ` ;
319
+ const imports = `import "${ r ( entryPath ) } ";` ;
320
+ if ( ( sourceRoot || publicPath ) && sourcemap ) {
321
+ const sp = sourceRoot || publicPath ;
322
+ const fixedSourceRoot = sp . endsWith ( '/' ) ? sp : sp + '/' ;
323
+ const entryContent = await readFile ( entryPath , { encoding : 'utf8' } ) ;
324
+ await writeFile (
325
+ entryPath ,
326
+ entryContent . replace ( `sourceMappingURL=${ fixedSourceRoot } ` , 'sourceMappingURL=' ) ,
327
+ { encoding : 'utf8' }
328
+ ) ;
329
+ }
330
+ const tmpJsCode = `${ imports } \n${ jsCode } ` ;
331
+ const tmpJsPath = path . resolve ( absOutdir , '.build.inject.js' ) ;
332
+ await writeFile ( tmpJsPath , tmpJsCode , { encoding : 'utf8' } ) ;
333
+ await esbuild . build ( {
334
+ charset,
335
+ absWorkingDir : absOutdir ,
336
+ write : true ,
337
+ allowOverwrite : true ,
338
+ treeShaking : false ,
339
+ logLevel,
340
+ format,
341
+ target,
342
+ minify,
343
+ sourceRoot,
344
+ publicPath,
345
+ sourcemap,
346
+ sourcesContent,
347
+ entryPoints : {
348
+ [ entryName ] : tmpJsPath
349
+ } ,
350
+ outdir : absOutdir ,
351
+ bundle : true ,
352
+ external
353
+ } ) ;
354
+ await unlink ( tmpJsPath ) ;
355
+ } ;
356
+
282
357
const cssContents = [ ] ;
283
358
284
- const { entryPoints } = build . initialOptions ;
285
359
let entriesArray = [ ] ;
286
360
if ( Array . isArray ( entryPoints ) ) {
287
361
entriesArray = [ ...entryPoints ] ;
@@ -296,35 +370,35 @@ const onEnd = async (build, options, result) => {
296
370
297
371
log ( 'entries:' , entries ) ;
298
372
299
- let injectTo = null ;
373
+ let entryToInject = null ;
300
374
const outputs = Object . keys ( result . metafile ?. outputs ?? [ ] ) ;
301
375
302
376
await Promise . all (
303
377
outputs . map ( async ( f ) => {
304
378
if (
305
- ! injectTo &&
379
+ ! entryToInject &&
306
380
result . metafile . outputs [ f ] . entryPoint &&
307
381
entries . includes ( path . resolve ( buildRoot , result . metafile . outputs [ f ] . entryPoint ) ) &&
308
- path . extname ( f ) === '.js'
382
+ [ '.js' , '.mjs' , '.cjs' ] . includes ( path . extname ( f ) )
309
383
) {
310
- injectTo = path . resolve ( buildRoot , f ) ;
384
+ entryToInject = path . resolve ( buildRoot , f ) ;
311
385
}
312
386
if ( path . extname ( f ) === '.css' ) {
313
387
const fullpath = path . resolve ( buildRoot , f ) ;
314
388
const css = await readFile ( fullpath , { encoding : 'utf8' } ) ;
315
- cssContents . push ( `${ css } ` ) ;
389
+ const transformed = await transformCss ( css ) ;
390
+ cssContents . push ( `${ transformed } ` ) ;
316
391
}
317
392
} )
318
393
) ;
319
394
320
- log ( 'inject css to' , path . relative ( buildRoot , injectTo ) ) ;
321
-
322
- if ( injectTo && cssContents . length ) {
323
- const allCss = cssContents . join ( '' ) ;
395
+ if ( entryToInject && cssContents . length ) {
396
+ log ( 'inject css to' , path . relative ( buildRoot , entryToInject ) ) ;
397
+ const entryName = path . basename ( entryToInject , path . extname ( entryToInject ) ) ;
398
+ const allCss = cssContents . join ( '\n ' ) ;
324
399
const container = typeof options . inject === 'string' ? options . inject : 'head' ;
325
400
const injectedCode = buildInjectCode ( container , allCss , buildId , options ) ;
326
-
327
- await appendFile ( injectTo , injectedCode , { encoding : 'utf-8' } ) ;
401
+ await buildJs ( entryName , entryToInject , injectedCode ) ;
328
402
}
329
403
}
330
404
0 commit comments