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.
@@ -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
- const start = performance.now();
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
- postCSSWatcher.on("change", () => {
48
- console.log(" modified postcss.config – CSS will rebuild now.");
49
- const newConfig = createPostCSSConfig();
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
- dispatchEvent(new Event("popstate"));
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.4.15",
3
+ "version": "5.5.0",
4
4
  "description": "A very simple bundler for HTML SFC",
5
- "bin": "./cjs/bundle.js",
5
+ "bin": "./dist/bundle.js",
6
6
  "scripts": {
7
- "start": "tsc && tsc -p tsconfig.cjs.json",
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.0",
22
- "@types/glob": "^7.1.3",
23
- "@types/html-minifier-terser": "^5.1.1",
24
- "@types/parse5": "^6.0.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.3.2"
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.2.2",
35
- "chokidar": "^3.5.1",
36
- "critical": "^3.0.1",
37
- "cssnano": "^5.0.4",
38
- "esbuild": "^0.12.4",
39
- "fastify": "^3.16.2",
40
- "fastify-static": "^4.2.2",
41
- "glob": "^7.1.7",
42
- "html-minifier-terser": "^5.1.1",
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.3.0",
45
- "postcss-load-config": "^3.0.1"
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
- const start = performance.now();
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
- postCSSWatcher.on("change", () => {
67
- console.log(" modified postcss.config – CSS will rebuild now.");
68
- const newConfig = createPostCSSConfig();
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
- dispatchEvent(new Event("popstate"));
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
@@ -3,7 +3,7 @@
3
3
  "target": "ESNext",
4
4
  "module": "ESNext",
5
5
  "lib": ["ESNext"],
6
- "outDir": "./esm",
6
+ "outDir": "./dist",
7
7
  "rootDir": "./src",
8
8
  "strict": true,
9
9
  "skipLibCheck": true,
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
- }