astro-html-minifier-next 0.1.3 → 0.2.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/dist/index.d.ts CHANGED
@@ -1,23 +1,5 @@
1
1
  import type { AstroIntegration } from "astro";
2
- import type { MinifierOptions as MinifyHTMLOptions } from "html-minifier-next";
3
- export interface HTMLMinifierOptions extends MinifyHTMLOptions {
4
- /**
5
- * Option specific to `astro-html-minifier-next` used to specify the maximum
6
- * number of worker threads to spawn when minifying files.
7
- * When set to `0`, `astro-html-minifier-next` will not create any worker
8
- * threads and will do the minification in the main thread.
9
- *
10
- * Note: If unable to do a structured clone of the `html-minifier-next`
11
- * options according to the
12
- * [HTML structured clone
13
- * algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm),
14
- * `astro-html-minifier-next` will do the minification on the main
15
- * thread, even if this option is not set to `0`.
16
- *
17
- * @default `Math.max(1, os.availableParallelism() - 1)`
18
- */
19
- maxWorkers?: number;
20
- }
2
+ import { type MinifierOptions as HTMLMinifierOptions } from "html-minifier-next";
21
3
  /**
22
4
  * An Astro integration that minifies HTML assets using
23
5
  * [html-minifier-next](https://www.npmjs.com/package/html-minifier-next).
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,IAAI,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAI/E,MAAM,WAAW,mBAAoB,SAAQ,iBAAiB;IAC7D;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CACnC,OAAO,EAAE,mBAAmB,GAC1B,gBAAgB,CA6HlB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EACN,KAAK,eAAe,IAAI,mBAAmB,EAE3C,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CACnC,OAAO,EAAE,mBAAmB,GAC1B,gBAAgB,CAyIlB"}
package/dist/index.js CHANGED
@@ -1,25 +1,9 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
1
2
  import { availableParallelism as getAvailableParallelism } from "node:os";
2
3
  import { relative as getRelativePath } from "node:path";
3
4
  import { fileURLToPath } from "node:url";
4
5
  import { styleText } from "node:util";
5
- import { minifyHTMLFile } from "./minify-html-file.js";
6
- import { MinifyHTMLFileWorkerPool } from "./minify-html-file-worker-pool.js";
7
- /**
8
- * Check if a value can be transferred to a worker.
9
- * @param {*} value
10
- * @returns {boolean}
11
- */
12
- function isTransferable(value) {
13
- try {
14
- // Attempt to do a structured clone of the value.
15
- // If it succeeds, it should be transferable to a worker.
16
- structuredClone(value);
17
- return true;
18
- }
19
- catch {
20
- return false;
21
- }
22
- }
6
+ import { minify as minifyHTML, } from "html-minifier-next";
23
7
  /**
24
8
  * An Astro integration that minifies HTML assets using
25
9
  * [html-minifier-next](https://www.npmjs.com/package/html-minifier-next).
@@ -33,15 +17,9 @@ export default function htmlMinifier(options) {
33
17
  return {
34
18
  name: "astro-html-minifier-next",
35
19
  hooks: {
36
- "astro:build:done": async ({ logger, dir: distUrl, assets }) => {
20
+ "astro:build:done": async ({ assets, dir: distUrl, logger, }) => {
37
21
  logger.info(styleText(["bgGreen", "black"], " minifying html assets "));
38
- const totalTimeStart = performance.now(); // --- TIMED BLOCK START ---
39
- const availableParallelism = getAvailableParallelism();
40
- const { maxWorkers = Math.max(1, availableParallelism - 1), ...minifyHTMLOptions } = options;
41
- let workerPool;
42
- if (maxWorkers > 0 && isTransferable(minifyHTMLOptions)) {
43
- workerPool = new MinifyHTMLFileWorkerPool(maxWorkers, minifyHTMLOptions);
44
- }
22
+ const totalTimeStart = performance.now(); // --- TOTAL TIMED BLOCK START ---
45
23
  const tasks = [];
46
24
  let tasksTotal = 0;
47
25
  let tasksDone = 0;
@@ -58,10 +36,24 @@ export default function htmlMinifier(options) {
58
36
  const relativeAssetPath = getRelativePath(distPath, assetPath);
59
37
  const logLineAssetPath = ` ${logLineArrow} /${relativeAssetPath} `;
60
38
  tasks.push(async () => {
61
- const { savings, time } = workerPool
62
- ? await workerPool.minifyHTMLFile(assetPath)
63
- : await minifyHTMLFile(assetPath, minifyHTMLOptions, signal);
64
- // Log a nice summary of the minification savings and the time it took.
39
+ const timeStart = performance.now(); // --- TIMED BLOCK START ---
40
+ const html = await readFile(assetPath, {
41
+ encoding: "utf8",
42
+ signal,
43
+ });
44
+ const minifiedHTML = await minifyHTML(html, options);
45
+ const savings = Buffer.byteLength(html) - Buffer.byteLength(minifiedHTML);
46
+ if (savings > 0) {
47
+ // Only write the minified HTML to the file if it's smaller.
48
+ await writeFile(assetPath, minifiedHTML, {
49
+ encoding: "utf8",
50
+ signal,
51
+ });
52
+ }
53
+ const timeEnd = performance.now(); // --- TIMED BLOCK END ---
54
+ const time = timeEnd - timeStart;
55
+ // Log a nice summary of the minification savings and the time it
56
+ // took.
65
57
  const savingsSign = savings > 0 ? "-" : "+";
66
58
  const savingsAbs = Math.abs(savings);
67
59
  const savingsWithUnit = savingsAbs < 1024
@@ -79,12 +71,15 @@ export default function htmlMinifier(options) {
79
71
  tasksTotal++;
80
72
  }
81
73
  }
82
- // We use a quadruple of the available parallelism here, even if we don't actually run the tasks in different threads or anything.
83
- // The available parallelism is a good indicator of machine capabilities, and the multiplier gives a good balance of speed and resource usage.
84
- const maxExecutingTasksSize = availableParallelism * 4;
74
+ // We use a quadruple of the available parallelism here, even if we
75
+ // don't actually run the tasks in different threads or anything. The
76
+ // available parallelism is a good indicator of machine capabilities,
77
+ // and the multiplier gives a good balance of speed and resource usage.
78
+ const maxExecutingTasksSize = getAvailableParallelism() * 4;
85
79
  // This holds the current batch of promises that are waiting to fulfill.
86
80
  const executingTasks = new Set();
87
- // Batch the tasks to avoid minifying too many files at once, which could lead to memory and performance issues.
81
+ // Batch the tasks to avoid minifying too many files at once, which
82
+ // could lead to memory and performance issues.
88
83
  for (const task of tasks) {
89
84
  const taskPromise = task()
90
85
  .then(() => {
@@ -98,8 +93,9 @@ export default function htmlMinifier(options) {
98
93
  });
99
94
  executingTasks.add(taskPromise);
100
95
  if (executingTasks.size >= maxExecutingTasksSize) {
101
- // If the amount of executing tasks reaches the limit, we wait until the one of them finishes,
102
- // and therefore gets deleted from the list, before continuing with the next task.
96
+ // If the amount of executing tasks reaches the limit, we wait
97
+ // until the one of them finishes, and therefore gets deleted from
98
+ // the list, before continuing with the next task.
103
99
  await Promise.race(executingTasks);
104
100
  }
105
101
  if (signal.aborted) {
@@ -108,13 +104,13 @@ export default function htmlMinifier(options) {
108
104
  }
109
105
  // Wait for any remaining tasks to finish.
110
106
  await Promise.all(executingTasks);
111
- const totalTimeEnd = performance.now(); // --- TIMED BLOCK END ---
112
- // Log how long processing all assets took.
107
+ const totalTimeEnd = performance.now(); // --- TOTAL TIMED BLOCK END ---
113
108
  const totalTime = totalTimeEnd - totalTimeStart;
114
- const totalTimeStr = totalTime < 1000
109
+ // Log how long processing all assets took.
110
+ const totalTimeWithUnit = totalTime < 1000
115
111
  ? `${Math.round(totalTime)}ms`
116
112
  : `${(totalTime / 1000).toFixed(2)}s`;
117
- logger.info(styleText("green", `✓ Completed in ${totalTimeStr}.`));
113
+ logger.info(styleText("green", `✓ Completed in ${totalTimeWithUnit}.`));
118
114
  },
119
115
  },
120
116
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,IAAI,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,QAAQ,IAAI,eAAe,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAqB7E;;;;GAIG;AACH,SAAS,cAAc,CAAC,KAAc;IACrC,IAAI,CAAC;QACJ,iDAAiD;QACjD,yDAAyD;QACzD,eAAe,CAAC,KAAK,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CACnC,OAA4B;IAE5B,+EAA+E;IAC/E,OAAO;QACN,IAAI,EAAE,0BAA0B;QAChC,KAAK,EAAE;YACN,kBAAkB,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE;gBAC9D,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,yBAAyB,CAAC,CAAC,CAAC;gBAExE,MAAM,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,4BAA4B;gBAEtE,MAAM,oBAAoB,GAAG,uBAAuB,EAAE,CAAC;gBACvD,MAAM,EACL,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,oBAAoB,GAAG,CAAC,CAAC,EAClD,GAAG,iBAAiB,EACpB,GAAG,OAAO,CAAC;gBAEZ,IAAI,UAAgD,CAAC;gBACrD,IAAI,UAAU,GAAG,CAAC,IAAI,cAAc,CAAC,iBAAiB,CAAC,EAAE,CAAC;oBACzD,UAAU,GAAG,IAAI,wBAAwB,CACxC,UAAU,EACV,iBAAiB,CACjB,CAAC;gBACH,CAAC;gBAED,MAAM,KAAK,GAA4B,EAAE,CAAC;gBAC1C,IAAI,UAAU,GAAG,CAAC,CAAC;gBACnB,IAAI,SAAS,GAAG,CAAC,CAAC;gBAElB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;gBACzC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;gBAEjC,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;gBACxC,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;gBAC7C,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;oBACzC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;wBAClC,MAAM,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;wBAC1C,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;4BAChD,SAAS;wBACV,CAAC;wBAED,MAAM,iBAAiB,GAAG,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;wBAC/D,MAAM,gBAAgB,GAAG,KAAK,YAAY,KAAK,iBAAiB,GAAG,CAAC;wBACpE,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;4BACrB,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,UAAU;gCACnC,CAAC,CAAC,MAAM,UAAU,CAAC,cAAc,CAAC,SAAS,CAAC;gCAC5C,CAAC,CAAC,MAAM,cAAc,CAAC,SAAS,EAAE,iBAAiB,EAAE,MAAM,CAAC,CAAC;4BAE9D,uEAAuE;4BACvE,MAAM,WAAW,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;4BAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;4BACrC,MAAM,eAAe,GACpB,UAAU,GAAG,IAAI;gCAChB,CAAC,CAAC,GAAG,UAAU,GAAG;gCAClB,CAAC,CAAC,UAAU,GAAG,OAAO;oCACrB,CAAC,CAAC,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;oCACvC,CAAC,CAAC,GAAG,CAAC,UAAU,GAAG,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;4BAC9C,MAAM,YAAY,GACjB,IAAI,GAAG,IAAI;gCACV,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI;gCACzB,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;4BACnC,MAAM,CAAC,IAAI,CACV,gBAAgB;gCACf,SAAS,CACR,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,EAC/B,IAAI,WAAW,GAAG,eAAe,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,CACvE;gCACD,SAAS,CACR,KAAK,EACL,KAAK,YAAY,MAAM,EAAE,SAAS,IAAI,UAAU,GAAG,CACnD,CACF,CAAC;wBACH,CAAC,CAAC,CAAC;wBAEH,UAAU,EAAE,CAAC;oBACd,CAAC;gBACF,CAAC;gBAED,kIAAkI;gBAClI,8IAA8I;gBAC9I,MAAM,qBAAqB,GAAG,oBAAoB,GAAG,CAAC,CAAC;gBAEvD,wEAAwE;gBACxE,MAAM,cAAc,GAAG,IAAI,GAAG,EAAiB,CAAC;gBAEhD,gHAAgH;gBAChH,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBAC1B,MAAM,WAAW,GAAG,IAAI,EAAE;yBACxB,IAAI,CAAC,GAAG,EAAE;wBACV,cAAc,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;oBACpC,CAAC,CAAC;yBACD,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;wBACZ,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;4BACrB,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;wBACrB,CAAC;wBACD,MAAM,CAAC,CAAC;oBACT,CAAC,CAAC,CAAC;oBAEJ,cAAc,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;oBAEhC,IAAI,cAAc,CAAC,IAAI,IAAI,qBAAqB,EAAE,CAAC;wBAClD,8FAA8F;wBAC9F,kFAAkF;wBAClF,MAAM,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;oBACpC,CAAC;oBAED,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;wBACpB,MAAM,MAAM,CAAC,MAAM,CAAC;oBACrB,CAAC;gBACF,CAAC;gBAED,0CAA0C;gBAC1C,MAAM,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBAElC,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,0BAA0B;gBAElE,2CAA2C;gBAC3C,MAAM,SAAS,GAAG,YAAY,GAAG,cAAc,CAAC;gBAChD,MAAM,YAAY,GACjB,SAAS,GAAG,IAAI;oBACf,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI;oBAC9B,CAAC,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;gBACxC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,kBAAkB,YAAY,GAAG,CAAC,CAAC,CAAC;YACpE,CAAC;SACD;KACD,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-html-minifier-next",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "Astro integration for html-minifier-next",
5
5
  "homepage": "https://github.com/jonasgeiler/astro-html-minifier-next#readme",
6
6
  "bugs": "https://github.com/jonasgeiler/astro-html-minifier-next/issues",
@@ -12,7 +12,7 @@
12
12
  "url": "git+https://github.com/jonasgeiler/astro-html-minifier-next.git"
13
13
  },
14
14
  "engines": {
15
- "node": "^20.12.0 || >=21.7.0"
15
+ "node": ">=22.13.0"
16
16
  },
17
17
  "peerDependencies": {
18
18
  "astro": "^5.0.0"
package/src/index.ts CHANGED
@@ -1,46 +1,13 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
1
2
  import { availableParallelism as getAvailableParallelism } from "node:os";
2
3
  import { relative as getRelativePath } from "node:path";
3
4
  import { fileURLToPath } from "node:url";
4
5
  import { styleText } from "node:util";
5
6
  import type { AstroIntegration } from "astro";
6
- import type { MinifierOptions as MinifyHTMLOptions } from "html-minifier-next";
7
- import { minifyHTMLFile } from "./minify-html-file.js";
8
- import { MinifyHTMLFileWorkerPool } from "./minify-html-file-worker-pool.js";
9
-
10
- export interface HTMLMinifierOptions extends MinifyHTMLOptions {
11
- /**
12
- * Option specific to `astro-html-minifier-next` used to specify the maximum
13
- * number of worker threads to spawn when minifying files.
14
- * When set to `0`, `astro-html-minifier-next` will not create any worker
15
- * threads and will do the minification in the main thread.
16
- *
17
- * Note: If unable to do a structured clone of the `html-minifier-next`
18
- * options according to the
19
- * [HTML structured clone
20
- * algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm),
21
- * `astro-html-minifier-next` will do the minification on the main
22
- * thread, even if this option is not set to `0`.
23
- *
24
- * @default `Math.max(1, os.availableParallelism() - 1)`
25
- */
26
- maxWorkers?: number;
27
- }
28
-
29
- /**
30
- * Check if a value can be transferred to a worker.
31
- * @param {*} value
32
- * @returns {boolean}
33
- */
34
- function isTransferable(value: unknown): boolean {
35
- try {
36
- // Attempt to do a structured clone of the value.
37
- // If it succeeds, it should be transferable to a worker.
38
- structuredClone(value);
39
- return true;
40
- } catch {
41
- return false;
42
- }
43
- }
7
+ import {
8
+ type MinifierOptions as HTMLMinifierOptions,
9
+ minify as minifyHTML,
10
+ } from "html-minifier-next";
44
11
 
