html-bundle 6.0.21 → 6.1.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/README.md +13 -0
- package/dist/bundle.mjs +45 -20
- package/dist/utils.mjs +1 -1
- package/package.json +7 -6
- package/src/bundle.mts +45 -22
- package/src/config.d.ts +13 -0
- package/src/utils.mts +1 -13
package/README.md
CHANGED
|
@@ -63,6 +63,19 @@ Generate the config in the root and call it "bundle.config.js"
|
|
|
63
63
|
**html-minifier-terser:** Your additional config<br>
|
|
64
64
|
**critical:** Your additional config<br>
|
|
65
65
|
|
|
66
|
+
Example:
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
/** @type {import('html-bundle').Config} */
|
|
70
|
+
export default {
|
|
71
|
+
secure: true,
|
|
72
|
+
handler: "utils/staticFiles.js",
|
|
73
|
+
esbuild: {
|
|
74
|
+
external: ["images"],
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
66
79
|
## Concept
|
|
67
80
|
|
|
68
81
|
The bundler always globs all HTML, CSS and TS/JS files from the `src` (config) directory and processes them to the `build` (config) directory. PostCSS is being used for CSS files and inline styles, html-minifier-terser for HTML and esbuild to bundle, minify, etc. for inline and referenced TS/JS. Server-sent events and [hydro-js](https://github.com/Krutsch/hydro-js) are used for HMR. In order to trigger SPA Routers, the popstate event is being triggered after HMR Operations.
|
package/dist/bundle.mjs
CHANGED
|
@@ -103,7 +103,10 @@ async function build(files, firstRun = true) {
|
|
|
103
103
|
if (files.includes(file) || INLINE_BUNDLE_FILE.test(file)) {
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
|
-
|
|
106
|
+
try {
|
|
107
|
+
await rebuild(file);
|
|
108
|
+
}
|
|
109
|
+
catch { }
|
|
107
110
|
console.log(`⚡ added ${file} to the build`);
|
|
108
111
|
});
|
|
109
112
|
watcher.on("change", async (file) => {
|
|
@@ -123,11 +126,14 @@ async function build(files, firstRun = true) {
|
|
|
123
126
|
const buildFile = getBuildPath(file)
|
|
124
127
|
.replace(".ts", ".js")
|
|
125
128
|
.replace(".jsx", ".js");
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
try {
|
|
130
|
+
await rm(buildFile);
|
|
131
|
+
const bfDir = buildFile.split("/").slice(0, -1).join("/");
|
|
132
|
+
const stats = await readdir(bfDir);
|
|
133
|
+
if (!stats.length)
|
|
134
|
+
await rm(bfDir);
|
|
135
|
+
}
|
|
136
|
+
catch { }
|
|
131
137
|
console.log(`⚡ deleted ${file} from the build`);
|
|
132
138
|
});
|
|
133
139
|
async function rebuild(file) {
|
|
@@ -162,6 +168,11 @@ async function build(files, firstRun = true) {
|
|
|
162
168
|
await fileCopy(file);
|
|
163
169
|
}
|
|
164
170
|
}
|
|
171
|
+
else if (handlerFile) {
|
|
172
|
+
const { stdout } = await execFilePromise("node", [handlerFile, file]);
|
|
173
|
+
if (String(stdout))
|
|
174
|
+
console.log("📋 Logging Handler: ", String(stdout));
|
|
175
|
+
}
|
|
165
176
|
serverSentEvents?.({ file, html });
|
|
166
177
|
}
|
|
167
178
|
}
|
|
@@ -177,7 +188,8 @@ async function minifyCSS(file, buildFile) {
|
|
|
177
188
|
await writeFile(buildFile, result.css);
|
|
178
189
|
}
|
|
179
190
|
catch (err) {
|
|
180
|
-
|
|
191
|
+
// @ts-ignore
|
|
192
|
+
console.error(err?.reason);
|
|
181
193
|
}
|
|
182
194
|
}
|
|
183
195
|
async function minifyCode() {
|
|
@@ -207,7 +219,7 @@ async function minifyCode() {
|
|
|
207
219
|
let missingPkg = false;
|
|
208
220
|
if (err?.errors) {
|
|
209
221
|
for (const error of err.errors) {
|
|
210
|
-
if (error.text?.startsWith("Could not resolve")) {
|
|
222
|
+
if (error.location && error.text?.startsWith("Could not resolve")) {
|
|
211
223
|
missingPkg = true;
|
|
212
224
|
const packageNameRegex = /(?<=").*(?=")/;
|
|
213
225
|
const [pkgName] = error.text.match(packageNameRegex);
|
|
@@ -244,8 +256,9 @@ async function writeInlineScripts(file) {
|
|
|
244
256
|
const script = scripts[index];
|
|
245
257
|
const scriptTextNode = script.childNodes[0];
|
|
246
258
|
const isReferencedScript = script.attrs.find((a) => a.name === "src");
|
|
259
|
+
const type = script.attrs.find((a) => a.name === "type");
|
|
247
260
|
const scriptContent = scriptTextNode?.value;
|
|
248
|
-
if (!scriptContent || isReferencedScript)
|
|
261
|
+
if (!scriptContent || isReferencedScript || type?.value === "importmap")
|
|
249
262
|
continue;
|
|
250
263
|
const jsFile = file.replace(".html", `-bundle-${index}.tsx`);
|
|
251
264
|
inlineFiles.add(jsFile);
|
|
@@ -274,15 +287,21 @@ async function minifyHTML(file, buildFile) {
|
|
|
274
287
|
const script = scripts[index];
|
|
275
288
|
const scriptTextNode = script.childNodes[0];
|
|
276
289
|
const isReferencedScript = script.attrs.find((a) => a.name === "src");
|
|
277
|
-
|
|
290
|
+
const type = script.attrs.find((a) => a.name === "type");
|
|
291
|
+
if (!scriptTextNode?.value ||
|
|
292
|
+
isReferencedScript ||
|
|
293
|
+
type?.value === "importmap")
|
|
278
294
|
continue;
|
|
279
295
|
// Use bundled file
|
|
280
296
|
const buildInlineScript = buildFile.replace(".html", `-bundle-${index}.js`);
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
297
|
+
try {
|
|
298
|
+
const scriptContent = await readFile(buildInlineScript, {
|
|
299
|
+
encoding: "utf-8",
|
|
300
|
+
});
|
|
301
|
+
await rm(buildInlineScript);
|
|
302
|
+
scriptTextNode.value = scriptContent.replace(TEMPLATE_LITERAL_MINIFIER, " ");
|
|
303
|
+
}
|
|
304
|
+
catch { }
|
|
286
305
|
}
|
|
287
306
|
// Minify Inline Style
|
|
288
307
|
const styles = findElements(DOM, (e) => getTagName(e) === "style");
|
|
@@ -291,11 +310,17 @@ async function minifyHTML(file, buildFile) {
|
|
|
291
310
|
const styleContent = node?.value;
|
|
292
311
|
if (!styleContent)
|
|
293
312
|
continue;
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
313
|
+
try {
|
|
314
|
+
const { css } = await CSSprocessor.process(styleContent, {
|
|
315
|
+
...options,
|
|
316
|
+
from: undefined,
|
|
317
|
+
});
|
|
318
|
+
node.value = css;
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
// @ts-ignore
|
|
322
|
+
console.error(err?.reason);
|
|
323
|
+
}
|
|
299
324
|
}
|
|
300
325
|
fileText = serialize(DOM);
|
|
301
326
|
// Minify HTML
|
package/dist/utils.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "html-bundle",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "A very simple bundler for HTML SFC",
|
|
5
5
|
"bin": "./dist/bundle.mjs",
|
|
6
|
+
"types": "./src/config.d.ts",
|
|
6
7
|
"scripts": {
|
|
7
8
|
"start": "tsc",
|
|
8
9
|
"update": "npx npm-check-updates -u && npx typesync && npm i && npm outdated"
|
|
@@ -31,19 +32,19 @@
|
|
|
31
32
|
},
|
|
32
33
|
"bugs": "https://github.com/Krutsch/html-bundle/issues",
|
|
33
34
|
"dependencies": {
|
|
34
|
-
"@fastify/static": "^
|
|
35
|
+
"@fastify/static": "^7.0.0",
|
|
35
36
|
"@web/parse5-utils": "^2.1.0",
|
|
36
37
|
"await-spawn": "^4.0.2",
|
|
37
38
|
"chokidar": "^3.5.3",
|
|
38
39
|
"critters": "^0.0.20",
|
|
39
|
-
"cssnano": "^6.0.
|
|
40
|
-
"esbuild": "^0.
|
|
41
|
-
"fastify": "^4.
|
|
40
|
+
"cssnano": "^6.0.3",
|
|
41
|
+
"esbuild": "^0.20.0",
|
|
42
|
+
"fastify": "^4.26.0",
|
|
42
43
|
"glob": "^10.3.10",
|
|
43
44
|
"html-minifier-terser": "^7.2.0",
|
|
44
45
|
"hydro-js": "^1.5.14",
|
|
45
46
|
"parse5": "^7.1.2",
|
|
46
|
-
"postcss": "^8.4.
|
|
47
|
+
"postcss": "^8.4.34",
|
|
47
48
|
"postcss-load-config": "^5.0.2"
|
|
48
49
|
}
|
|
49
50
|
}
|
package/src/bundle.mts
CHANGED
|
@@ -138,7 +138,9 @@ async function build(files: string[], firstRun = true) {
|
|
|
138
138
|
return;
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
try {
|
|
142
|
+
await rebuild(file);
|
|
143
|
+
} catch {}
|
|
142
144
|
|
|
143
145
|
console.log(`⚡ added ${file} to the build`);
|
|
144
146
|
});
|
|
@@ -162,11 +164,13 @@ async function build(files: string[], firstRun = true) {
|
|
|
162
164
|
const buildFile = getBuildPath(file)
|
|
163
165
|
.replace(".ts", ".js")
|
|
164
166
|
.replace(".jsx", ".js");
|
|
165
|
-
await rm(buildFile);
|
|
166
167
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
168
|
+
try {
|
|
169
|
+
await rm(buildFile);
|
|
170
|
+
const bfDir = buildFile.split("/").slice(0, -1).join("/");
|
|
171
|
+
const stats = await readdir(bfDir);
|
|
172
|
+
if (!stats.length) await rm(bfDir);
|
|
173
|
+
} catch {}
|
|
170
174
|
|
|
171
175
|
console.log(`⚡ deleted ${file} from the build`);
|
|
172
176
|
});
|
|
@@ -200,6 +204,9 @@ async function build(files: string[], firstRun = true) {
|
|
|
200
204
|
} else {
|
|
201
205
|
await fileCopy(file);
|
|
202
206
|
}
|
|
207
|
+
} else if (handlerFile) {
|
|
208
|
+
const { stdout } = await execFilePromise("node", [handlerFile, file]);
|
|
209
|
+
if (String(stdout)) console.log("📋 Logging Handler: ", String(stdout));
|
|
203
210
|
}
|
|
204
211
|
|
|
205
212
|
serverSentEvents?.({ file, html });
|
|
@@ -217,7 +224,8 @@ async function minifyCSS(file: string, buildFile: string) {
|
|
|
217
224
|
});
|
|
218
225
|
await writeFile(buildFile, result.css);
|
|
219
226
|
} catch (err) {
|
|
220
|
-
|
|
227
|
+
// @ts-ignore
|
|
228
|
+
console.error(err?.reason);
|
|
221
229
|
}
|
|
222
230
|
}
|
|
223
231
|
|
|
@@ -248,7 +256,7 @@ async function minifyCode(): Promise<unknown> {
|
|
|
248
256
|
let missingPkg = false;
|
|
249
257
|
if (err?.errors) {
|
|
250
258
|
for (const error of err.errors) {
|
|
251
|
-
if (error.text?.startsWith("Could not resolve")) {
|
|
259
|
+
if (error.location && error.text?.startsWith("Could not resolve")) {
|
|
252
260
|
missingPkg = true;
|
|
253
261
|
const packageNameRegex = /(?<=").*(?=")/;
|
|
254
262
|
const [pkgName] = error.text.match(packageNameRegex);
|
|
@@ -293,8 +301,10 @@ async function writeInlineScripts(file: string) {
|
|
|
293
301
|
const isReferencedScript = script.attrs.find(
|
|
294
302
|
(a: { name: string }) => a.name === "src"
|
|
295
303
|
);
|
|
304
|
+
const type = script.attrs.find((a: { name: string }) => a.name === "type");
|
|
296
305
|
const scriptContent = scriptTextNode?.value;
|
|
297
|
-
if (!scriptContent || isReferencedScript)
|
|
306
|
+
if (!scriptContent || isReferencedScript || type?.value === "importmap")
|
|
307
|
+
continue;
|
|
298
308
|
|
|
299
309
|
const jsFile = file.replace(".html", `-bundle-${index}.tsx`);
|
|
300
310
|
inlineFiles.add(jsFile);
|
|
@@ -327,19 +337,27 @@ async function minifyHTML(file: string, buildFile: string) {
|
|
|
327
337
|
const isReferencedScript = script.attrs.find(
|
|
328
338
|
(a: { name: string }) => a.name === "src"
|
|
329
339
|
);
|
|
330
|
-
|
|
340
|
+
const type = script.attrs.find((a: { name: string }) => a.name === "type");
|
|
341
|
+
if (
|
|
342
|
+
!scriptTextNode?.value ||
|
|
343
|
+
isReferencedScript ||
|
|
344
|
+
type?.value === "importmap"
|
|
345
|
+
)
|
|
346
|
+
continue;
|
|
331
347
|
|
|
332
348
|
// Use bundled file
|
|
333
349
|
const buildInlineScript = buildFile.replace(".html", `-bundle-${index}.js`);
|
|
334
350
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
351
|
+
try {
|
|
352
|
+
const scriptContent = await readFile(buildInlineScript, {
|
|
353
|
+
encoding: "utf-8",
|
|
354
|
+
});
|
|
355
|
+
await rm(buildInlineScript);
|
|
356
|
+
scriptTextNode.value = scriptContent.replace(
|
|
357
|
+
TEMPLATE_LITERAL_MINIFIER,
|
|
358
|
+
" "
|
|
359
|
+
);
|
|
360
|
+
} catch {}
|
|
343
361
|
}
|
|
344
362
|
|
|
345
363
|
// Minify Inline Style
|
|
@@ -349,11 +367,16 @@ async function minifyHTML(file: string, buildFile: string) {
|
|
|
349
367
|
const styleContent = node?.value;
|
|
350
368
|
if (!styleContent) continue;
|
|
351
369
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
370
|
+
try {
|
|
371
|
+
const { css } = await CSSprocessor.process(styleContent, {
|
|
372
|
+
...options,
|
|
373
|
+
from: undefined,
|
|
374
|
+
});
|
|
375
|
+
node.value = css;
|
|
376
|
+
} catch {
|
|
377
|
+
// @ts-ignore
|
|
378
|
+
console.error(err?.reason);
|
|
379
|
+
}
|
|
357
380
|
}
|
|
358
381
|
|
|
359
382
|
fileText = serialize(DOM);
|
package/src/config.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type Config = {
|
|
2
|
+
build: string;
|
|
3
|
+
src: string;
|
|
4
|
+
port: number;
|
|
5
|
+
secure: boolean;
|
|
6
|
+
esbuild?: BuildOptions;
|
|
7
|
+
"html-minifier-terser"?: HTMLOptions;
|
|
8
|
+
critical?: Options;
|
|
9
|
+
deletePrev?: boolean;
|
|
10
|
+
isCritical?: boolean;
|
|
11
|
+
hmr?: boolean;
|
|
12
|
+
handler?: string;
|
|
13
|
+
};
|
package/src/utils.mts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
findElement,
|
|
17
17
|
appendChild,
|
|
18
18
|
} from "@web/parse5-utils";
|
|
19
|
+
import { Config } from "./config";
|
|
19
20
|
|
|
20
21
|
export const bundleConfig = await getBundleConfig();
|
|
21
22
|
|
|
@@ -89,19 +90,6 @@ export async function getPostCSSConfig() {
|
|
|
89
90
|
}
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
export type Config = {
|
|
93
|
-
build: string;
|
|
94
|
-
src: string;
|
|
95
|
-
port: number;
|
|
96
|
-
secure: boolean;
|
|
97
|
-
esbuild?: BuildOptions;
|
|
98
|
-
"html-minifier-terser"?: HTMLOptions;
|
|
99
|
-
critical?: Options;
|
|
100
|
-
deletePrev?: boolean;
|
|
101
|
-
isCritical?: boolean;
|
|
102
|
-
hmr?: boolean;
|
|
103
|
-
handler?: string;
|
|
104
|
-
};
|
|
105
93
|
async function getBundleConfig(): Promise<Config> {
|
|
106
94
|
const base = {
|
|
107
95
|
build: "build",
|