html-bundle 5.4.15 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{esm → dist}/bundle.js +32 -22
- package/package.json +19 -19
- package/src/bundle.ts +37 -24
- package/tsconfig.json +1 -1
- package/cjs/bundle.js +0 -681
- package/tsconfig.cjs.json +0 -16
package/{esm → dist}/bundle.js
RENAMED
|
@@ -34,32 +34,21 @@ else {
|
|
|
34
34
|
// Performance Observer and file watcher
|
|
35
35
|
const globHTML = new Event.EventEmitter();
|
|
36
36
|
const taskEmitter = new Event.EventEmitter();
|
|
37
|
-
|
|
37
|
+
let start = performance.now();
|
|
38
|
+
let addedHMR = false;
|
|
38
39
|
let expectedTasks = 0; // This will be increased in globHandlers
|
|
39
40
|
let finishedTasks = 0; // Current status
|
|
40
41
|
taskEmitter.on("done", () => {
|
|
41
42
|
finishedTasks++;
|
|
42
43
|
if (finishedTasks === expectedTasks) {
|
|
43
44
|
console.log(`🚀 Build finished in ${(performance.now() - start).toFixed(2)}ms ✨`);
|
|
44
|
-
if (isHMR) {
|
|
45
|
+
if (isHMR && !addedHMR) {
|
|
46
|
+
addedHMR = true;
|
|
45
47
|
if (file) {
|
|
46
48
|
const postCSSWatcher = watch(file);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
plugins = newConfig.plugins;
|
|
51
|
-
options = newConfig.options;
|
|
52
|
-
CSSprocessor = postcss(plugins);
|
|
53
|
-
glob(`${SOURCE_FOLDER}/**/*.css`, {}, (err, files) => {
|
|
54
|
-
errorHandler(err);
|
|
55
|
-
expectedTasks += files.length;
|
|
56
|
-
for (const filename of files) {
|
|
57
|
-
const [buildFilename, buildPathDir] = getBuildNames(filename);
|
|
58
|
-
fs.mkdirSync(buildPathDir, { recursive: true });
|
|
59
|
-
minifyCSS(filename, buildFilename);
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
});
|
|
49
|
+
const tailwindCSSWatcher = watch(file.replace("postcss", "tailwind"));
|
|
50
|
+
postCSSWatcher.on("change", () => rebuildCSS("postcss"));
|
|
51
|
+
tailwindCSSWatcher.on("change", () => rebuildCSS("tailwind"));
|
|
63
52
|
}
|
|
64
53
|
console.log(`⌛ Waiting for file changes ...`);
|
|
65
54
|
const watcher = watch(SOURCE_FOLDER);
|
|
@@ -67,6 +56,7 @@ else {
|
|
|
67
56
|
let initialAdd = 0;
|
|
68
57
|
let hasJSTS = false;
|
|
69
58
|
watcher.on("add", (filename) => {
|
|
59
|
+
start = performance.now();
|
|
70
60
|
// Return if it was added by the build system itself
|
|
71
61
|
if (/-bundle-\d+\.(j|t)sx?$/.test(filename)) {
|
|
72
62
|
return;
|
|
@@ -89,6 +79,7 @@ else {
|
|
|
89
79
|
});
|
|
90
80
|
});
|
|
91
81
|
watcher.on("change", (filename) => {
|
|
82
|
+
start = performance.now();
|
|
92
83
|
// Return if it was changed by the build system itself
|
|
93
84
|
if (/-bundle-\d+\.(j|t)sx?$/.test(filename)) {
|
|
94
85
|
return;
|
|
@@ -99,6 +90,7 @@ else {
|
|
|
99
90
|
console.log(`⚡ modified ${buildFilename}`);
|
|
100
91
|
});
|
|
101
92
|
watcher.on("unlink", (filename) => {
|
|
93
|
+
start = performance.now();
|
|
102
94
|
// Return if it was deleted by the build system itself
|
|
103
95
|
if (/-bundle-\d+\.(j|t)sx?$/.test(filename)) {
|
|
104
96
|
return;
|
|
@@ -117,6 +109,23 @@ else {
|
|
|
117
109
|
}
|
|
118
110
|
}
|
|
119
111
|
});
|
|
112
|
+
function rebuildCSS(config) {
|
|
113
|
+
start = performance.now();
|
|
114
|
+
console.log(`⚡ modified ${config}.config – CSS will rebuild now.`);
|
|
115
|
+
const newConfig = createPostCSSConfig();
|
|
116
|
+
plugins = newConfig.plugins;
|
|
117
|
+
options = newConfig.options;
|
|
118
|
+
CSSprocessor = postcss(plugins);
|
|
119
|
+
glob(`${SOURCE_FOLDER}/**/*.css`, {}, (err, files) => {
|
|
120
|
+
errorHandler(err);
|
|
121
|
+
expectedTasks += files.length;
|
|
122
|
+
for (const filename of files) {
|
|
123
|
+
const [buildFilename, buildPathDir] = getBuildNames(filename);
|
|
124
|
+
fs.mkdirSync(buildPathDir, { recursive: true });
|
|
125
|
+
minifyCSS(filename, buildFilename);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
120
129
|
// Basic configuration
|
|
121
130
|
const SOURCE_FOLDER = "src";
|
|
122
131
|
const BUILD_FOLDER = "build";
|
|
@@ -258,7 +267,7 @@ else {
|
|
|
258
267
|
if (!isInline) {
|
|
259
268
|
taskEmitter.emit("done");
|
|
260
269
|
globHTML.emit("getReady");
|
|
261
|
-
if (serverSentEvents) {
|
|
270
|
+
if (serverSentEvents && file) {
|
|
262
271
|
const changedFile = tsMaybeX2JS(file);
|
|
263
272
|
const [buildFilename] = getBuildNames(changedFile);
|
|
264
273
|
const js = fs.readFileSync(buildFilename, { encoding: "utf8" });
|
|
@@ -339,7 +348,7 @@ else {
|
|
|
339
348
|
}
|
|
340
349
|
fileText = serialize(DOM);
|
|
341
350
|
// Minify HTML
|
|
342
|
-
fileText = minify(fileText, {
|
|
351
|
+
fileText = await minify(fileText, {
|
|
343
352
|
collapseWhitespace: true,
|
|
344
353
|
removeComments: true,
|
|
345
354
|
});
|
|
@@ -353,7 +362,6 @@ else {
|
|
|
353
362
|
base: buildDir,
|
|
354
363
|
html: fileText,
|
|
355
364
|
target: fileWithBase,
|
|
356
|
-
minify: true,
|
|
357
365
|
inline: !isCSP,
|
|
358
366
|
extract: true,
|
|
359
367
|
rebase: () => { },
|
|
@@ -488,7 +496,9 @@ if (!window.eventsource${id}) {
|
|
|
488
496
|
}
|
|
489
497
|
}
|
|
490
498
|
setInsertDiffing(false);
|
|
491
|
-
|
|
499
|
+
if (dataObj.filename === 'build/index.html') {
|
|
500
|
+
dispatchEvent(new Event("popstate"));
|
|
501
|
+
}
|
|
492
502
|
} else if ("css" in dataObj) {
|
|
493
503
|
window.onceEveryXTime(100, window.updateCSS, [updateAttr]);
|
|
494
504
|
} else if ("js" in dataObj) {
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "html-bundle",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.5.0",
|
|
4
4
|
"description": "A very simple bundler for HTML SFC",
|
|
5
|
-
"bin": "./
|
|
5
|
+
"bin": "./dist/bundle.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"start": "tsc
|
|
7
|
+
"start": "tsc",
|
|
8
8
|
"update": "npx npm-check-updates -u && npx typesync && npm i && npm outdated"
|
|
9
9
|
},
|
|
10
10
|
"keywords": [
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
"author": "Fabian Krutsch <f.krutsch@gmx.de> (https://krutsch.netlify.app/)",
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@types/cssnano": "^4.0.
|
|
22
|
-
"@types/glob": "^7.
|
|
23
|
-
"@types/html-minifier-terser": "^
|
|
24
|
-
"@types/parse5": "^6.0.
|
|
21
|
+
"@types/cssnano": "^4.0.1",
|
|
22
|
+
"@types/glob": "^7.2.0",
|
|
23
|
+
"@types/html-minifier-terser": "^6.1.0",
|
|
24
|
+
"@types/parse5": "^6.0.3",
|
|
25
25
|
"@types/postcss-load-config": "^3.0.1",
|
|
26
|
-
"typescript": "^4.
|
|
26
|
+
"typescript": "^4.5.4"
|
|
27
27
|
},
|
|
28
28
|
"repository": {
|
|
29
29
|
"type": "git",
|
|
@@ -31,17 +31,17 @@
|
|
|
31
31
|
},
|
|
32
32
|
"bugs": "https://github.com/Krutsch/html-bundle/issues",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@web/parse5-utils": "^1.
|
|
35
|
-
"chokidar": "^3.5.
|
|
36
|
-
"critical": "^
|
|
37
|
-
"cssnano": "^5.0.
|
|
38
|
-
"esbuild": "^0.
|
|
39
|
-
"fastify": "^3.
|
|
40
|
-
"fastify-static": "^4.
|
|
41
|
-
"glob": "^7.
|
|
42
|
-
"html-minifier-terser": "^
|
|
34
|
+
"@web/parse5-utils": "^1.3.0",
|
|
35
|
+
"chokidar": "^3.5.2",
|
|
36
|
+
"critical": "^4.0.1",
|
|
37
|
+
"cssnano": "^5.0.14",
|
|
38
|
+
"esbuild": "^0.14.8",
|
|
39
|
+
"fastify": "^3.25.2",
|
|
40
|
+
"fastify-static": "^4.5.0",
|
|
41
|
+
"glob": "^7.2.0",
|
|
42
|
+
"html-minifier-terser": "^6.1.0",
|
|
43
43
|
"parse5": "^6.0.1",
|
|
44
|
-
"postcss": "^8.
|
|
45
|
-
"postcss-load-config": "^3.0
|
|
44
|
+
"postcss": "^8.4.5",
|
|
45
|
+
"postcss-load-config": "^3.1.0"
|
|
46
46
|
}
|
|
47
47
|
}
|
package/src/bundle.ts
CHANGED
|
@@ -49,7 +49,8 @@ if (isServeOnly) {
|
|
|
49
49
|
// Performance Observer and file watcher
|
|
50
50
|
const globHTML = new Event.EventEmitter();
|
|
51
51
|
const taskEmitter = new Event.EventEmitter();
|
|
52
|
-
|
|
52
|
+
let start = performance.now();
|
|
53
|
+
let addedHMR = false;
|
|
53
54
|
let expectedTasks = 0; // This will be increased in globHandlers
|
|
54
55
|
let finishedTasks = 0; // Current status
|
|
55
56
|
taskEmitter.on("done", () => {
|
|
@@ -60,26 +61,13 @@ if (isServeOnly) {
|
|
|
60
61
|
`🚀 Build finished in ${(performance.now() - start).toFixed(2)}ms ✨`
|
|
61
62
|
);
|
|
62
63
|
|
|
63
|
-
if (isHMR) {
|
|
64
|
+
if (isHMR && !addedHMR) {
|
|
65
|
+
addedHMR = true;
|
|
64
66
|
if (file) {
|
|
65
67
|
const postCSSWatcher = watch(file);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
plugins = newConfig.plugins;
|
|
70
|
-
options = newConfig.options;
|
|
71
|
-
CSSprocessor = postcss(plugins as AcceptedPlugin[]);
|
|
72
|
-
|
|
73
|
-
glob(`${SOURCE_FOLDER}/**/*.css`, {}, (err, files) => {
|
|
74
|
-
errorHandler(err);
|
|
75
|
-
expectedTasks += files.length;
|
|
76
|
-
for (const filename of files) {
|
|
77
|
-
const [buildFilename, buildPathDir] = getBuildNames(filename);
|
|
78
|
-
fs.mkdirSync(buildPathDir, { recursive: true });
|
|
79
|
-
minifyCSS(filename, buildFilename);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
});
|
|
68
|
+
const tailwindCSSWatcher = watch(file.replace("postcss", "tailwind"));
|
|
69
|
+
postCSSWatcher.on("change", () => rebuildCSS("postcss"));
|
|
70
|
+
tailwindCSSWatcher.on("change", () => rebuildCSS("tailwind"));
|
|
83
71
|
}
|
|
84
72
|
|
|
85
73
|
console.log(`⌛ Waiting for file changes ...`);
|
|
@@ -89,6 +77,8 @@ if (isServeOnly) {
|
|
|
89
77
|
let hasJSTS = false;
|
|
90
78
|
|
|
91
79
|
watcher.on("add", (filename) => {
|
|
80
|
+
start = performance.now();
|
|
81
|
+
rebuildCSS();
|
|
92
82
|
// Return if it was added by the build system itself
|
|
93
83
|
if (/-bundle-\d+\.(j|t)sx?$/.test(filename)) {
|
|
94
84
|
return;
|
|
@@ -112,6 +102,8 @@ if (isServeOnly) {
|
|
|
112
102
|
});
|
|
113
103
|
});
|
|
114
104
|
watcher.on("change", (filename) => {
|
|
105
|
+
start = performance.now();
|
|
106
|
+
rebuildCSS();
|
|
115
107
|
// Return if it was changed by the build system itself
|
|
116
108
|
if (/-bundle-\d+\.(j|t)sx?$/.test(filename)) {
|
|
117
109
|
return;
|
|
@@ -123,6 +115,7 @@ if (isServeOnly) {
|
|
|
123
115
|
console.log(`⚡ modified ${buildFilename}`);
|
|
124
116
|
});
|
|
125
117
|
watcher.on("unlink", (filename) => {
|
|
118
|
+
start = performance.now();
|
|
126
119
|
// Return if it was deleted by the build system itself
|
|
127
120
|
if (/-bundle-\d+\.(j|t)sx?$/.test(filename)) {
|
|
128
121
|
return;
|
|
@@ -143,6 +136,25 @@ if (isServeOnly) {
|
|
|
143
136
|
}
|
|
144
137
|
});
|
|
145
138
|
|
|
139
|
+
function rebuildCSS(config?: string) {
|
|
140
|
+
start = performance.now();
|
|
141
|
+
if (config)
|
|
142
|
+
console.log(`⚡ modified ${config}.config – CSS will rebuild now.`);
|
|
143
|
+
const newConfig = createPostCSSConfig();
|
|
144
|
+
plugins = newConfig.plugins;
|
|
145
|
+
options = newConfig.options;
|
|
146
|
+
CSSprocessor = postcss(plugins as AcceptedPlugin[]);
|
|
147
|
+
glob(`${SOURCE_FOLDER}/**/*.css`, {}, (err, files) => {
|
|
148
|
+
errorHandler(err);
|
|
149
|
+
expectedTasks += files.length;
|
|
150
|
+
for (const filename of files) {
|
|
151
|
+
const [buildFilename, buildPathDir] = getBuildNames(filename);
|
|
152
|
+
fs.mkdirSync(buildPathDir, { recursive: true });
|
|
153
|
+
minifyCSS(filename, buildFilename);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
146
158
|
// Basic configuration
|
|
147
159
|
const SOURCE_FOLDER = "src";
|
|
148
160
|
const BUILD_FOLDER = "build";
|
|
@@ -318,8 +330,8 @@ if (isServeOnly) {
|
|
|
318
330
|
taskEmitter.emit("done");
|
|
319
331
|
globHTML.emit("getReady");
|
|
320
332
|
|
|
321
|
-
if (serverSentEvents) {
|
|
322
|
-
const changedFile = tsMaybeX2JS(file
|
|
333
|
+
if (serverSentEvents && file) {
|
|
334
|
+
const changedFile = tsMaybeX2JS(file);
|
|
323
335
|
const [buildFilename] = getBuildNames(changedFile);
|
|
324
336
|
const js = fs.readFileSync(buildFilename, { encoding: "utf8" });
|
|
325
337
|
serverSentEvents({
|
|
@@ -411,7 +423,7 @@ if (isServeOnly) {
|
|
|
411
423
|
fileText = serialize(DOM);
|
|
412
424
|
|
|
413
425
|
// Minify HTML
|
|
414
|
-
fileText = minify(fileText, {
|
|
426
|
+
fileText = await minify(fileText, {
|
|
415
427
|
collapseWhitespace: true,
|
|
416
428
|
removeComments: true,
|
|
417
429
|
});
|
|
@@ -427,7 +439,6 @@ if (isServeOnly) {
|
|
|
427
439
|
base: buildDir,
|
|
428
440
|
html: fileText,
|
|
429
441
|
target: fileWithBase,
|
|
430
|
-
minify: true,
|
|
431
442
|
inline: !isCSP,
|
|
432
443
|
extract: true,
|
|
433
444
|
rebase: () => {},
|
|
@@ -576,7 +587,9 @@ if (!window.eventsource${id}) {
|
|
|
576
587
|
}
|
|
577
588
|
}
|
|
578
589
|
setInsertDiffing(false);
|
|
579
|
-
|
|
590
|
+
if (dataObj.filename === 'build/index.html') {
|
|
591
|
+
dispatchEvent(new Event("popstate"));
|
|
592
|
+
}
|
|
580
593
|
} else if ("css" in dataObj) {
|
|
581
594
|
window.onceEveryXTime(100, window.updateCSS, [updateAttr]);
|
|
582
595
|
} else if ("js" in dataObj) {
|
package/tsconfig.json
CHANGED
package/cjs/bundle.js
DELETED
|
@@ -1,681 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
var __importDefault =
|
|
4
|
-
(this && this.__importDefault) ||
|
|
5
|
-
function (mod) {
|
|
6
|
-
return mod && mod.__esModule ? mod : { default: mod };
|
|
7
|
-
};
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
const fs_1 = __importDefault(require("fs"));
|
|
10
|
-
const perf_hooks_1 = require("perf_hooks");
|
|
11
|
-
const events_1 = __importDefault(require("events"));
|
|
12
|
-
const glob_1 = __importDefault(require("glob"));
|
|
13
|
-
const path_1 = __importDefault(require("path"));
|
|
14
|
-
const fastify_1 = __importDefault(require("fastify"));
|
|
15
|
-
const fastify_static_1 = __importDefault(require("fastify-static"));
|
|
16
|
-
const postcss_1 = __importDefault(require("postcss"));
|
|
17
|
-
const postcss_load_config_1 = __importDefault(require("postcss-load-config"));
|
|
18
|
-
const cssnano_1 = __importDefault(require("cssnano"));
|
|
19
|
-
const esbuild_1 = __importDefault(require("esbuild"));
|
|
20
|
-
const critical_1 = __importDefault(require("critical"));
|
|
21
|
-
const html_minifier_terser_1 = require("html-minifier-terser");
|
|
22
|
-
const chokidar_1 = require("chokidar");
|
|
23
|
-
const parse5_1 = require("parse5");
|
|
24
|
-
const parse5_utils_1 = require("@web/parse5-utils");
|
|
25
|
-
// CLI and options
|
|
26
|
-
const isCritical = process.argv.includes("--critical");
|
|
27
|
-
const isHMR = process.argv.includes("--hmr");
|
|
28
|
-
const isCSP = process.argv.includes("--csp");
|
|
29
|
-
const isSecure = process.argv.includes("--secure");
|
|
30
|
-
const isServeOnly = process.argv.includes("--serveOnly");
|
|
31
|
-
let fastify;
|
|
32
|
-
if (isServeOnly) {
|
|
33
|
-
createDefaultServer();
|
|
34
|
-
fastify.listen(5000);
|
|
35
|
-
console.log(`💻 Sever listening on port 5000.`);
|
|
36
|
-
} else {
|
|
37
|
-
process.env.NODE_ENV = isHMR ? "development" : "production";
|
|
38
|
-
let { plugins, options, file } = createPostCSSConfig();
|
|
39
|
-
let CSSprocessor = postcss_1.default(plugins);
|
|
40
|
-
// Performance Observer and file watcher
|
|
41
|
-
const globHTML = new events_1.default.EventEmitter();
|
|
42
|
-
const taskEmitter = new events_1.default.EventEmitter();
|
|
43
|
-
const start = perf_hooks_1.performance.now();
|
|
44
|
-
let expectedTasks = 0; // This will be increased in globHandlers
|
|
45
|
-
let finishedTasks = 0; // Current status
|
|
46
|
-
taskEmitter.on("done", () => {
|
|
47
|
-
finishedTasks++;
|
|
48
|
-
if (finishedTasks === expectedTasks) {
|
|
49
|
-
console.log(
|
|
50
|
-
`🚀 Build finished in ${(
|
|
51
|
-
perf_hooks_1.performance.now() - start
|
|
52
|
-
).toFixed(2)}ms ✨`
|
|
53
|
-
);
|
|
54
|
-
if (isHMR) {
|
|
55
|
-
if (file) {
|
|
56
|
-
const postCSSWatcher = chokidar_1.watch(file);
|
|
57
|
-
postCSSWatcher.on("change", () => {
|
|
58
|
-
console.log("⚡ modified postcss.config – CSS will rebuild now.");
|
|
59
|
-
const newConfig = createPostCSSConfig();
|
|
60
|
-
plugins = newConfig.plugins;
|
|
61
|
-
options = newConfig.options;
|
|
62
|
-
CSSprocessor = postcss_1.default(plugins);
|
|
63
|
-
glob_1.default(`${SOURCE_FOLDER}/**/*.css`, {}, (err, files) => {
|
|
64
|
-
errorHandler(err);
|
|
65
|
-
expectedTasks += files.length;
|
|
66
|
-
for (const filename of files) {
|
|
67
|
-
const [buildFilename, buildPathDir] = getBuildNames(filename);
|
|
68
|
-
fs_1.default.mkdirSync(buildPathDir, { recursive: true });
|
|
69
|
-
minifyCSS(filename, buildFilename);
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
console.log(`⌛ Waiting for file changes ...`);
|
|
75
|
-
const watcher = chokidar_1.watch(SOURCE_FOLDER);
|
|
76
|
-
// The add watcher will add all the files initially - do not rebuild them
|
|
77
|
-
let initialAdd = 0;
|
|
78
|
-
let hasJSTS = false;
|
|
79
|
-
watcher.on("add", (filename) => {
|
|
80
|
-
// Return if it was added by the build system itself
|
|
81
|
-
if (/-bundle-\d+\.(j|t)sx?$/.test(filename)) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
filename = String.raw`${filename}`.replace(/\\/g, "/");
|
|
85
|
-
if (filename.endsWith(".html") || filename.endsWith(".css")) {
|
|
86
|
-
initialAdd++;
|
|
87
|
-
} else if (hasJSTS === false && /\.(j|t)sx?$/.test(filename)) {
|
|
88
|
-
hasJSTS = true;
|
|
89
|
-
initialAdd++;
|
|
90
|
-
}
|
|
91
|
-
if (initialAdd <= expectedTasks) return;
|
|
92
|
-
const [buildFilename, buildPathDir] = getBuildNames(filename);
|
|
93
|
-
fs_1.default.mkdir(buildPathDir, { recursive: true }, (err) => {
|
|
94
|
-
errorHandler(err);
|
|
95
|
-
rebuild(filename);
|
|
96
|
-
console.log(`⚡ added ${buildFilename}`);
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
watcher.on("change", (filename) => {
|
|
100
|
-
// Return if it was changed by the build system itself
|
|
101
|
-
if (/-bundle-\d+\.(j|t)sx?$/.test(filename)) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
filename = String.raw`${filename}`.replace(/\\/g, "/");
|
|
105
|
-
rebuild(filename);
|
|
106
|
-
const [buildFilename] = getBuildNames(filename);
|
|
107
|
-
console.log(`⚡ modified ${buildFilename}`);
|
|
108
|
-
});
|
|
109
|
-
watcher.on("unlink", (filename) => {
|
|
110
|
-
// Return if it was deleted by the build system itself
|
|
111
|
-
if (/-bundle-\d+\.(j|t)sx?$/.test(filename)) {
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
filename = String.raw`${filename}`.replace(/\\/g, "/");
|
|
115
|
-
JSTSFiles.delete(filename);
|
|
116
|
-
const [buildFilename, buildPathDir] = getBuildNames(filename);
|
|
117
|
-
fs_1.default.rm(tsMaybeX2JS(buildFilename), (err) => {
|
|
118
|
-
errorHandler(err);
|
|
119
|
-
console.log(`⚡ deleted ${buildFilename}`);
|
|
120
|
-
const length = fs_1.default.readdirSync(buildPathDir).length;
|
|
121
|
-
if (!length) fs_1.default.rmdir(buildPathDir, errorHandler);
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
// Basic configuration
|
|
128
|
-
const SOURCE_FOLDER = "src";
|
|
129
|
-
const BUILD_FOLDER = "build";
|
|
130
|
-
const TEMPLATE_LITERAL_MINIFIER = /\n\s+/g;
|
|
131
|
-
const CONNECTIONS = []; // HMR
|
|
132
|
-
let htmlTasks = 0;
|
|
133
|
-
let serverSentEvents;
|
|
134
|
-
if (isHMR) {
|
|
135
|
-
fastify = fastify_1.default(
|
|
136
|
-
isSecure
|
|
137
|
-
? {
|
|
138
|
-
http2: true,
|
|
139
|
-
https: {
|
|
140
|
-
key: fs_1.default.readFileSync(
|
|
141
|
-
path_1.default.join(process.cwd(), "localhost-key.pem")
|
|
142
|
-
),
|
|
143
|
-
cert: fs_1.default.readFileSync(
|
|
144
|
-
path_1.default.join(process.cwd(), "localhost.pem")
|
|
145
|
-
),
|
|
146
|
-
},
|
|
147
|
-
}
|
|
148
|
-
: void 0
|
|
149
|
-
);
|
|
150
|
-
fastify.setNotFoundHandler((_req, reply) => {
|
|
151
|
-
const file = fs_1.default.readFileSync(
|
|
152
|
-
path_1.default.join(process.cwd(), BUILD_FOLDER, "/index.html"),
|
|
153
|
-
{
|
|
154
|
-
encoding: "utf-8",
|
|
155
|
-
}
|
|
156
|
-
);
|
|
157
|
-
reply.header("Content-Type", "text/html; charset=UTF-8");
|
|
158
|
-
return reply.send(addHMRCode(file, "build/index.html"));
|
|
159
|
-
});
|
|
160
|
-
fastify.register(fastify_static_1.default, {
|
|
161
|
-
root: path_1.default.join(process.cwd(), BUILD_FOLDER),
|
|
162
|
-
});
|
|
163
|
-
fastify.get("/events", (_req, reply) => {
|
|
164
|
-
reply.raw.setHeader("Content-Type", "text/event-stream");
|
|
165
|
-
reply.raw.setHeader("Cache-Control", "no-cache");
|
|
166
|
-
!isSecure && reply.raw.setHeader("Connection", "keep-alive");
|
|
167
|
-
CONNECTIONS.push(reply.raw);
|
|
168
|
-
serverSentEvents = (data) =>
|
|
169
|
-
CONNECTIONS.forEach((rep) => {
|
|
170
|
-
rep.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
// THE BUNDLE CODE
|
|
175
|
-
// Glob all files and transform the code
|
|
176
|
-
glob_1.default(`${SOURCE_FOLDER}/**/*.html`, {}, (err, files) => {
|
|
177
|
-
errorHandler(err);
|
|
178
|
-
expectedTasks += files.length;
|
|
179
|
-
htmlTasks += files.length;
|
|
180
|
-
if (isHMR) {
|
|
181
|
-
createHMRHandlers(files);
|
|
182
|
-
fastify.listen(5000);
|
|
183
|
-
console.log(`💻 Sever listening on port 5000.`);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
glob_1.default(`${SOURCE_FOLDER}/**/*.css`, {}, (err, files) => {
|
|
187
|
-
errorHandler(err);
|
|
188
|
-
expectedTasks += files.length;
|
|
189
|
-
for (const filename of files) {
|
|
190
|
-
const [buildFilename, buildPathDir] = getBuildNames(filename);
|
|
191
|
-
fs_1.default.mkdirSync(buildPathDir, { recursive: true });
|
|
192
|
-
minifyCSS(filename, buildFilename);
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
const JSTSFiles = new Set();
|
|
196
|
-
glob_1.default(
|
|
197
|
-
`${SOURCE_FOLDER}/**/!(*.d).{ts,js,tsx,jsx}`,
|
|
198
|
-
{},
|
|
199
|
-
(err, files) => {
|
|
200
|
-
errorHandler(err);
|
|
201
|
-
if (files.length) {
|
|
202
|
-
expectedTasks += 1;
|
|
203
|
-
} else {
|
|
204
|
-
globHTML.emit("getReady");
|
|
205
|
-
}
|
|
206
|
-
files.forEach((file) => JSTSFiles.add(file));
|
|
207
|
-
minifyTSJS().catch(errorHandler);
|
|
208
|
-
}
|
|
209
|
-
);
|
|
210
|
-
globHTML.on("getReady", () => {
|
|
211
|
-
if (expectedTasks - htmlTasks === finishedTasks) {
|
|
212
|
-
// After CSS and JS because critical needs file built css files and inline script might reference js files.
|
|
213
|
-
glob_1.default(`${SOURCE_FOLDER}/**/*.html`, {}, async (err, files) => {
|
|
214
|
-
errorHandler(err);
|
|
215
|
-
await createGlobalJS(files);
|
|
216
|
-
files.forEach((filename) => {
|
|
217
|
-
const [buildFilename, buildPathDir] = getBuildNames(filename);
|
|
218
|
-
fs_1.default.mkdirSync(buildPathDir, { recursive: true });
|
|
219
|
-
minifyHTML(filename, buildFilename);
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
function createGlobalJS(files) {
|
|
225
|
-
const scriptFilenames = [];
|
|
226
|
-
files.forEach((filename) => {
|
|
227
|
-
const fileText = fs_1.default.readFileSync(filename, {
|
|
228
|
-
encoding: "utf-8",
|
|
229
|
-
});
|
|
230
|
-
let DOM;
|
|
231
|
-
if (fileText.includes("<!DOCTYPE html>") || fileText.includes("<html")) {
|
|
232
|
-
DOM = parse5_1.parse(fileText);
|
|
233
|
-
} else {
|
|
234
|
-
DOM = parse5_1.parseFragment(fileText);
|
|
235
|
-
}
|
|
236
|
-
const scripts = parse5_utils_1.findElements(
|
|
237
|
-
DOM,
|
|
238
|
-
(e) => parse5_utils_1.getTagName(e) === "script"
|
|
239
|
-
);
|
|
240
|
-
scripts.forEach((script, index) => {
|
|
241
|
-
const scriptTextNode = script.childNodes[0];
|
|
242
|
-
const isReferencedScript = script.attrs.find((a) => a.name === "src");
|
|
243
|
-
//@ts-ignore
|
|
244
|
-
const scriptContent =
|
|
245
|
-
scriptTextNode === null || scriptTextNode === void 0
|
|
246
|
-
? void 0
|
|
247
|
-
: scriptTextNode.value;
|
|
248
|
-
if (!scriptContent || isReferencedScript) return;
|
|
249
|
-
const jsFilename = filename.replace(".html", `-bundle-${index}.js`);
|
|
250
|
-
scriptFilenames.push(jsFilename);
|
|
251
|
-
fs_1.default.writeFileSync(jsFilename, scriptContent);
|
|
252
|
-
});
|
|
253
|
-
});
|
|
254
|
-
scriptFilenames.forEach((file) => JSTSFiles.add(file));
|
|
255
|
-
return minifyTSJS(true)
|
|
256
|
-
.catch(console.error)
|
|
257
|
-
.finally(() =>
|
|
258
|
-
scriptFilenames.forEach((file) => {
|
|
259
|
-
JSTSFiles.delete(file);
|
|
260
|
-
try {
|
|
261
|
-
fs_1.default.rmSync(file);
|
|
262
|
-
} catch (_a) {}
|
|
263
|
-
})
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
function minifyTSJS(isInline = false, file) {
|
|
267
|
-
return esbuild_1
|
|
268
|
-
.build({
|
|
269
|
-
entryPoints: Array.from(JSTSFiles),
|
|
270
|
-
charset: "utf8",
|
|
271
|
-
format: "esm",
|
|
272
|
-
incremental: isHMR,
|
|
273
|
-
sourcemap: isHMR,
|
|
274
|
-
splitting: true,
|
|
275
|
-
define: {
|
|
276
|
-
"process.env.NODE_ENV": isHMR ? '"development"' : '"production"',
|
|
277
|
-
},
|
|
278
|
-
loader: { ".js": "jsx", ".ts": "tsx" },
|
|
279
|
-
bundle: true,
|
|
280
|
-
minify: true,
|
|
281
|
-
outdir: BUILD_FOLDER,
|
|
282
|
-
outbase: SOURCE_FOLDER,
|
|
283
|
-
})
|
|
284
|
-
.then(() => {
|
|
285
|
-
if (!isInline) {
|
|
286
|
-
taskEmitter.emit("done");
|
|
287
|
-
globHTML.emit("getReady");
|
|
288
|
-
if (serverSentEvents) {
|
|
289
|
-
const changedFile = tsMaybeX2JS(file);
|
|
290
|
-
const [buildFilename] = getBuildNames(changedFile);
|
|
291
|
-
const js = fs_1.default.readFileSync(buildFilename, {
|
|
292
|
-
encoding: "utf8",
|
|
293
|
-
});
|
|
294
|
-
serverSentEvents({
|
|
295
|
-
js,
|
|
296
|
-
filename: buildFilename.split(`${BUILD_FOLDER}/`).pop(),
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
function minifyCSS(filename, buildFilename) {
|
|
303
|
-
const fileText = fs_1.default.readFileSync(filename, { encoding: "utf-8" });
|
|
304
|
-
return CSSprocessor.process(
|
|
305
|
-
fileText,
|
|
306
|
-
Object.assign(Object.assign({}, options), {
|
|
307
|
-
from: filename,
|
|
308
|
-
to: buildFilename,
|
|
309
|
-
})
|
|
310
|
-
)
|
|
311
|
-
.then((result) => {
|
|
312
|
-
fs_1.default.writeFileSync(buildFilename, result.css);
|
|
313
|
-
taskEmitter.emit("done");
|
|
314
|
-
globHTML.emit("getReady");
|
|
315
|
-
if (serverSentEvents) {
|
|
316
|
-
serverSentEvents({
|
|
317
|
-
css: result.css,
|
|
318
|
-
filename: buildFilename.split(`${BUILD_FOLDER}/`).pop(),
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
})
|
|
322
|
-
.catch((err) => {
|
|
323
|
-
console.error(err);
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
async function minifyHTML(filename, buildFilename) {
|
|
327
|
-
let fileText = fs_1.default.readFileSync(filename, { encoding: "utf-8" });
|
|
328
|
-
let DOM;
|
|
329
|
-
if (fileText.includes("<!DOCTYPE html>") || fileText.includes("<html")) {
|
|
330
|
-
DOM = parse5_1.parse(fileText);
|
|
331
|
-
} else {
|
|
332
|
-
DOM = parse5_1.parseFragment(fileText);
|
|
333
|
-
}
|
|
334
|
-
// Minify Code
|
|
335
|
-
const scripts = parse5_utils_1.findElements(
|
|
336
|
-
DOM,
|
|
337
|
-
(e) => parse5_utils_1.getTagName(e) === "script"
|
|
338
|
-
);
|
|
339
|
-
scripts.forEach((script, index) => {
|
|
340
|
-
const scriptTextNode = script.childNodes[0];
|
|
341
|
-
const isReferencedScript = script.attrs.find((a) => a.name === "src");
|
|
342
|
-
//@ts-ignore
|
|
343
|
-
if (
|
|
344
|
-
!(scriptTextNode === null || scriptTextNode === void 0
|
|
345
|
-
? void 0
|
|
346
|
-
: scriptTextNode.value) ||
|
|
347
|
-
isReferencedScript
|
|
348
|
-
)
|
|
349
|
-
return;
|
|
350
|
-
// Use bundled file and remove it from fs
|
|
351
|
-
const bundledFilename = buildFilename.replace(
|
|
352
|
-
".html",
|
|
353
|
-
`-bundle-${index}.js`
|
|
354
|
-
);
|
|
355
|
-
try {
|
|
356
|
-
const scriptContent = fs_1.default.readFileSync(bundledFilename, {
|
|
357
|
-
encoding: "utf-8",
|
|
358
|
-
});
|
|
359
|
-
fs_1.default.rmSync(bundledFilename);
|
|
360
|
-
// Replace src with bundled code
|
|
361
|
-
//@ts-ignore
|
|
362
|
-
scriptTextNode.value = scriptContent.replace(
|
|
363
|
-
TEMPLATE_LITERAL_MINIFIER,
|
|
364
|
-
" "
|
|
365
|
-
);
|
|
366
|
-
} catch (_a) {}
|
|
367
|
-
});
|
|
368
|
-
// Minify Inline Style
|
|
369
|
-
const styles = parse5_utils_1.findElements(
|
|
370
|
-
DOM,
|
|
371
|
-
(e) => parse5_utils_1.getTagName(e) === "style"
|
|
372
|
-
);
|
|
373
|
-
for (const style of styles) {
|
|
374
|
-
const node = style.childNodes[0];
|
|
375
|
-
//@ts-ignore
|
|
376
|
-
const styleContent =
|
|
377
|
-
node === null || node === void 0 ? void 0 : node.value;
|
|
378
|
-
if (!styleContent) continue;
|
|
379
|
-
const { css } = await CSSprocessor.process(
|
|
380
|
-
styleContent,
|
|
381
|
-
Object.assign(Object.assign({}, options), { from: undefined })
|
|
382
|
-
);
|
|
383
|
-
//@ts-ignore
|
|
384
|
-
node.value = css;
|
|
385
|
-
}
|
|
386
|
-
fileText = parse5_1.serialize(DOM);
|
|
387
|
-
// Minify HTML
|
|
388
|
-
fileText = html_minifier_terser_1.minify(fileText, {
|
|
389
|
-
collapseWhitespace: true,
|
|
390
|
-
removeComments: true,
|
|
391
|
-
});
|
|
392
|
-
if (isCritical) {
|
|
393
|
-
const buildFilenameArr = buildFilename.split("/");
|
|
394
|
-
const fileWithBase = buildFilenameArr.pop();
|
|
395
|
-
const buildDir = buildFilenameArr.join("/");
|
|
396
|
-
// critical is generating the files on the fs
|
|
397
|
-
return critical_1.default
|
|
398
|
-
.generate({
|
|
399
|
-
base: buildDir,
|
|
400
|
-
html: fileText,
|
|
401
|
-
target: fileWithBase,
|
|
402
|
-
minify: true,
|
|
403
|
-
inline: !isCSP,
|
|
404
|
-
extract: true,
|
|
405
|
-
rebase: () => {},
|
|
406
|
-
})
|
|
407
|
-
.then(({ html }) => {
|
|
408
|
-
taskEmitter.emit("done");
|
|
409
|
-
if (serverSentEvents) {
|
|
410
|
-
serverSentEvents({
|
|
411
|
-
html: addHMRCode(html, buildFilename),
|
|
412
|
-
filename: buildFilename,
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
})
|
|
416
|
-
.catch((err) => {
|
|
417
|
-
console.error(err);
|
|
418
|
-
});
|
|
419
|
-
} else {
|
|
420
|
-
fs_1.default.writeFileSync(buildFilename, fileText);
|
|
421
|
-
taskEmitter.emit("done");
|
|
422
|
-
if (serverSentEvents) {
|
|
423
|
-
serverSentEvents({
|
|
424
|
-
html: addHMRCode(fileText, buildFilename),
|
|
425
|
-
filename: buildFilename,
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
// Helper functions from here
|
|
431
|
-
function createPostCSSConfig() {
|
|
432
|
-
try {
|
|
433
|
-
return postcss_load_config_1.default.sync({});
|
|
434
|
-
} catch (_a) {
|
|
435
|
-
return { plugins: [cssnano_1.default], options: {}, file: "" };
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
function getBuildNames(filename) {
|
|
439
|
-
const buildFilename = filename.replace(
|
|
440
|
-
`${SOURCE_FOLDER}/`,
|
|
441
|
-
`${BUILD_FOLDER}/`
|
|
442
|
-
);
|
|
443
|
-
const buildFilenameArr = buildFilename.split("/");
|
|
444
|
-
buildFilenameArr.pop();
|
|
445
|
-
const buildPathDir = buildFilenameArr.join("/");
|
|
446
|
-
return [buildFilename, buildPathDir];
|
|
447
|
-
}
|
|
448
|
-
async function rebuild(filename) {
|
|
449
|
-
const [buildFilename] = getBuildNames(filename);
|
|
450
|
-
if (/\.(j|t)sx?$/.test(filename)) {
|
|
451
|
-
JSTSFiles.add(filename);
|
|
452
|
-
} else if (filename.endsWith(".css")) {
|
|
453
|
-
await minifyCSS(filename, buildFilename);
|
|
454
|
-
}
|
|
455
|
-
glob_1.default(`${SOURCE_FOLDER}/**/*.html`, {}, async (err, files) => {
|
|
456
|
-
errorHandler(err);
|
|
457
|
-
await createGlobalJS(files);
|
|
458
|
-
if (filename.endsWith(".html")) {
|
|
459
|
-
minifyHTML(filename, buildFilename);
|
|
460
|
-
} else if (
|
|
461
|
-
/\.(j|t)sx?$/.test(filename) ||
|
|
462
|
-
(filename.endsWith(".css") && isCritical)
|
|
463
|
-
) {
|
|
464
|
-
for (const htmlFilename of files) {
|
|
465
|
-
const [htmlBuildFilename] = getBuildNames(htmlFilename);
|
|
466
|
-
await minifyHTML(htmlFilename, htmlBuildFilename);
|
|
467
|
-
}
|
|
468
|
-
if (/\.(j|t)sx?$/.test(filename) && serverSentEvents) {
|
|
469
|
-
const jsFile = tsMaybeX2JS(buildFilename);
|
|
470
|
-
try {
|
|
471
|
-
// Do not try to send empty files
|
|
472
|
-
serverSentEvents({
|
|
473
|
-
js: fs_1.default.readFileSync(jsFile, { encoding: "utf-8" }),
|
|
474
|
-
filename: jsFile.split(`${BUILD_FOLDER}/`).pop(),
|
|
475
|
-
});
|
|
476
|
-
} catch (_a) {}
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
const getHMRCode = (
|
|
482
|
-
filename,
|
|
483
|
-
id
|
|
484
|
-
) => `import { render, html, setShouldSetReactivity, $$, setGlobalSchedule, setInsertDiffing } from "https://unpkg.com/hydro-js/dist/library.js";
|
|
485
|
-
|
|
486
|
-
if (!window.eventsource${id}) {
|
|
487
|
-
setGlobalSchedule(false);
|
|
488
|
-
setShouldSetReactivity(false);
|
|
489
|
-
|
|
490
|
-
window.eventsource${id} = new EventSource("/events");
|
|
491
|
-
window.eventsource${id}.addEventListener("message", ({ data }) => {
|
|
492
|
-
const dataObj = JSON.parse(data);
|
|
493
|
-
|
|
494
|
-
if ("html" in dataObj && "${filename}" === dataObj.filename) {
|
|
495
|
-
setInsertDiffing(true);
|
|
496
|
-
|
|
497
|
-
let newHTML;
|
|
498
|
-
let isBody;
|
|
499
|
-
|
|
500
|
-
if (dataObj.html.startsWith('<!DOCTYPE html>') || dataObj.html.startsWith('<html')) {
|
|
501
|
-
newHTML = html\`\${dataObj.html}\`;
|
|
502
|
-
} else {
|
|
503
|
-
newHTML = html\`<body>\${dataObj.html}</body>\`
|
|
504
|
-
isBody = true
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
if (isBody) {
|
|
508
|
-
const hmrID = "${id}";
|
|
509
|
-
const hmrElems = Array.from(newHTML.childNodes);
|
|
510
|
-
const hmrWheres = Array.from($$(\`[data-hmr="\${hmrID}"]\`))
|
|
511
|
-
// Render new Elements in old Elements, also remove rest old Elements and add add new elements after the last old one
|
|
512
|
-
hmrWheres.forEach((where, index) => {
|
|
513
|
-
if (index < hmrElems.length) {
|
|
514
|
-
render(hmrElems[index], where);
|
|
515
|
-
} else {
|
|
516
|
-
where.remove();
|
|
517
|
-
}
|
|
518
|
-
});
|
|
519
|
-
for (let rest = hmrWheres.length; rest < hmrElems.length; rest++) {
|
|
520
|
-
if (hmrWheres.length) {
|
|
521
|
-
const template = document.createElement('template');
|
|
522
|
-
hmrElems[hmrWheres.length - 1].after(template);
|
|
523
|
-
render(hmrElems[rest], template);
|
|
524
|
-
template.remove();
|
|
525
|
-
} else {
|
|
526
|
-
render(hmrElems[rest])
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
} else {
|
|
530
|
-
const oldElementCount = document.body.querySelectorAll('*').length;
|
|
531
|
-
render(newHTML, document.documentElement);
|
|
532
|
-
const newElementCount = document.body.querySelectorAll('*').length;
|
|
533
|
-
|
|
534
|
-
// Looks like JS did not reload? Last resort - hard refresh
|
|
535
|
-
if (newElementCount < 5 && Math.abs(newElementCount - oldElementCount) > 10) {
|
|
536
|
-
location.reload()
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
setInsertDiffing(false);
|
|
540
|
-
dispatchEvent(new Event("popstate"));
|
|
541
|
-
} else if ("css" in dataObj) {
|
|
542
|
-
window.onceEveryXTime(100, window.updateCSS, [updateAttr]);
|
|
543
|
-
} else if ("js" in dataObj) {
|
|
544
|
-
window.onceEveryXTime(100, window.updateJS, [updateAttr]);
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
function updateAttr (attr, forceUpdate = false) {
|
|
548
|
-
return (elem) => {
|
|
549
|
-
const attrValue = elem[attr].replace(/\\?v=.*/, "");
|
|
550
|
-
if (forceUpdate || attrValue.endsWith(dataObj.filename)) {
|
|
551
|
-
elem[attr] = \`\${attrValue}?v=\${Math.random().toFixed(4)}\`;
|
|
552
|
-
} else if (elem.localName === 'script' && !elem.src && new RegExp(\`["']\${dataObj.filename}["']\`).test(elem.textContent)) {
|
|
553
|
-
elem.setAttribute('data-inline', String(Math.random().toFixed(4)).slice(2));
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
};
|
|
557
|
-
});
|
|
558
|
-
|
|
559
|
-
if (!window.updateCSS) {
|
|
560
|
-
window.updateCSS = function updateCSS(updateAttr) {
|
|
561
|
-
$$('link').forEach(updateAttr("href"));
|
|
562
|
-
window.fnToLastCalled.set(window.updateCSS, performance.now())
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
if (!window.updateJS) {
|
|
566
|
-
window.updateJS = function updateJS(updateAttr) {
|
|
567
|
-
window.fnToLastCalled.set(window.updateJS, performance.now());
|
|
568
|
-
const copy = html\`\${document.documentElement.outerHTML}\`;
|
|
569
|
-
copy.querySelectorAll('script').forEach(updateAttr("src"));
|
|
570
|
-
render(copy, document.documentElement);
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
if (!window.fnToLastCalled) {
|
|
574
|
-
window.fnToLastCalled = new Map();
|
|
575
|
-
}
|
|
576
|
-
if (!window.onceEveryXTime) {
|
|
577
|
-
window.onceEveryXTime = function (time, fn, params) {
|
|
578
|
-
if (!window.fnToLastCalled.has(fn) || performance.now() - window.fnToLastCalled.get(fn) > time) {
|
|
579
|
-
fn(...params)
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
}`;
|
|
584
|
-
function randomText() {
|
|
585
|
-
return Math.random().toString(32).slice(2);
|
|
586
|
-
}
|
|
587
|
-
const htmlIdMap = new Map();
|
|
588
|
-
function addHMRCode(html, filename) {
|
|
589
|
-
if (!htmlIdMap.has(filename)) {
|
|
590
|
-
htmlIdMap.set(filename, randomText());
|
|
591
|
-
}
|
|
592
|
-
const script = parse5_utils_1.createScript(
|
|
593
|
-
{ type: "module" },
|
|
594
|
-
getHMRCode(filename, htmlIdMap.get(filename))
|
|
595
|
-
);
|
|
596
|
-
let ast;
|
|
597
|
-
if (html.includes("<!DOCTYPE html>") || html.includes("<html")) {
|
|
598
|
-
ast = parse5_1.parse(html);
|
|
599
|
-
const headNode = parse5_utils_1.findElement(
|
|
600
|
-
ast,
|
|
601
|
-
(e) => parse5_utils_1.getTagName(e) === "head"
|
|
602
|
-
);
|
|
603
|
-
parse5_utils_1.appendChild(headNode, script);
|
|
604
|
-
} else {
|
|
605
|
-
ast = parse5_1.parseFragment(html);
|
|
606
|
-
parse5_utils_1.appendChild(ast, script);
|
|
607
|
-
ast.childNodes.forEach((node) => {
|
|
608
|
-
var _a;
|
|
609
|
-
//@ts-ignore
|
|
610
|
-
return (_a = node.attrs) === null || _a === void 0
|
|
611
|
-
? void 0
|
|
612
|
-
: _a.push({ name: "data-hmr", value: htmlIdMap.get(filename) });
|
|
613
|
-
});
|
|
614
|
-
}
|
|
615
|
-
// Burst CSS cache
|
|
616
|
-
parse5_utils_1
|
|
617
|
-
.findElements(ast, (e) => parse5_utils_1.getTagName(e) === "link")
|
|
618
|
-
.forEach((link) => {
|
|
619
|
-
const href = link.attrs.find((attr) => attr.name === "href");
|
|
620
|
-
const rel = link.attrs.find((attr) => attr.name === "rel");
|
|
621
|
-
if (rel.value === "stylesheet") {
|
|
622
|
-
href.value += `?v=${Math.random().toFixed(4)}`;
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
|
-
return parse5_1.serialize(ast);
|
|
626
|
-
}
|
|
627
|
-
function createHMRHandlers(files) {
|
|
628
|
-
files.forEach((filename) => {
|
|
629
|
-
const newFilename = "/" + filename.replace(/src\//, "");
|
|
630
|
-
const filePath = newFilename.split("/");
|
|
631
|
-
const endName = filePath.pop();
|
|
632
|
-
if (endName.endsWith("index.html")) {
|
|
633
|
-
//@ts-ignore
|
|
634
|
-
fastify.get(filePath.join("/") + "/", HMRHandler);
|
|
635
|
-
}
|
|
636
|
-
//@ts-ignore
|
|
637
|
-
fastify.get(newFilename, HMRHandler);
|
|
638
|
-
});
|
|
639
|
-
}
|
|
640
|
-
function HMRHandler(request, reply) {
|
|
641
|
-
let filename = request.url;
|
|
642
|
-
if (filename.endsWith("/")) {
|
|
643
|
-
filename += "index.html";
|
|
644
|
-
}
|
|
645
|
-
filename = BUILD_FOLDER + filename;
|
|
646
|
-
const file = fs_1.default.readFileSync(filename, {
|
|
647
|
-
encoding: "utf-8",
|
|
648
|
-
});
|
|
649
|
-
reply.header("Content-Type", "text/html; charset=UTF-8");
|
|
650
|
-
return reply.send(addHMRCode(file, filename));
|
|
651
|
-
}
|
|
652
|
-
function errorHandler(err) {
|
|
653
|
-
if (err) {
|
|
654
|
-
console.error(err);
|
|
655
|
-
process.exit(1);
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
function tsMaybeX2JS(filename) {
|
|
659
|
-
return filename.replace(".ts", ".js").replace(".jsx", ".js");
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
function createDefaultServer(BUILD_FOLDER = "build") {
|
|
663
|
-
fastify = fastify_1.default(
|
|
664
|
-
isSecure
|
|
665
|
-
? {
|
|
666
|
-
http2: true,
|
|
667
|
-
https: {
|
|
668
|
-
key: fs_1.default.readFileSync(
|
|
669
|
-
path_1.default.join(process.cwd(), "localhost-key.pem")
|
|
670
|
-
),
|
|
671
|
-
cert: fs_1.default.readFileSync(
|
|
672
|
-
path_1.default.join(process.cwd(), "localhost.pem")
|
|
673
|
-
),
|
|
674
|
-
},
|
|
675
|
-
}
|
|
676
|
-
: void 0
|
|
677
|
-
);
|
|
678
|
-
fastify.register(fastify_static_1.default, {
|
|
679
|
-
root: path_1.default.join(process.cwd(), BUILD_FOLDER),
|
|
680
|
-
});
|
|
681
|
-
}
|
package/tsconfig.cjs.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2017",
|
|
4
|
-
"module": "CommonJS",
|
|
5
|
-
"lib": ["ES2017"],
|
|
6
|
-
"outDir": "./cjs",
|
|
7
|
-
"rootDir": "./src",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"skipLibCheck": true,
|
|
10
|
-
"moduleResolution": "node",
|
|
11
|
-
"esModuleInterop": true,
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"typeRoots": ["node_modules/@types"]
|
|
14
|
-
},
|
|
15
|
-
"include": ["src", "types"]
|
|
16
|
-
}
|