@erickxavier/no-js 1.3.0 → 1.4.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/cjs/no.js +5 -5
- package/dist/cjs/no.js.map +3 -3
- package/dist/esm/no.js +5 -5
- package/dist/esm/no.js.map +3 -3
- package/dist/iife/no.js +5 -5
- package/dist/iife/no.js.map +3 -3
- package/package.json +1 -1
- package/src/dom.js +14 -0
- package/src/index.js +1 -1
- package/src/router.js +60 -0
package/package.json
CHANGED
package/src/dom.js
CHANGED
|
@@ -161,6 +161,20 @@ export async function _loadTemplateElement(tpl) {
|
|
|
161
161
|
// Content-include templates: load nested ones now.
|
|
162
162
|
if (!tpl.hasAttribute("route")) {
|
|
163
163
|
await _loadRemoteTemplates(tpl.content || tpl);
|
|
164
|
+
} else if (useCache && tpl.content) {
|
|
165
|
+
// Route templates: pre-warm HTML cache for nested subtemplates so
|
|
166
|
+
// navigation finds cache hits instead of issuing network requests.
|
|
167
|
+
// Only the HTML is fetched — no DOM processing or skeleton insertion.
|
|
168
|
+
const nested = tpl.content.querySelectorAll("template[src]");
|
|
169
|
+
const warmups = [...nested].map((sub) => {
|
|
170
|
+
const subSrc = sub.getAttribute("src");
|
|
171
|
+
const subUrl = _resolveTemplateSrc(subSrc, sub);
|
|
172
|
+
if (_templateHtmlCache.has(subUrl)) return;
|
|
173
|
+
return fetch(subUrl).then((r) => r.text()).then((h) => {
|
|
174
|
+
_templateHtmlCache.set(subUrl, h);
|
|
175
|
+
}).catch(() => {});
|
|
176
|
+
});
|
|
177
|
+
Promise.all(warmups);
|
|
164
178
|
}
|
|
165
179
|
// Remove loading placeholder once real content is ready
|
|
166
180
|
if (loadingMarker) loadingMarker.remove();
|
package/src/index.js
CHANGED
package/src/router.js
CHANGED
|
@@ -242,6 +242,63 @@ export function _createRouter() {
|
|
|
242
242
|
});
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
+
function _prefetchRoutes() {
|
|
246
|
+
const outletEls = document.querySelectorAll("[route-view]");
|
|
247
|
+
for (const outletEl of outletEls) {
|
|
248
|
+
const rawSrc = outletEl.getAttribute("src") || _config.router.templates || "";
|
|
249
|
+
if (!rawSrc) continue;
|
|
250
|
+
const baseSrc = rawSrc.replace(/\/?$/, "/");
|
|
251
|
+
const ext = outletEl.getAttribute("ext") || _config.router.ext || ".html";
|
|
252
|
+
const indexName = outletEl.getAttribute("route-index") || "index";
|
|
253
|
+
const outletName = (outletEl.getAttribute("route-view") || "").trim() || "default";
|
|
254
|
+
|
|
255
|
+
// Collect routes from links, keeping most aggressive lazy level per path
|
|
256
|
+
const routeLazy = new Map();
|
|
257
|
+
document.querySelectorAll("[route]:not([route-view])").forEach((link) => {
|
|
258
|
+
const raw = link.getAttribute("route");
|
|
259
|
+
if (!raw) return;
|
|
260
|
+
const path = raw.split("?")[0].split("#")[0];
|
|
261
|
+
const lazy = link.getAttribute("lazy");
|
|
262
|
+
const prev = routeLazy.get(path);
|
|
263
|
+
if (!routeLazy.has(path) || lazy === "priority" ||
|
|
264
|
+
(prev === "ondemand" && lazy !== "ondemand")) {
|
|
265
|
+
routeLazy.set(path, lazy);
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const priorityFetches = [];
|
|
270
|
+
const backgroundFetches = [];
|
|
271
|
+
|
|
272
|
+
for (const [path, lazy] of routeLazy) {
|
|
273
|
+
if (lazy === "ondemand" || path === current.path) continue;
|
|
274
|
+
const segment = path === "/" ? indexName : path.replace(/^\//, "");
|
|
275
|
+
const fullSrc = baseSrc + segment + ext;
|
|
276
|
+
const cacheKey = outletName + ":" + fullSrc;
|
|
277
|
+
if (_autoTemplateCache.has(cacheKey)) continue;
|
|
278
|
+
|
|
279
|
+
const tpl = document.createElement("template");
|
|
280
|
+
tpl.setAttribute("src", fullSrc);
|
|
281
|
+
tpl.setAttribute("route", path);
|
|
282
|
+
document.body.appendChild(tpl);
|
|
283
|
+
_autoTemplateCache.set(cacheKey, tpl);
|
|
284
|
+
_log("[ROUTER] Prefetch:", path, "→", fullSrc, lazy === "priority" ? "(priority)" : "(background)");
|
|
285
|
+
|
|
286
|
+
if (outletEl.hasAttribute("i18n-ns")) {
|
|
287
|
+
tpl.setAttribute("i18n-ns", segment);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (lazy === "priority") priorityFetches.push(tpl);
|
|
291
|
+
else backgroundFetches.push(tpl);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (priorityFetches.length || backgroundFetches.length) {
|
|
295
|
+
Promise.all(priorityFetches.map(_loadTemplateElement)).then(() => {
|
|
296
|
+
backgroundFetches.forEach(_loadTemplateElement);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
245
302
|
const router = {
|
|
246
303
|
get current() {
|
|
247
304
|
return current;
|
|
@@ -333,6 +390,9 @@ export function _createRouter() {
|
|
|
333
390
|
window.location.pathname.replace(_config.router.base, "") || "/";
|
|
334
391
|
await navigate(path, true);
|
|
335
392
|
}
|
|
393
|
+
|
|
394
|
+
// Prefetch route templates declared via <a route> links
|
|
395
|
+
_prefetchRoutes();
|
|
336
396
|
},
|
|
337
397
|
};
|
|
338
398
|
|