vanilla-jet 1.4.1 → 1.4.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/CHANGELOG.md +10 -1
- package/README.md +2 -2
- package/ROADMAP_INTEGRAL.md +1 -1
- package/framework/dipper.js +32 -2
- package/framework/router.js +1 -14
- package/gulpfile.js +4 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable project changes are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format follows a structure inspired by Keep a Changelog and semantic versioning.
|
|
6
6
|
|
|
7
|
+
## [1.4.2] - 2026-02-19
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Version bump to 1.4.2.
|
|
12
|
+
|
|
7
13
|
## [1.4.1] - 2026-02-19
|
|
8
14
|
|
|
9
15
|
### Highlights (v1.4.1)
|
|
@@ -11,9 +17,11 @@ The format follows a structure inspired by Keep a Changelog and semantic version
|
|
|
11
17
|
- Completed HU 2.1 (`Fast path de estaticos en Node`).
|
|
12
18
|
- Optimized static serving in `framework/router.js`:
|
|
13
19
|
- Added warm-path static resolution cache (`route + accept-encoding`) to avoid repeated candidate resolution work.
|
|
14
|
-
-
|
|
20
|
+
- Keeps strict conditional metadata revalidation so content changes are visible on reload without stale `304`.
|
|
15
21
|
- Consolidated static header assembly and reused mime header maps.
|
|
16
22
|
- Kept stream-based delivery for large assets and tuned `createReadStream` chunk size.
|
|
23
|
+
- Added asset URL versioning in `framework/dipper.js` (`?v=size-mtime`) for local scripts/styles.
|
|
24
|
+
- Updated `gulp dev` watch flow so JS/CSS recompiles also trigger template compilation and refresh asset URLs in HTML.
|
|
17
25
|
- Added reproducible local benchmark:
|
|
18
26
|
- New script: `npm run benchmark:static`.
|
|
19
27
|
- New guide: `docs/benchmark-static.md`.
|
|
@@ -103,4 +111,5 @@ The format follows a structure inspired by Keep a Changelog and semantic version
|
|
|
103
111
|
[1.3.4]: https://github.com/nalancer08/VanillaJet/releases/tag/v1.3.4
|
|
104
112
|
[1.3.5]: https://github.com/nalancer08/VanillaJet/releases/tag/v1.3.5
|
|
105
113
|
[1.3.6]: https://github.com/nalancer08/VanillaJet/releases/tag/v1.3.6
|
|
114
|
+
[1.4.2]: https://github.com/nalancer08/VanillaJet/releases/tag/v1.4.2
|
|
106
115
|
[1.4.1]: https://github.com/nalancer08/VanillaJet/releases/tag/v1.4.1
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Node.js framework for building SPA applications with a JS/CSS/HTML build pipelin
|
|
|
6
6
|
|
|
7
7
|
## Current version
|
|
8
8
|
|
|
9
|
-
- Version: `1.4.
|
|
9
|
+
- Version: `1.4.2`
|
|
10
10
|
- Changelog: see [`CHANGELOG.md`](./CHANGELOG.md)
|
|
11
11
|
- Improvement plan (performance and backward compatibility): see `ROADMAP_INTEGRAL.md`
|
|
12
12
|
|
|
@@ -125,7 +125,7 @@ Behavior details:
|
|
|
125
125
|
Static serving includes a warm-path optimization focused on Node runtime latency:
|
|
126
126
|
|
|
127
127
|
- Reuses static resolution for repeated requests (`route + accept-encoding`).
|
|
128
|
-
-
|
|
128
|
+
- Keeps conditional revalidation (`ETag`/`Last-Modified`) strict so reload reflects changes immediately.
|
|
129
129
|
- Keeps streaming strategy for large assets (`fs.createReadStream`) with tuned chunk size.
|
|
130
130
|
- Preserves conditional cache behavior (`ETag`/`Last-Modified` + `304`) and precompressed fallback contract.
|
|
131
131
|
|
package/ROADMAP_INTEGRAL.md
CHANGED
|
@@ -117,7 +117,7 @@ Cada historia incluye su ciclo completo: fases, tareas, entregables, metricas, c
|
|
|
117
117
|
|
|
118
118
|
## EPIC 2 - Performance Node + DX de compilacion (foco actual)
|
|
119
119
|
|
|
120
|
-
### HU 2.1 - Fast path de estaticos en Node (completada `v1.4.
|
|
120
|
+
### HU 2.1 - Fast path de estaticos en Node (completada `v1.4.2`)
|
|
121
121
|
|
|
122
122
|
#### Fases
|
|
123
123
|
- F1: profiling de request estatico.
|
package/framework/dipper.js
CHANGED
|
@@ -93,12 +93,12 @@ Dipper.prototype.img = function(filename) {
|
|
|
93
93
|
|
|
94
94
|
Dipper.prototype.script = function(filename) {
|
|
95
95
|
let dir = this.getDir('scripts', false);
|
|
96
|
-
return this.
|
|
96
|
+
return this.versionedUrl(dir + filename);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
Dipper.prototype.style = function(filename) {
|
|
100
100
|
let dir = this.getDir('styles', false);
|
|
101
|
-
return this.
|
|
101
|
+
return this.versionedUrl(dir + filename);;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
Dipper.prototype.pdf = function(filename) {
|
|
@@ -128,6 +128,36 @@ Dipper.prototype.urlTo = function (route) {
|
|
|
128
128
|
return '/' + route.replace(/^\/+/, '');
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
+
Dipper.prototype.versionedUrl = function(route) {
|
|
132
|
+
const fs = require('fs');
|
|
133
|
+
const path = require('path');
|
|
134
|
+
const normalizedUrl = this.urlTo(route);
|
|
135
|
+
|
|
136
|
+
// External URLs should remain untouched.
|
|
137
|
+
if (/^(?:[a-z][a-z0-9+.-]*:)?\/\//i.test(normalizedUrl)) {
|
|
138
|
+
return normalizedUrl;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
const filePath = path.join(this.processCwd(), normalizedUrl.replace(/^\//, ''));
|
|
143
|
+
const stats = fs.statSync(filePath);
|
|
144
|
+
if (!stats.isFile()) {
|
|
145
|
+
return normalizedUrl;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const version = `${stats.size}-${Math.floor(stats.mtimeMs)}`;
|
|
149
|
+
return this.appendQueryParam(normalizedUrl, 'v', version);
|
|
150
|
+
} catch (err) {
|
|
151
|
+
// If file does not exist yet, keep legacy behavior.
|
|
152
|
+
return normalizedUrl;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
Dipper.prototype.appendQueryParam = function(url, key, value) {
|
|
157
|
+
const separator = url.includes('?') ? '&' : '?';
|
|
158
|
+
return `${url}${separator}${key}=${encodeURIComponent(value)}`;
|
|
159
|
+
}
|
|
160
|
+
|
|
131
161
|
Dipper.prototype.registerStyle = function(
|
|
132
162
|
name, url, requires,
|
|
133
163
|
cdn = false, async = false,
|
package/framework/router.js
CHANGED
|
@@ -20,7 +20,6 @@ class Router {
|
|
|
20
20
|
this.staticMetadataCache = new Map();
|
|
21
21
|
this.staticResolutionCache = new Map();
|
|
22
22
|
this.staticFileWatchers = new Map();
|
|
23
|
-
this.staticMetadataMaxAgeMs = 1000;
|
|
24
23
|
this.staticStreamChunkSize = 128 * 1024;
|
|
25
24
|
this.mimes = {
|
|
26
25
|
'png': 'image/png',
|
|
@@ -170,10 +169,6 @@ class Router {
|
|
|
170
169
|
return callback(null, cachedMetadata);
|
|
171
170
|
}
|
|
172
171
|
|
|
173
|
-
if (cachedMetadata && forceRefresh && !obj.shouldRefreshConditionalMetadata(cachedMetadata)) {
|
|
174
|
-
return callback(null, cachedMetadata);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
172
|
fs.stat(filename, (err, stats) => {
|
|
178
173
|
if (err || !stats.isFile()) {
|
|
179
174
|
return callback(err || new Error('File not found'));
|
|
@@ -182,8 +177,7 @@ class Router {
|
|
|
182
177
|
let metadata = {
|
|
183
178
|
size: stats.size,
|
|
184
179
|
lastModified: stats.mtime.toUTCString(),
|
|
185
|
-
etag: `W/"${stats.size}-${Math.floor(stats.mtimeMs)}"
|
|
186
|
-
cachedAt: Date.now()
|
|
180
|
+
etag: `W/"${stats.size}-${Math.floor(stats.mtimeMs)}"`
|
|
187
181
|
};
|
|
188
182
|
|
|
189
183
|
obj.staticMetadataCache.set(filename, metadata);
|
|
@@ -268,13 +262,6 @@ class Router {
|
|
|
268
262
|
return `${route}|${normalizedEncodings}`;
|
|
269
263
|
}
|
|
270
264
|
|
|
271
|
-
shouldRefreshConditionalMetadata(metadata) {
|
|
272
|
-
if (!metadata || !metadata.cachedAt) {
|
|
273
|
-
return true;
|
|
274
|
-
}
|
|
275
|
-
return Date.now() - metadata.cachedAt > this.staticMetadataMaxAgeMs;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
265
|
buildStaticHeaders(extHeader, candidates, contentEncoding, metadata) {
|
|
279
266
|
let staticHeaders = Object.assign({}, extHeader);
|
|
280
267
|
if (contentEncoding) {
|
package/gulpfile.js
CHANGED
|
@@ -123,7 +123,8 @@ function watchFiles(cb) {
|
|
|
123
123
|
// Watch LESS files
|
|
124
124
|
watch([`${base}/assets/styles/less/**/*.less`], gulp.series(
|
|
125
125
|
buildLess,
|
|
126
|
-
compressCss
|
|
126
|
+
compressCss,
|
|
127
|
+
compileTemplates
|
|
127
128
|
));
|
|
128
129
|
|
|
129
130
|
// Watch HTML files
|
|
@@ -138,7 +139,8 @@ function watchFiles(cb) {
|
|
|
138
139
|
uglifyJs,
|
|
139
140
|
concatJs,
|
|
140
141
|
cleanMinified,
|
|
141
|
-
compressJs
|
|
142
|
+
compressJs,
|
|
143
|
+
compileTemplates
|
|
142
144
|
));
|
|
143
145
|
|
|
144
146
|
cb();
|