cindel 1.0.0 → 1.0.2
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 +3 -3
- package/dist/client/file-loader.d.ts +8 -1
- package/dist/client/file-loader.d.ts.map +1 -1
- package/dist/client/hmr-client.d.ts +3 -0
- package/dist/client/hmr-client.d.ts.map +1 -1
- package/dist/client.iife.js +23 -18
- package/dist/client.iife.js.map +2 -2
- package/dist/client.iife.min.js +1 -1
- package/dist/client.iife.min.js.map +3 -3
- package/dist/client.js +23 -18
- package/dist/client.js.map +2 -2
- package/dist/index.js +20 -12
- package/dist/index.js.map +3 -3
- package/dist/server/file-watcher.d.ts.map +1 -1
- package/dist/server/hmr-server.d.ts.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/shared/constants.d.ts +6 -0
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/logger.d.ts.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
> Hot module replacement server and client with file watching, static file serving, CORS proxy and WebSocket proxy support
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/cindel)
|
|
6
|
+
[](https://bundlephobia.com/package/cindel@latest)
|
|
6
7
|
[](LICENSE)
|
|
7
|
-
[](https://bundlephobia.com/package/cindel)
|
|
8
|
-
|
|
9
8
|
---
|
|
10
9
|
|
|
11
10
|
## Features
|
|
@@ -13,10 +12,10 @@
|
|
|
13
12
|
**HMR & File Watching**
|
|
14
13
|
|
|
15
14
|
- Instant push driven HMR over WebSocket on file change
|
|
16
|
-
- Atomic CSS hot swap (no flash of unstyled content), script execution, and ES module reload
|
|
17
15
|
- Glob pattern support for watch, ignore, and cold file configuration
|
|
18
16
|
- Cold file patterns that can trigger a full page reload instead of HMR
|
|
19
17
|
- Override detection to map replacement files onto their originals
|
|
18
|
+
- Atomic CSS hot swap (no flash of unstyled content), script execution, and ES module reload
|
|
20
19
|
|
|
21
20
|
**Server**
|
|
22
21
|
|
|
@@ -399,6 +398,7 @@ process.on("SIGINT", () => server.stop().then(() => process.exit(0)));
|
|
|
399
398
|
| `autoReconnect` | `boolean` | `true` | Reconnect on disconnect with exponential backoff |
|
|
400
399
|
| `reconnectDelay` | `number` | `2000` | Base reconnect delay in ms |
|
|
401
400
|
| `maxReconnectDelay` | `number` | `30000` | Maximum reconnect delay cap in ms |
|
|
401
|
+
| `skipOnReconnect` | `boolean` | `true` | Skip files already loaded in the page when the server reconnects |
|
|
402
402
|
| `skip` | `string[]` | | Glob patterns for files to never load |
|
|
403
403
|
| `filterSkip` | `(file, allFiles) => boolean` | | Custom skip logic, OR'd with `skip` |
|
|
404
404
|
| `cold` | `string[]` | | Glob patterns that trigger a full page reload. Merged with the server's `cold` config on connect |
|
|
@@ -12,9 +12,16 @@ export class FileLoader {
|
|
|
12
12
|
timeout: number;
|
|
13
13
|
resolvers: Function[];
|
|
14
14
|
}>;
|
|
15
|
+
/**
|
|
16
|
+
* Load counter per file used for cache busting.
|
|
17
|
+
* Produces short URLs like Logger.js?v=3 which keeps
|
|
18
|
+
* browser stack traces readable.
|
|
19
|
+
* @type {Map<string, number>}
|
|
20
|
+
*/
|
|
21
|
+
versions: Map<string, number>;
|
|
15
22
|
loadFile(path: any): Promise<any>;
|
|
16
23
|
loadCSS(path: any): Promise<any>;
|
|
17
|
-
loadModule(path: any): Promise<
|
|
24
|
+
loadModule(path: any): Promise<boolean>;
|
|
18
25
|
loadScript(path: any): Promise<any>;
|
|
19
26
|
reloadFile(path: any): Promise<any>;
|
|
20
27
|
_flushReload(path: any): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-loader.d.ts","sourceRoot":"","sources":["../../src/client/file-loader.js"],"names":[],"mappings":"AAAA,mFAAmF;AACnF;IACE,
|
|
1
|
+
{"version":3,"file":"file-loader.d.ts","sourceRoot":"","sources":["../../src/client/file-loader.js"],"names":[],"mappings":"AAAA,mFAAmF;AACnF;IACE,0BAgBC;IAfC,aAAsB;IACtB;;;;;OAKG;IACH,WAFU,GAAG,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,UAAU,CAAA;KAAE,CAAC,CAEvC;IAC1B;;;;;OAKG;IACH,UAFU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAEJ;IAG3B,kCAOC;IAKD,iCAoBC;IAED,wCAIC;IAED,oCAeC;IAKD,oCAeC;IAED,uCAUC;IAED,qCAiBC;IAGD,2BAIC;CACF"}
|
|
@@ -39,6 +39,7 @@ export class HMRClient {
|
|
|
39
39
|
* @param {boolean} [options.autoReconnect=true] - Reconnect on disconnect with exponential backoff.
|
|
40
40
|
* @param {number} [options.reconnectDelay=2000] - Base reconnect delay in ms
|
|
41
41
|
* @param {number} [options.maxReconnectDelay=30000] - Maximum reconnect delay cap in ms
|
|
42
|
+
* @param {boolean} [options.skipOnReconnect=true] - Skip files already present in the page on reconnect, preventing them from being loaded again.
|
|
42
43
|
* @param {string[]} [options.skip] - Glob patterns for files that should never be loaded (e.g. `['_*\/**']`)
|
|
43
44
|
* @param {function(string, string[]): boolean} [options.filterSkip] - Custom skip logic. Receives `(filePath, allFiles)`. Combined with `skip` via OR.
|
|
44
45
|
* @param {string[]} [options.cold] - Glob patterns for files that require a full page reload. Merged with the server's `cold` config on connect. A `cold` event is emitted instead of hot reloading.
|
|
@@ -57,6 +58,7 @@ export class HMRClient {
|
|
|
57
58
|
autoReconnect?: boolean;
|
|
58
59
|
reconnectDelay?: number;
|
|
59
60
|
maxReconnectDelay?: number;
|
|
61
|
+
skipOnReconnect?: boolean;
|
|
60
62
|
skip?: string[];
|
|
61
63
|
filterSkip?: (arg0: string, arg1: string[]) => boolean;
|
|
62
64
|
cold?: string[];
|
|
@@ -72,6 +74,7 @@ export class HMRClient {
|
|
|
72
74
|
autoReconnect: boolean;
|
|
73
75
|
reconnectDelay: number;
|
|
74
76
|
maxReconnectDelay: number;
|
|
77
|
+
skipOnReconnect: boolean;
|
|
75
78
|
_coldPatterns: string[];
|
|
76
79
|
_filterCold: (arg0: string) => boolean;
|
|
77
80
|
shouldSkipFile: any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hmr-client.d.ts","sourceRoot":"","sources":["../../src/client/hmr-client.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;IACE
|
|
1
|
+
{"version":3,"file":"hmr-client.d.ts","sourceRoot":"","sources":["../../src/client/hmr-client.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;IACE;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,qBAlBG;QAAyB,KAAK,GAAtB,MAAM;QACW,OAAO,GAAxB,MAAM;QACY,UAAU,GAA5B,OAAO;QACU,IAAI,GAArB,MAAM;QACW,IAAI,GAArB,MAAM;QACY,MAAM,GAAxB,OAAO;QACW,aAAa,GAA/B,OAAO;QACU,cAAc,GAA/B,MAAM;QACW,iBAAiB,GAAlC,MAAM;QACY,eAAe,GAAjC,OAAO;QACY,IAAI,GAAvB,MAAM,EAAE;QACsC,UAAU,GAAxD,CAAS,IAAM,EAAN,MAAM,EAAE,IAAQ,EAAR,MAAM,EAAE,KAAG,OAAO;QAChB,IAAI,GAAvB,MAAM,EAAE;QAC4B,UAAU,GAA9C,CAAS,IAAM,EAAN,MAAM,KAAG,OAAO;QACyB,iBAAiB,GAAnE,CAAS,IAAM,EAAN,MAAM,EAAE,IAAQ,EAAR,MAAM,EAAE,KAAG,MAAM,GAAC,IAAI;QACN,YAAY,GAA7C,CAAS,IAAM,EAAN,MAAM,KAAG,IAAI;QACiB,SAAS,GAAhD,CAAS,IAAQ,EAAR,MAAM,EAAE,KAAG,MAAM,EAAE;KACtC,EA+DA;IAxDC,WAAkB;IAClB,aAAsB;IACtB,oBAAsB;IAEtB,+BAAyD;IACzD,uBAA+C;IAC/C,uBAAiD;IACjD,0BAAwD;IACxD,yBAAqD;IAGrD,wBAAsC;IACtC,oBAvBkB,MAAM,KAAG,OAAO,CAuBQ;IAG1C,oBAAiF;IACjF,gBAAuE;IAGvE,gBAAkB;IAElB,0BA/BkB,MAAM,QAAE,MAAM,EAAE,KAAG,MAAM,GAAC,IAAI,CA+BO;IACvD,qBA/BkB,MAAM,KAAG,IAAI,CA+Bc;IAC7C,eAAmE;IAEnE,kBAAkB;IAClB,0BAA0B;IAC1B,qBAAwB;IACxB,6BAA8B;IAC9B,gCAA2B;IAI3B,qBAAuB;IACvB,6BAAgC;IAEhC,uBAA8C;IAE9C,wEAAwE;IACxE,aADW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CACF;IAC5B,uFAAuF;IACvF,qBADW,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CACC;IAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAYC;IAGH,oCAmBC;IAED,8CAcC;IAED,mCAIC;IAED,sEAoDC;IAED,kCA0BC;IAED,4CAgDC;IAED,8EAkEC;IAED,2CA4CC;IAED,wCA6CC;IAED;;;;;OAKG;IACH,UAJW,MAAM,GAAC,QAAQ,GAAC,KAAK,GAAC,QAAQ,GAAC,MAAM,GAAC,SAAS,GAAC,YAAY,GAAC,OAAO,sBAElE,SAAS,CAQrB;IAED;;;;;OAKG;IACH,YAJW,MAAM,GAAC,QAAQ,GAAC,KAAK,GAAC,QAAQ,GAAC,MAAM,GAAC,SAAS,GAAC,YAAY,GAAC,OAAO,sBAElE,SAAS,CASrB;IAED;;;;;OAKG;IACH,WAJW,MAAM,GAAC,QAAQ,GAAC,KAAK,GAAC,QAAQ,GAAC,MAAM,GAAC,SAAS,GAAC,YAAY,GAAC,OAAO,sBAElE,SAAS,CAoBrB;IAED,uCAQC;IAMD,iCAGC;IAED,oCAWC;IAED;;;OAGG;IACH,WAFa,OAAO,CAAC,IAAI,CAAC,CAuFzB;IAED;;OAEG;IACH,mBAUC;CACF;2BAtoB0B,kBAAkB"}
|
package/dist/client.iife.js
CHANGED
|
@@ -1561,6 +1561,7 @@ var HMR = (() => {
|
|
|
1561
1561
|
constructor(httpUrl) {
|
|
1562
1562
|
this.httpUrl = httpUrl;
|
|
1563
1563
|
this.loadQueue = /* @__PURE__ */ new Map();
|
|
1564
|
+
this.versions = /* @__PURE__ */ new Map();
|
|
1564
1565
|
}
|
|
1565
1566
|
async loadFile(path) {
|
|
1566
1567
|
const isCSS = path.endsWith(".css");
|
|
@@ -1591,22 +1592,10 @@ var HMR = (() => {
|
|
|
1591
1592
|
document.head.appendChild(link);
|
|
1592
1593
|
});
|
|
1593
1594
|
}
|
|
1594
|
-
// Replace the existing module script with a cache busted URL.
|
|
1595
|
-
// Changing the URL makes the browser treat it as a new module
|
|
1596
|
-
// and execute it from scratch.
|
|
1597
1595
|
async loadModule(path) {
|
|
1598
1596
|
const url = this.makeUrl(path);
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
const script = document.createElement("script");
|
|
1602
|
-
script.type = "module";
|
|
1603
|
-
script.src = url;
|
|
1604
|
-
script.setAttribute("data-file", path);
|
|
1605
|
-
return new Promise((resolve, reject) => {
|
|
1606
|
-
script.onload = () => resolve(true);
|
|
1607
|
-
script.onerror = () => reject(new Error(`Failed to execute module: ${path}`));
|
|
1608
|
-
document.head.appendChild(script);
|
|
1609
|
-
});
|
|
1597
|
+
await import(url);
|
|
1598
|
+
return true;
|
|
1610
1599
|
}
|
|
1611
1600
|
async loadScript(path) {
|
|
1612
1601
|
const url = this.makeUrl(path);
|
|
@@ -1662,11 +1651,13 @@ var HMR = (() => {
|
|
|
1662
1651
|
el.remove();
|
|
1663
1652
|
await new Promise((r) => setTimeout(r, 0));
|
|
1664
1653
|
}
|
|
1654
|
+
this.versions.delete(path);
|
|
1665
1655
|
}
|
|
1666
|
-
//
|
|
1656
|
+
// Increment the version counter for individual files and return a versioned URL
|
|
1667
1657
|
makeUrl(path) {
|
|
1668
|
-
const
|
|
1669
|
-
|
|
1658
|
+
const v = (this.versions.get(path) ?? 0) + 1;
|
|
1659
|
+
this.versions.set(path, v);
|
|
1660
|
+
return `${this.httpUrl}${path}?v=${v}`;
|
|
1670
1661
|
}
|
|
1671
1662
|
};
|
|
1672
1663
|
|
|
@@ -1764,6 +1755,7 @@ var HMR = (() => {
|
|
|
1764
1755
|
* @param {boolean} [options.autoReconnect=true] - Reconnect on disconnect with exponential backoff.
|
|
1765
1756
|
* @param {number} [options.reconnectDelay=2000] - Base reconnect delay in ms
|
|
1766
1757
|
* @param {number} [options.maxReconnectDelay=30000] - Maximum reconnect delay cap in ms
|
|
1758
|
+
* @param {boolean} [options.skipOnReconnect=true] - Skip files already present in the page on reconnect, preventing them from being loaded again.
|
|
1767
1759
|
* @param {string[]} [options.skip] - Glob patterns for files that should never be loaded (e.g. `['_*\/**']`)
|
|
1768
1760
|
* @param {function(string, string[]): boolean} [options.filterSkip] - Custom skip logic. Receives `(filePath, allFiles)`. Combined with `skip` via OR.
|
|
1769
1761
|
* @param {string[]} [options.cold] - Glob patterns for files that require a full page reload. Merged with the server's `cold` config on connect. A `cold` event is emitted instead of hot reloading.
|
|
@@ -1783,6 +1775,7 @@ var HMR = (() => {
|
|
|
1783
1775
|
this.autoReconnect = this._autoReconnectDefault;
|
|
1784
1776
|
this.reconnectDelay = opts.reconnectDelay || 2e3;
|
|
1785
1777
|
this.maxReconnectDelay = opts.maxReconnectDelay || 3e4;
|
|
1778
|
+
this.skipOnReconnect = opts.skipOnReconnect !== false;
|
|
1786
1779
|
this._coldPatterns = opts.cold || null;
|
|
1787
1780
|
this._filterCold = opts.filterCold || null;
|
|
1788
1781
|
this.shouldSkipFile = this.makeFilter(opts.skip || null, opts.filterSkip || null);
|
|
@@ -1930,7 +1923,19 @@ var HMR = (() => {
|
|
|
1930
1923
|
skipped.forEach((f) => console.log(` \u2514\u2500 ${getFileName(f)}`));
|
|
1931
1924
|
console.groupEnd();
|
|
1932
1925
|
}
|
|
1933
|
-
|
|
1926
|
+
let toLoad = filtered;
|
|
1927
|
+
if (this.skipOnReconnect) {
|
|
1928
|
+
const alreadyLoaded = [];
|
|
1929
|
+
toLoad = [];
|
|
1930
|
+
for (const f of filtered) {
|
|
1931
|
+
const isLoaded = this.fileLoader.versions.has(f) || document.querySelector(`[data-file="${f}"]`);
|
|
1932
|
+
(isLoaded ? alreadyLoaded : toLoad).push(f);
|
|
1933
|
+
}
|
|
1934
|
+
if (alreadyLoaded.length > 0) {
|
|
1935
|
+
this.log("info", `Server reconnected - skipping ${alreadyLoaded.length} existing file${alreadyLoaded.length !== 1 ? "s" : ""}`);
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
const withOverrides = this.buildOverrideMap(toLoad);
|
|
1934
1939
|
const sorted2 = this.sortFiles(withOverrides);
|
|
1935
1940
|
this.logInitFileGroup(sorted2, this.overrideMap, this.isColdFile.bind(this));
|
|
1936
1941
|
for (const file of sorted2) {
|