lightweight-router 1.0.4 → 1.0.6

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 CHANGED
@@ -34,6 +34,10 @@ Example:
34
34
  ```javascript
35
35
  import { startRouter } from "lightweight-router";
36
36
 
37
+ startRouter()
38
+
39
+ //or with your callback
40
+
37
41
  startRouter({
38
42
  onRouteChange: currentRoute => {
39
43
  console.log("Route changed:", currentRoute);
@@ -55,7 +59,7 @@ You can also directly import the minified version of the router in your HTML fil
55
59
  </head>
56
60
  <body>
57
61
  <!-- Your website content -->
58
- <script src="path/to/dist/router.min.js"></script>
62
+ <script src="path/to/router.ultramin.js"></script>
59
63
  </body>
60
64
  </html>
61
65
  ```
@@ -88,9 +92,39 @@ Your website content
88
92
  </script>
89
93
  ```
90
94
 
95
+ ## Prefetching
96
+
97
+ By default, links are prefetched when they get in the user's screen using an `IntersectionObserver`. This ensures that the content is loaded in the background before the user clicks on the link, providing a smoother navigation experience.
98
+ This behaviour is automatically disabled if the user has data saving preferences.
99
+
100
+
101
+ If you have too many links at once or too many requests, you can add the `prefetch="onHover"` attribute to your links or some of them (usually links to huge pages that are not often visited):
102
+
103
+ ```html
104
+ <a href="/archive" prefetch="onHover">Archive</a>
105
+ ```
106
+
107
+ P.S. you can easily test in your website by pasting the ultra minified version into the console.
108
+ The minified version was created with uglify-js, clean.css and then ultra minified with https://packjs.com
109
+ The size of the gzipped version was calculated with: https://dafrok.github.io/gzip-size-online/
110
+ It's worth to note that nonetheless Terser give better results than uglify-js. The final uglify version packed by packjs.com was even smaller.
111
+
112
+ ## Browser Support
113
+
114
+ The router supports all modern browsers. Required features:
115
+
116
+ - IntersectionObserver
117
+ - Fetch API
118
+ - History API
119
+
120
+ For older browsers, consider using the following polyfills:
121
+
122
+ - intersection-observer
123
+ - whatwg-fetch
124
+
91
125
  ## Server Configuration
92
126
 
93
- Configuring your server to return only the route content can make the router much more efficient. Instead of returning the entire page, the server should return only the content for the requested route when it detects a request with the message "onlyRoute".
127
+ Configuring your server to return only the route content can make the router much more efficient. Instead of returning the entire page, the server could return only the content for the requested route when it detects a request with the message "onlyRoute".
94
128
 
95
129
  ```javascript
96
130
  await fetch(url, { method: "POST", body: "onlyRoute" });
@@ -123,35 +157,6 @@ Right now errors are shown without styling as the content of the page.
123
157
 
124
158
  Soon there will be a DenoJS library that will help you deal with all these routes stuff. It will also come with api routes functionality 🔥
125
159
 
126
- ## Prefetching
127
-
128
- By default, links are prefetched when they get in the user's screen using an `IntersectionObserver`. This ensures that the content is loaded in the background before the user clicks on the link, providing a smoother navigation experience.
129
-
130
- If you have too many links at once or too many requests, you can add the `prefetch="onHover"` attribute to your links or some of them (usually links to huge pages that are not often visited):
131
-
132
- ```html
133
- <a href="/archive" prefetch="onHover">Archive</a>
134
- ```
135
-
136
- P.S. you can easily test in your website by pasting this minified version into the console.
137
-
138
- The minified version was created with uglify-js, clean.css and then minified again with https://packjs.com
139
- The size of the gzipped version was calculated with: https://dafrok.github.io/gzip-size-online/
140
- It's worth to note that nonethewise Terser give better results than uglify-js. The final uglify version packed by packjs.com was even smaller.
141
-
142
- ## Browser Support
143
-
144
- The router supports all modern browsers. Required features:
145
-
146
- - IntersectionObserver
147
- - Fetch API
148
- - History API
149
-
150
- For older browsers, consider using the following polyfills:
151
-
152
- - intersection-observer
153
- - whatwg-fetch
154
-
155
160
  ## Performance Tips