45
12
  /**
46
13
  * An Astro integration that minifies HTML assets using
@@ -57,24 +24,14 @@ export default function htmlMinifier(
57
24
  return {
58
25
  name: "astro-html-minifier-next",
59
26
  hooks: {
60
- "astro:build:done": async ({ logger, dir: distUrl, assets }) => {
27
+ "astro:build:done": async ({
28
+ assets,
29
+ dir: distUrl,
30
+ logger,
31
+ }): Promise<void> => {
61
32
  logger.info(styleText(["bgGreen", "black"], " minifying html assets "));
62
33
 
63
- const totalTimeStart = performance.now(); // --- TIMED BLOCK START ---
64
-
65
- const availableParallelism = getAvailableParallelism();
66
- const {
67
- maxWorkers = Math.max(1, availableParallelism - 1),
68
- ...minifyHTMLOptions
69
- } = options;
70
-
71
- let workerPool: MinifyHTMLFileWorkerPool | undefined;
72
- if (maxWorkers > 0 && isTransferable(minifyHTMLOptions)) {
73
- workerPool = new MinifyHTMLFileWorkerPool(
74
- maxWorkers,
75
- minifyHTMLOptions,
76
- );
77
- }
34
+ const totalTimeStart = performance.now(); // --- TOTAL TIMED BLOCK START ---
78
35
 
79
36
  const tasks: (() => Promise<void>)[] = [];
80
37
  let tasksTotal = 0;
@@ -95,11 +52,29 @@ export default function htmlMinifier(
95
52
  const relativeAssetPath = getRelativePath(distPath, assetPath);
96
53
  const logLineAssetPath = ` ${logLineArrow} /${relativeAssetPath} `;
97
54
  tasks.push(async () => {
98
- const { savings, time } = workerPool
99
- ? await workerPool.minifyHTMLFile(assetPath)
100
- : await minifyHTMLFile(assetPath, minifyHTMLOptions, signal);
55
+ const timeStart = performance.now(); // --- TIMED BLOCK START ---
56
+
57
+ const html = await readFile(assetPath, {
58
+ encoding: "utf8",
59
+ signal,
60
+ });
61
+ const minifiedHTML = await minifyHTML(html, options);
62
+
63
+ const savings =
64
+ Buffer.byteLength(html) - Buffer.byteLength(minifiedHTML);
65
+ if (savings > 0) {
66
+ // Only write the minified HTML to the file if it's smaller.
67
+ await writeFile(assetPath, minifiedHTML, {
68
+ encoding: "utf8",
69
+ signal,
70
+ });
71
+ }
101
72
 
102
- // Log a nice summary of the minification savings and the time it took.
73
+ const timeEnd = performance.now(); // --- TIMED BLOCK END ---
74
+ const time = timeEnd - timeStart;
75
+
76
+ // Log a nice summary of the minification savings and the time it
77
+ // took.
103
78
  const savingsSign = savings > 0 ? "-" : "+";
104
79
  const savingsAbs = Math.abs(savings);
105
80
  const savingsWithUnit =
@@ -129,14 +104,17 @@ export default function htmlMinifier(
129
104
  }
130
105
  }
131
106
 
132
- // We use a quadruple of the available parallelism here, even if we don't actually run the tasks in different threads or anything.
133
- // The available parallelism is a good indicator of machine capabilities, and the multiplier gives a good balance of speed and resource usage.
134
- const maxExecutingTasksSize = availableParallelism * 4;
107
+ // We use a quadruple of the available parallelism here, even if we
108
+ // don't actually run the tasks in different threads or anything. The
109
+ // available parallelism is a good indicator of machine capabilities,
110
+ // and the multiplier gives a good balance of speed and resource usage.
111
+ const maxExecutingTasksSize = getAvailableParallelism() * 4;
135
112
 
136
113
  // This holds the current batch of promises that are waiting to fulfill.
137
114
  const executingTasks = new Set<Promise<void>>();
138
115
 
139
- // Batch the tasks to avoid minifying too many files at once, which could lead to memory and performance issues.
116
+ // Batch the tasks to avoid minifying too many files at once, which
117
+ // could lead to memory and performance issues.
140
118
  for (const task of tasks) {
141
119
  const taskPromise = task()
142
120
  .then(() => {
@@ -152,8 +130,9 @@ export default function htmlMinifier(
152
130
  executingTasks.add(taskPromise);
153
131
 
154
132
  if (executingTasks.size >= maxExecutingTasksSize) {
155
- // If the amount of executing tasks reaches the limit, we wait until the one of them finishes,
156
- // and therefore gets deleted from the list, before continuing with the next task.
133
+ // If the amount of executing tasks reaches the limit, we wait
134
+ // until the one of them finishes, and therefore gets deleted from
135
+ // the list, before continuing with the next task.
157
136
  await Promise.race(executingTasks);
158
137
  }
159
138
 
@@ -165,15 +144,15 @@ export default function htmlMinifier(
165
144
  // Wait for any remaining tasks to finish.
166
145
  await Promise.all(executingTasks);
167
146
 
168
- const totalTimeEnd = performance.now(); // --- TIMED BLOCK END ---
147
+ const totalTimeEnd = performance.now(); // --- TOTAL TIMED BLOCK END ---
148
+ const totalTime = totalTimeEnd - totalTimeStart;
169
149
 
170
150
  // Log how long processing all assets took.
171
- const totalTime = totalTimeEnd - totalTimeStart;
172
- const totalTimeStr =
151
+ const totalTimeWithUnit =
173
152
  totalTime < 1000
174
153
  ? `${Math.round(totalTime)}ms`
175
154
  : `${(totalTime / 1000).toFixed(2)}s`;
176
- logger.info(styleText("green", `✓ Completed in ${totalTimeStr}.`));
155
+ logger.info(styleText("green", `✓ Completed in ${totalTimeWithUnit}.`));
177
156
  },
178
157
  },
179
158
  };
@@ -1,26 +0,0 @@
1
- import { Worker } from "node:worker_threads";
2
- import type { MinifierOptions as MinifyHTMLOptions } from "html-minifier-next";
3
- import type { MinifyHTMLFileResult } from "./minify-html-file.js";
4
- interface MinifyHTMLFileWorker extends Worker {
5
- _currentResolve?: (result: MinifyHTMLFileResult) => void;
6
- _currentReject?: (error: unknown) => void;
7
- }
8
- export type MinifyHTMLWorkerInput = string;
9
- export type MinifyHTMLWorkerOutput = MinifyHTMLFileResult | {
10
- error: unknown;
11
- };
12
- export declare class MinifyHTMLFileWorkerPool {
13
- protected maxWorkers: number;
14
- protected minifyHTMLOptions: MinifyHTMLOptions;
15
- protected workerUrl: URL;
16
- protected pool: Set<Worker>;
17
- protected idle: Worker[];
18
- protected queue: ((value: Worker) => void)[];
19
- constructor(maxWorkers: number, minifyHTMLOptions: MinifyHTMLOptions);
20
- protected getAvailableWorker(): Promise<MinifyHTMLFileWorker>;
21
- protected releaseWorker(worker: Worker): void;
22
- protected removeWorker(worker: Worker): void;
23
- minifyHTMLFile(htmlFile: string): Promise<MinifyHTMLFileResult>;
24
- }
25
- export {};
26
- //# sourceMappingURL=minify-html-file-worker-pool.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"minify-html-file-worker-pool.d.ts","sourceRoot":"","sources":["../src/minify-html-file-worker-pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,IAAI,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,UAAU,oBAAqB,SAAQ,MAAM;IAC5C,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACzD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1C;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAC3C,MAAM,MAAM,sBAAsB,GAAG,oBAAoB,GAAG;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAE/E,qBAAa,wBAAwB;IACpC,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAE/C,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC;IACzB,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC;gBAEjC,UAAU,EAAE,MAAM,EAAE,iBAAiB,EAAE,iBAAiB;cAUpD,kBAAkB,IAAI,OAAO,CAAC,oBAAoB,CAAC;IAqDnE,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAc7C,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAU/B,cAAc,CAC1B,QAAQ,EAAE,MAAM,GAEd,OAAO,CAAC,oBAAoB,CAAC;CAWhC"}
@@ -1,89 +0,0 @@
1
- import { Worker } from "node:worker_threads";
2
- export class MinifyHTMLFileWorkerPool {
3
- maxWorkers;
4
- minifyHTMLOptions;
5
- workerUrl;
6
- pool;
7
- idle;
8
- queue;
9
- constructor(maxWorkers, minifyHTMLOptions) {
10
- this.maxWorkers = maxWorkers;
11
- this.minifyHTMLOptions = minifyHTMLOptions;
12
- this.workerUrl = new URL("./minify-html-file-worker.js", import.meta.url);
13
- this.pool = new Set();
14
- this.idle = [];
15
- this.queue = [];
16
- }
17
- async getAvailableWorker() {
18
- // If there is an idle worker, use it.
19
- if (this.idle.length) {
20
- const worker = this.idle.shift();
21
- if (worker !== undefined) {
22
- return worker;
23
- }
24
- }
25
- // If we can create a new worker, do so.
26
- if (this.pool.size < this.maxWorkers) {
27
- const worker = new Worker(this.workerUrl, {
28
- workerData: this.minifyHTMLOptions,
29
- });
30
- worker.on("message", async (message) => {
31
- if ("error" in message) {
32
- worker._currentReject?.(message.error);
33
- }
34
- else {
35
- worker._currentResolve?.(message);
36
- }
37
- worker._currentResolve = worker._currentReject = undefined;
38
- this.releaseWorker(worker);
39
- });
40
- worker.on("error", (error) => {
41
- worker._currentReject?.(error);
42
- worker._currentResolve = worker._currentReject = undefined;
43
- });
44
- worker.on("exit", (exitCode) => {
45
- this.removeWorker(worker);
46
- if (exitCode !== 0) {
47
- worker._currentReject?.(new Error(`Worker failed with exit code ${exitCode}.`));
48
- worker._currentResolve = worker._currentReject = undefined;
49
- }
50
- });
51
- this.pool.add(worker);
52
- return worker;
53
- }
54
- // Otherwise, wait for a worker to free up.
55
- return new Promise((resolve) => {
56
- // When a worker frees up, they will check the queue and resolve this promise.
57
- this.queue.push(resolve);
58
- });
59
- }
60
- releaseWorker(worker) {
61
- // If there is a queued request for a worker, resolve it.
62
- if (this.queue.length) {
63
- const resolve = this.queue.shift();
64
- if (resolve !== undefined) {
65
- resolve(worker);
66
- return;
67
- }
68
- }
69
- // Otherwise, keep the worker as idle.
70
- this.idle.push(worker);
71
- }
72
- removeWorker(worker) {
73
- this.pool.delete(worker);
74
- // If a worker is force stopped by the system, it might still be in the idle list.
75
- const idleIndex = this.idle.indexOf(worker);
76
- if (idleIndex !== -1) {
77
- this.idle.splice(idleIndex, 1);
78
- }
79
- }
80
- async minifyHTMLFile(htmlFile) {
81
- const worker = await this.getAvailableWorker();
82
- return new Promise((resolve, reject) => {
83
- worker._currentResolve = resolve;
84
- worker._currentReject = reject;
85
- worker.postMessage(htmlFile);
86
- });
87
- }
88
- }
89
- //# sourceMappingURL=minify-html-file-worker-pool.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"minify-html-file-worker-pool.js","sourceRoot":"","sources":["../src/minify-html-file-worker-pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAY7C,MAAM,OAAO,wBAAwB;IAC1B,UAAU,CAAS;IACnB,iBAAiB,CAAoB;IAErC,SAAS,CAAM;IACf,IAAI,CAAc;IAClB,IAAI,CAAW;IACf,KAAK,CAA8B;IAE7C,YAAY,UAAkB,EAAE,iBAAoC;QACnE,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAE3C,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,CAAC,8BAA8B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1E,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;IACjB,CAAC;IAES,KAAK,CAAC,kBAAkB;QACjC,sCAAsC;QACtC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC1B,OAAO,MAAM,CAAC;YACf,CAAC;QACF,CAAC;QAED,wCAAwC;QACxC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE;gBACzC,UAAU,EAAE,IAAI,CAAC,iBAAiB;aAClC,CAAyB,CAAC;YAE3B,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,OAA+B,EAAE,EAAE;gBAC9D,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;oBACxB,MAAM,CAAC,cAAc,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBACxC,CAAC;qBAAM,CAAC;oBACP,MAAM,CAAC,eAAe,EAAE,CAAC,OAAO,CAAC,CAAC;gBACnC,CAAC;gBACD,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,cAAc,GAAG,SAAS,CAAC;gBAE3D,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC5B,MAAM,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,CAAC;gBAC/B,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,cAAc,GAAG,SAAS,CAAC;YAC5D,CAAC,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE;gBAC9B,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;gBAE1B,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;oBACpB,MAAM,CAAC,cAAc,EAAE,CACtB,IAAI,KAAK,CAAC,gCAAgC,QAAQ,GAAG,CAAC,CACtD,CAAC;oBACF,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,cAAc,GAAG,SAAS,CAAC;gBAC5D,CAAC;YACF,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACtB,OAAO,MAAM,CAAC;QACf,CAAC;QAED,2CAA2C;QAC3C,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;YACtC,8EAA8E;YAC9E,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACJ,CAAC;IAES,aAAa,CAAC,MAAc;QACrC,yDAAyD;QACzD,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACnC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC3B,OAAO,CAAC,MAAM,CAAC,CAAC;gBAChB,OAAO;YACR,CAAC;QACF,CAAC;QAED,sCAAsC;QACtC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAES,YAAY,CAAC,MAAc;QACpC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEzB,kFAAkF;QAClF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAChC,CAAC;IACF,CAAC;IAEM,KAAK,CAAC,cAAc,CAC1B,QAAgB;QAGhB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAE/C,OAAO,IAAI,OAAO,CAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC5D,MAAM,CAAC,eAAe,GAAG,OAAO,CAAC;YACjC,MAAM,CAAC,cAAc,GAAG,MAAM,CAAC;YAC/B,MAAM,CAAC,WAAW,CAAC,QAAwC,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IACJ,CAAC;CAGD"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=minify-html-file-worker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"minify-html-file-worker.d.ts","sourceRoot":"","sources":["../src/minify-html-file-worker.ts"],"names":[],"mappings":""}
@@ -1,16 +0,0 @@
1
- import { isMainThread, workerData as minifyHTMLOptions, parentPort, } from "node:worker_threads";
2
- import { minifyHTMLFile } from "./minify-html-file.js";
3
- if (isMainThread) {
4
- throw new Error("Not a worker thread.");
5
- }
6
- // biome-ignore-start lint/style/noNonNullAssertion: I can assume `parentPort` is not null.
7
- parentPort.on("message", async (htmlFile) => {
8
- try {
9
- parentPort.postMessage((await minifyHTMLFile(htmlFile, minifyHTMLOptions)));
10
- }
11
- catch (error) {
12
- parentPort.postMessage({ error });
13
- }
14
- });
15
- // biome-ignore-end lint/style/noNonNullAssertion: See start.
16
- //# sourceMappingURL=minify-html-file-worker.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"minify-html-file-worker.js","sourceRoot":"","sources":["../src/minify-html-file-worker.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,YAAY,EACZ,UAAU,IAAI,iBAAiB,EAC/B,UAAU,GACV,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAMvD,IAAI,YAAY,EAAE,CAAC;IAClB,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;AACzC,CAAC;AAED,2FAA2F;AAC3F,UAAW,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,QAA+B,EAAE,EAAE;IACnE,IAAI,CAAC;QACJ,UAAW,CAAC,WAAW,CACtB,CAAC,MAAM,cAAc,CACpB,QAAQ,EACR,iBAAiB,CACjB,CAAkC,CACnC,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,UAAW,CAAC,WAAW,CAAC,EAAE,KAAK,EAAmC,CAAC,CAAC;IACrE,CAAC;AACF,CAAC,CAAC,CAAC;AACH,6DAA6D"}
@@ -1,7 +0,0 @@
1
- import { type MinifierOptions as MinifyHTMLOptions } from "html-minifier-next";
2
- export interface MinifyHTMLFileResult {
3
- savings: number;
4
- time: number;
5
- }
6
- export declare function minifyHTMLFile(htmlFile: string, minifyHTMLOptions: MinifyHTMLOptions, signal?: AbortSignal): Promise<MinifyHTMLFileResult>;
7
- //# sourceMappingURL=minify-html-file.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"minify-html-file.d.ts","sourceRoot":"","sources":["../src/minify-html-file.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,eAAe,IAAI,iBAAiB,EAEzC,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,oBAAoB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,wBAAsB,cAAc,CACnC,QAAQ,EAAE,MAAM,EAChB,iBAAiB,EAAE,iBAAiB,EACpC,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,oBAAoB,CAAC,CAsB/B"}
@@ -1,22 +0,0 @@
1
- import { readFile, writeFile } from "node:fs/promises";
2
- import { minify as minifyHTML, } from "html-minifier-next";
3
- export async function minifyHTMLFile(htmlFile, minifyHTMLOptions, signal) {
4
- const timeStart = performance.now(); // --- TIMED BLOCK START ---
5
- const html = await readFile(htmlFile, {
6
- encoding: "utf8",
7
- signal,
8
- });
9
- const minifiedHTML = await minifyHTML(html, minifyHTMLOptions);
10
- const savings = Buffer.byteLength(html) - Buffer.byteLength(minifiedHTML);
11
- if (savings > 0) {
12
- // Only write the minified HTML to the file if it's smaller.
13
- await writeFile(htmlFile, minifiedHTML, {
14
- encoding: "utf8",
15
- signal,
16
- });
17
- }
18
- const timeEnd = performance.now(); // --- TIMED BLOCK END ---
19
- const time = timeEnd - timeStart;
20
- return { savings, time };
21
- }
22
- //# sourceMappingURL=minify-html-file.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"minify-html-file.js","sourceRoot":"","sources":["../src/minify-html-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAEN,MAAM,IAAI,UAAU,GACpB,MAAM,oBAAoB,CAAC;AAO5B,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,QAAgB,EAChB,iBAAoC,EACpC,MAAoB;IAEpB,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,4BAA4B;IAEjE,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE;QACrC,QAAQ,EAAE,MAAM;QAChB,MAAM;KACN,CAAC,CAAC;IACH,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;IAE/D,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IAC1E,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QACjB,4DAA4D;QAC5D,MAAM,SAAS,CAAC,QAAQ,EAAE,YAAY,EAAE;YACvC,QAAQ,EAAE,MAAM;YAChB,MAAM;SACN,CAAC,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,0BAA0B;IAE7D,MAAM,IAAI,GAAG,OAAO,GAAG,SAAS,CAAC;IACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC1B,CAAC"}
@@ -1,123 +0,0 @@
1
- import { Worker } from "node:worker_threads";
2
- import type { MinifierOptions as MinifyHTMLOptions } from "html-minifier-next";
3
- import type { MinifyHTMLFileResult } from "./minify-html-file.js";
4
-
5
- interface MinifyHTMLFileWorker extends Worker {
6
- _currentResolve?: (result: MinifyHTMLFileResult) => void;
7
- _currentReject?: (error: unknown) => void;
8
- }
9
-
10
- export type MinifyHTMLWorkerInput = string;
11
- export type MinifyHTMLWorkerOutput = MinifyHTMLFileResult | { error: unknown };
12
-
13
- export class MinifyHTMLFileWorkerPool {
14
- protected maxWorkers: number;
15
- protected minifyHTMLOptions: MinifyHTMLOptions;
16
-
17
- protected workerUrl: URL;
18
- protected pool: Set<Worker>;
19
- protected idle: Worker[];
20
- protected queue: ((value: Worker) => void)[];
21
-
22
- constructor(maxWorkers: number, minifyHTMLOptions: MinifyHTMLOptions) {
23
- this.maxWorkers = maxWorkers;
24
- this.minifyHTMLOptions = minifyHTMLOptions;
25
-
26
- this.workerUrl = new URL("./minify-html-file-worker.js", import.meta.url);
27
- this.pool = new Set();
28
- this.idle = [];
29
- this.queue = [];
30
- }
31
-
32
- protected async getAvailableWorker(): Promise<MinifyHTMLFileWorker> {
33
- // If there is an idle worker, use it.
34
- if (this.idle.length) {
35
- const worker = this.idle.shift();
36
- if (worker !== undefined) {
37
- return worker;
38
- }
39
- }
40
-
41
- // If we can create a new worker, do so.
42
- if (this.pool.size < this.maxWorkers) {
43
- const worker = new Worker(this.workerUrl, {
44
- workerData: this.minifyHTMLOptions,
45
- }) as MinifyHTMLFileWorker;
46
-
47
- worker.on("message", async (message: MinifyHTMLWorkerOutput) => {
48
- if ("error" in message) {
49
- worker._currentReject?.(message.error);
50
- } else {
51
- worker._currentResolve?.(message);
52
- }
53
- worker._currentResolve = worker._currentReject = undefined;
54
-
55
- this.releaseWorker(worker);
56
- });
57
-
58
- worker.on("error", (error) => {
59
- worker._currentReject?.(error);
60
- worker._currentResolve = worker._currentReject = undefined;
61
- });
62
-
63
- worker.on("exit", (exitCode) => {
64
- this.removeWorker(worker);
65
-
66
- if (exitCode !== 0) {
67
- worker._currentReject?.(
68
- new Error(`Worker failed with exit code ${exitCode}.`),
69
- );
70
- worker._currentResolve = worker._currentReject = undefined;
71
- }
72
- });
73
-
74
- this.pool.add(worker);
75
- return worker;
76
- }
77
-
78
- // Otherwise, wait for a worker to free up.
79
- return new Promise<Worker>((resolve) => {
80
- // When a worker frees up, they will check the queue and resolve this promise.
81
- this.queue.push(resolve);
82
- });
83
- }
84
-
85
- protected releaseWorker(worker: Worker): void {
86
- // If there is a queued request for a worker, resolve it.
87
- if (this.queue.length) {
88
- const resolve = this.queue.shift();
89
- if (resolve !== undefined) {
90
- resolve(worker);
91
- return;
92
- }
93
- }
94
-
95
- // Otherwise, keep the worker as idle.
96
- this.idle.push(worker);
97
- }
98
-
99
- protected removeWorker(worker: Worker): void {
100
- this.pool.delete(worker);
101
-
102
- // If a worker is force stopped by the system, it might still be in the idle list.
103
- const idleIndex = this.idle.indexOf(worker);
104
- if (idleIndex !== -1) {
105
- this.idle.splice(idleIndex, 1);
106
- }
107
- }
108
-
109
- public async minifyHTMLFile(
110
- htmlFile: string,
111
- // TODO: Signal?
112
- ): Promise<MinifyHTMLFileResult> {
113
- const worker = await this.getAvailableWorker();
114
-
115
- return new Promise<MinifyHTMLFileResult>((resolve, reject) => {
116
- worker._currentResolve = resolve;
117
- worker._currentReject = reject;
118
- worker.postMessage(htmlFile satisfies MinifyHTMLWorkerInput);
119
- });
120
- }
121
-
122
- // TODO: Destroy function
123
- }
@@ -1,29 +0,0 @@
1
- import {
2
- isMainThread,
3
- workerData as minifyHTMLOptions,
4
- parentPort,
5
- } from "node:worker_threads";
6
- import { minifyHTMLFile } from "./minify-html-file.js";
7
- import type {
8
- MinifyHTMLWorkerInput,
9
- MinifyHTMLWorkerOutput,
10
- } from "./minify-html-file-worker-pool.js";
11
-
12
- if (isMainThread) {
13
- throw new Error("Not a worker thread.");
14
- }
15
-
16
- // biome-ignore-start lint/style/noNonNullAssertion: I can assume `parentPort` is not null.
17
- parentPort!.on("message", async (htmlFile: MinifyHTMLWorkerInput) => {
18
- try {
19
- parentPort!.postMessage(
20
- (await minifyHTMLFile(
21
- htmlFile,
22
- minifyHTMLOptions,
23
- )) satisfies MinifyHTMLWorkerOutput,
24
- );
25
- } catch (error) {
26
- parentPort!.postMessage({ error } satisfies MinifyHTMLWorkerOutput);
27
- }
28
- });
29
- // biome-ignore-end lint/style/noNonNullAssertion: See start.
@@ -1,38 +0,0 @@
1
- import { readFile, writeFile } from "node:fs/promises";
2
- import {
3
- type MinifierOptions as MinifyHTMLOptions,
4
- minify as minifyHTML,
5
- } from "html-minifier-next";
6
-
7
- export interface MinifyHTMLFileResult {
8
- savings: number;
9
- time: number;
10
- }
11
-
12
- export async function minifyHTMLFile(
13
- htmlFile: string,
14
- minifyHTMLOptions: MinifyHTMLOptions,
15
- signal?: AbortSignal,
16
- ): Promise<MinifyHTMLFileResult> {
17
- const timeStart = performance.now(); // --- TIMED BLOCK START ---
18
-
19
- const html = await readFile(htmlFile, {
20
- encoding: "utf8",
21
- signal,
22
- });
23
- const minifiedHTML = await minifyHTML(html, minifyHTMLOptions);
24
-
25
- const savings = Buffer.byteLength(html) - Buffer.byteLength(minifiedHTML);
26
- if (savings > 0) {
27
- // Only write the minified HTML to the file if it's smaller.
28
- await writeFile(htmlFile, minifiedHTML, {
29
- encoding: "utf8",
30
- signal,
31
- });
32
- }
33
-
34
- const timeEnd = performance.now(); // --- TIMED BLOCK END ---
35
-
36
- const time = timeEnd - timeStart;
37
- return { savings, time };
38
- }