6
6
'use strict' ;
7
7
8
8
const fs = require ( 'fs' ) ;
9
+ const path = require ( 'path' ) ;
9
10
10
11
const esbuild = require ( 'esbuild' ) ;
11
12
@@ -23,33 +24,63 @@ if (!['build', 'watch'].includes(command)) {
23
24
}
24
25
25
26
/**
27
+ * All of this is dumb but esbuild-plugin-html is limited and paths are hard.
28
+ *
29
+ * FYI If you see a static resource served as HTML, then the express router attempted use
30
+ * a static file, but didnt see it on disk, and instead served the HTML. The problem will probably
31
+ * be in here.
26
32
* @param {esbuild.BuildResult } result
33
+ * @param {esbuild.BuildOptions } buildOptions
27
34
*/
28
- function fixHtmlSubresourceUrls ( result ) {
29
- if ( publicPath !== '/app' ) return ;
35
+ function fixHtmlSubresourceUrls ( result , buildOptions ) {
30
36
if ( ! result . metafile ) throw new Error ( 'expected metafile' ) ;
31
37
32
38
const htmls = Object . keys ( result . metafile . outputs ) . filter ( o => o . endsWith ( '.html' ) ) ;
33
- const html = htmls [ 0 ] ;
39
+ const csss = Object . keys ( result . metafile . outputs ) . filter ( o => o . endsWith ( '.css' ) ) ;
34
40
if ( htmls . length !== 1 ) throw new Error ( 'expected exactly one generated html' ) ;
41
+ if ( csss . length !== 1 ) throw new Error ( 'expected exactly one generated html' ) ;
42
+ const htmlDistPath = htmls [ 0 ] ;
43
+ const cssDistPath = csss [ 0 ] ;
35
44
36
- const htmlText = fs . readFileSync ( html , 'utf-8' ) ;
45
+ // Viewer uses a publicPath of ./, Server uses /app.
46
+ if ( ! buildOptions . outdir || ! buildOptions . publicPath ) {
47
+ throw new Error ( 'missing args' ) ;
48
+ }
49
+ const relativeCssPath = path . relative ( buildOptions . outdir , cssDistPath ) ;
50
+
51
+ // Rewrite the HTML
52
+ const htmlText = fs . readFileSync ( htmlDistPath , 'utf-8' ) ;
37
53
const newHtmlText = htmlText
38
- . replace ( '<script src="chunks/' , '<script src="/app/chunks/' )
39
- . replace ( '<link rel="stylesheet" href="chunks/' , '<link rel="stylesheet" href="/app/chunks/' ) ;
40
- fs . writeFileSync ( html , newHtmlText ) ;
54
+ // Inject publicPath on JS references
55
+ . replace ( '<script src="chunks/' , `<script src="${ buildOptions . publicPath } chunks/` )
56
+ // noop @chialab /esbuild-plugin-html's stupid css loading technique
57
+ . replace ( '<script type="application/javascript">' , '<script type="dumb-dont-run-this">' )
58
+ // ... and instead use a proper stylesheet link. (with a fixed path)
59
+ . replace (
60
+ '</head>' ,
61
+ `
62
+ <link rel="stylesheet" href="${ buildOptions . publicPath } ${ relativeCssPath } ">
63
+ </head>
64
+ `
65
+ ) ;
66
+ fs . writeFileSync ( htmlDistPath , newHtmlText ) ;
67
+
68
+ // Rewrite the CSS, making sure we don't source icons relative to the chunks/css file.
69
+ const newCssText = fs
70
+ . readFileSync ( cssDistPath , 'utf-8' )
71
+ . replaceAll ( `url(./assets` , `url(../assets` ) ;
72
+ fs . writeFileSync ( cssDistPath , newCssText ) ;
41
73
}
42
74
43
75
async function main ( ) {
44
76
const htmlPlugin = ( await import ( '@chialab/esbuild-plugin-html' ) ) . default ;
45
-
46
77
/** @type {esbuild.BuildOptions } */
47
78
const buildOptions = {
48
79
entryPoints : [ entryPoint ] ,
49
80
entryNames : '[name]' ,
50
81
assetNames : 'assets/[name]-[hash]' ,
51
- // Defined chunknames breaks the viewer (probably cuz the -plugin-html), but pairs with fixHtmlSubresourceUrls.
52
- chunkNames : publicPath ? `chunks/[name]-[hash]` : undefined ,
82
+ // See the special handling in fixHtmlSubresourceUrls.
83
+ chunkNames : `chunks/[name]-[hash]` ,
53
84
plugins : [ htmlPlugin ( ) ] ,
54
85
loader : {
55
86
'.svg' : 'file' ,
@@ -70,15 +101,15 @@ async function main() {
70
101
? {
71
102
onRebuild ( err , result ) {
72
103
if ( ! err && result ) {
73
- fixHtmlSubresourceUrls ( result ) ;
104
+ fixHtmlSubresourceUrls ( result , buildOptions ) ;
74
105
}
75
106
} ,
76
107
}
77
108
: undefined ,
78
109
} ;
79
110
80
111
const result = await esbuild . build ( buildOptions ) ;
81
- fixHtmlSubresourceUrls ( result ) ;
112
+ fixHtmlSubresourceUrls ( result , buildOptions ) ;
82
113
83
114
console . log ( 'Built.' , new Date ( ) ) ;
84
115
if ( result . errors . length ) console . error ( result . errors ) ;
0 commit comments