156
161
 
157
162
  - Use `content-visibility: auto` on route elements to improve rendering performance
@@ -1 +1 @@
1
- (()=>{let c={},n=async()=>{var e=document.querySelector("router"),t=globalThis.location.pathname;let o=e.querySelector(`route[path="${t}"]`),n=(o||((o=document.createElement("route")).setAttribute("path",globalThis.location.pathname),e.appendChild(o)),document.body.classList.add("loading"),c[globalThis.location.href]);n||(n=await d(globalThis.location.href),c[globalThis.location.href]=n);var r,a=(new DOMParser).parseFromString(n,"text/html"),i=a.querySelector("title"),i=(i&&(document.title=i.textContent),o.innerHTML=a.body.innerHTML,Array.from(o.querySelectorAll("script")));for(r of i){var l=document.createElement("script");r.src?l.src=r.src:l.textContent=r.textContent,r.parentNode.replaceChild(l,r)}e.querySelectorAll("route").forEach(e=>e.style.display="none"),o.style.display="contents",document.body.classList.remove("loading"),window.scrollTo(0,0),s&&s(t)},r=async e=>{c[e.href]||(c[e.href]=await d(e.href))},a=(e,t)=>{e.forEach(e=>{e.isIntersecting&&(e=e.target,c[e.href]||(r(e),t.unobserve(e)))})},i=e=>{var t=e.target.closest("A");t&&t.href&&l(t.href)&&t.origin===location.origin&&(e.preventDefault(),globalThis.history.pushState(null,null,t.href),globalThis.dispatchEvent(new Event("popstate")))};function l(e){if(e&&!e.startsWith("#")&&!e.startsWith("javascript:")){if(e.startsWith("/"))return 1;try{var t=new URL(e,window.location.origin),o=new URL(window.location.href);return o.hostname.replace(/^www\./,"")===t.hostname.replace(/^www\./,"")?o.pathname!==t.pathname||!t.hash:void 0}catch{}}}let s,d=async e=>{e=await t(e);return e.ok?e.text():"Couldn't fetch the route - HTTP error! status: "+e.status},t=async e=>{if(!h){var t=await fetch(e,{method:"POST",body:"onlyRoute"});if(t.ok)return t}return fetch(e)},h=!1,e=(e={})=>{var t,e=e.onRouteChange,e=(e&&(e=e,s=e),document.createElement("style")),e=(e.textContent="body.loading{animation:pulseOpacity 1s infinite alternate}@keyframes pulseOpacity{from{opacity:.8}to{opacity:.3}}",document.head.appendChild(e),document.querySelector("router")),o=globalThis.location.pathname,o=(e||(e=document.createElement("router"),(t=document.createElement("route")).setAttribute("path",o),t.style.contentVisibility="auto",t.innerHTML=document.body.innerHTML,e.appendChild(t),document.body.innerHTML="",document.body.appendChild(e),h=!0),globalThis.addEventListener("popstate",n),document.addEventListener("click",i),document.body.addEventListener("mouseover",e=>{"A"===e.target.tagName&&"onHover"===e.target.getAttribute("prefetch")&&(async e=>{e=e.target;!c[e.href]&&l(e.href)&&await r(e)})(e)}),new IntersectionObserver(a,{root:null,threshold:.5}));(t=>{let o=navigator.connection&&navigator.connection.saveData;document.querySelectorAll("a").forEach(e=>{"onHover"===e.getAttribute("prefetch")||o||l(e.href)||t.observe(e)})})(o)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>e()):e()})();
1
+ (()=>{let c={},n=async()=>{var e=document.querySelector("router"),t=globalThis.location.pathname;let o=e.querySelector(`route[path="${t}"]`),n=(o||((o=document.createElement("route")).setAttribute("path",globalThis.location.pathname),e.appendChild(o)),document.body.classList.add("loading"),c[globalThis.location.href]);n||(n=await d(globalThis.location.href),c[globalThis.location.href]=n);var r,a=(new DOMParser).parseFromString(n,"text/html"),i=a.querySelector("title"),i=(i&&(document.title=i.textContent),o.innerHTML=a.body.innerHTML,Array.from(o.querySelectorAll("script")));for(r of i){var l=document.createElement("script");r.src?l.src=r.src:l.textContent=r.textContent,r.parentNode.replaceChild(l,r)}e.querySelectorAll("route").forEach(e=>e.style.display="none"),o.style.display="contents",document.body.classList.remove("loading"),window.scrollTo(0,0),s&&s(t)},r=async e=>{c[e.href]||(c[e.href]=await d(e.href))},a=(e,t)=>{e.forEach(e=>{e.isIntersecting&&(e=e.target,c[e.href]||(r(e),t.unobserve(e)))})},i=e=>{var t=e.target.closest("A");t&&t.href&&l(t.href)&&t.origin===location.origin&&(e.preventDefault(),globalThis.history.pushState(null,null,t.href),globalThis.dispatchEvent(new Event("popstate")))};function l(e){if(e&&!e.startsWith("#")&&!e.startsWith("javascript:")){if(e.startsWith("/"))return 1;try{var t=new URL(e,window.location.origin),o=new URL(window.location.href);return o.hostname.replace(/^www\./,"")===t.hostname.replace(/^www\./,"")?o.pathname!==t.pathname||!t.hash:void 0}catch{}}}let s,d=async e=>{e=await t(e);return e.ok?e.text():"Couldn't fetch the route - HTTP error! status: "+e.status},t=async e=>{if(!h){var t=await fetch(e,{method:"POST",body:"onlyRoute"});if(t.ok)return t}return fetch(e)},h=!1,e=(e={})=>{var t,e=e.onRouteChange,e=(e&&(e=e,s=e),document.createElement("style")),e=(e.textContent=".loading{animation:pulse 1s infinite alternate}@keyframes pulse{from{opacity:.6}to{opacity:.1}}route{content-visibility:auto}",document.head.appendChild(e),document.querySelector("router")),o=globalThis.location.pathname,o=(e||(e=document.createElement("router"),(t=document.createElement("route")).setAttribute("path",o),t.innerHTML=document.body.innerHTML,e.appendChild(t),document.body.innerHTML="",document.body.appendChild(e),h=!0),globalThis.addEventListener("popstate",n),document.addEventListener("click",i),document.body.addEventListener("mouseover",e=>{"A"===e.target.tagName&&"onHover"===e.target.getAttribute("prefetch")&&(async e=>{e=e.target;!c[e.href]&&l(e.href)&&await r(e)})(e)}),new IntersectionObserver(a,{root:null,threshold:.5}));(t=>{let o=navigator.connection&&navigator.connection.saveData;document.querySelectorAll("a").forEach(e=>{"onHover"===e.getAttribute("prefetch")||o||l(e.href)||t.observe(e)})})(o)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>e()):e()})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lightweight-router",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "main": "src/router.js",
5
5
  "scripts": {
6
6
  "dev": "npx http-server src -o",
@@ -1 +1 @@
1
- s;
1
+ $="(£ì­c={},n=async£ìܵ¨¢t=êð;­¦úè(`ä[pÓh=${t}]`÷n=(oÊ((o´êð÷ú½(o)÷Æç.addöÛ³¼nÊ(n=×d(êó³=n¼Ür,a=(ÍDOMParsõ).parseF°mString(n,ýxt/html¢i=a.èötàle¢i=(iÞ(¾tàlµi.Ý÷¥î=a.¬.î,Array.f°m(¥¹Éé)¼for(r of i){Ül=ßÉé;r«?l«=r«:l.Ý=r.Ý,r.paùïNodÐChild(l,rØú¹äé.fÔ=>ú²nëeé÷¥²c¡sÑÆç.ùmo·öÛ¢Ïsc°llTo(0,0÷sÞs(tØ,r=âËÊ(Ë=×dªØ,a=ô,t)ìúfÔìúisIÀngÞôí,ËÊ(rô÷Õun®))±Ø,i=eìÜtí.closeçöAé;tÞÕóÞl(Õó)ÞÕÈÒ=lüÈÞ(úpù·ïDefault(ºhiçory.pushStaý(¸¸ÕóºdispÓchE·ï(ÍE·ïö¯é)Ø;functië lô){ifô©#é©javaÉ:é){ Öhö/é)á1;try{Üt=ÍURLô,ÏlüÈ÷¦ÍURL(Ïlüó¼á¥¤Ò=Õ¤?¥ð!ÒÕðÊ!Õhash:void 0}cÓch{}}}­s,d=âµ×tô¼áúok?úýxt£:Couldn't Ì the ä - HTTP õ°r! çÓus: +úçÓus},t=â !h){Üt=×Ìô,{mÚhod:POSTѬ:ëlyRouý}¼ Õok)át}áÌôØ,h=!1,µô={})ìÜt,µúëRouýChange,µôÞô=e,s=e÷ßçyleé÷µ(úÝ=¬.Û{animÓië:¶ 1s infiniý alýrnaý}@keyframes ¶{f°m§8}to§3}}Ѿhead.½ô÷¨é÷¦êð,¦ôÊô=ßär¢(t´o÷Õçylúc¡Visibilày=autoÑÕî=òî,ú½(t÷òî=Ñò½ô÷h=!0ºÙ¯Ñn÷¾ÙclickÑi÷òÙmouseovõÑôìAÒí.tagNameÞ»í.¿Þ(âeí;!ËÞlªÞ×rô±ô±÷ÍIÀëObsõvõ(a,{°ot:¸thùshold:.5})¼(tì­¦naÁÞnaÁ.sa·DÓa;¾¹aé.fÔì»=ú¿ÊoÊlªÊÕ®±±(oØ;ÛÒ=¾ùadyStaý?¾ÙDOMC¡LoadedÑ(£=>e£)):e(±(¼";l="if(ëýï÷()hoÂéo.o={oÎ:.¾èöärÞ!Öhö(úó).srcbodylÚ obsõ·ôpopçaýroØ)çylÇ=÷c[êó]=ßäÅÓhÑe=pulseOÎvenull,èAllö÷glû.ëHovõÒ);aãlddþgÚAåpùÌénýrsectivigÃctiëÄwww./,Óor.cëneçnamÐ(/^é).sÚAåpòclassLiúdisplayoriginscript||c[úó]fÚchnew pacàywindow.úùplace,==atorEach(ôt.úçartsWàawaà )}addEveæetloadingvar ýxtCëýï&&dñmeïöitùturn async eìppendChirouýttribuýöïLisýnõöstquõør)glû.lüon=>{=útargetinnõHTMLntpathnameþcùaýEledþbody.hùf(eer(),ySelectoree.obalThisocation.teocument.".split('');_=" ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ";for(i=0;i<95;i++){$=$.split(_[i]).join(l[i])};eval($.replace(//g,'"').replace(//g,'\\').replace(//g,String.fromCharCode(10)));
package/src/router.js CHANGED
@@ -148,13 +148,15 @@ const startRouter = (options = {}) => {
148
148
  if (onRouteChange) setRouteChangeHandler(onRouteChange);
149
149
  const style = document.createElement("style");
150
150
  style.textContent = `
151
- body.loading {
152
- animation: pulseOpacity 1s infinite alternate;
151
+ .loading {
152
+ animation: pulse 1s infinite alternate;
153
153
  }
154
-
155
- @keyframes pulseOpacity {
156
- from { opacity: 0.8; }
157
- to { opacity: 0.3; }
154
+ @keyframes pulse {
155
+ from { opacity: 0.6; }
156
+ to { opacity: 0.1; }
157
+ }
158
+ route {
159
+ content-visibility: auto;
158
160
  }
159
161
  `;
160
162
  document.head.appendChild(style);
@@ -166,7 +168,6 @@ const startRouter = (options = {}) => {
166
168
  router = document.createElement("router");
167
169
  const route = document.createElement("route");
168
170
  route.setAttribute("path", currentPath);
169
- route.style.contentVisibility = "auto";
170
171
  route.innerHTML = document.body.innerHTML;
171
172
  router.appendChild(route);
172
173
  document.body.innerHTML = "";
@@ -188,3 +189,10 @@ const startRouter = (options = {}) => {
188
189
  };
189
190
 
190
191
  export { startRouter };
192
+
193
+ // TODO: create ultra minified version or deploy
194
+ // - add support for prefetching on hover
195
+ // - add support for prefetching on click
196
+ // - add support for prefetching on scroll
197
+ // - add support for prefetching on focus
198
+ // - add support for prefetching on touch