├── .gitignore
├── README.md
├── beneficiary.html
├── build
└── build.js
├── icons
├── icon-alarm.svg
├── icon-cow.svg
└── icon-wheelchair.svg
├── index.html
├── index.njk
├── package-lock.json
├── package.json
├── script
└── enhance-icons.js
├── styles
└── style.css
└── sw.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Icons! Cached!
2 |
3 | I wrote that inlining your <svg>
icons makes for the best icon system. Scott Jehl wrote that just because you inline something doesn't mean you can't cache it. Let's see if Scott's idea can extend to SVG icons.
4 |
5 | [Demo Site](https://serene-sinoussi-3d0c1f.netlify.com/)
6 |
7 | ## Needs a server...
8 |
9 | This works on macOS:
10 |
11 | ```
12 | php -S localhost:2222
13 | ```
14 |
15 | ## Build
16 |
17 | There is a wildly simple build step here:
18 |
19 | ```
20 | node build/build.js
21 | ```
22 |
23 | It's just so that the SVG icons can be included and not duplicated needlessly.
24 |
--------------------------------------------------------------------------------
/beneficiary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
I wrote that inlining your <svg>
icons makes for the best icon system. Scott Jehl wrote that just because you inline something doesn't mean you can't cache it. Let's see if Scott's idea can extend to SVG icons.
Here's the GitHub Repo.
16 | 17 |This page benefits from the caching, where as this one cached the stuff.
20 | 21 | 24 | 27 | 30 | 31 |You could definitely get fancier with this, with cookies or something to determine whether or not to display the inline SVG and cache it, or if you know they are cached and can show the <use>
stuff.
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/build/build.js:
--------------------------------------------------------------------------------
1 | var nunjucks = require("nunjucks");
2 | var fs = require("fs");
3 |
4 | fs.writeFile("index.html", nunjucks.render("index.njk"), function(err, data) {
5 | if (err) console.log(err);
6 | console.log("Compiled the Nunjucks, captain.");
7 | });
8 |
--------------------------------------------------------------------------------
/icons/icon-alarm.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/icons/icon-cow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/icons/icon-wheelchair.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
I wrote that inlining your <svg>
icons makes for the best icon system. Scott Jehl wrote that just because you inline something doesn't mean you can't cache it. Let's see if Scott's idea can extend to SVG icons.
Here's the GitHub Repo.
16 | 17 |This page does the caching, whereas this one benefits from said caching.
20 | 21 | 24 | 25 | 28 | 29 | 32 | 33 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /index.njk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |I wrote that inlining your <svg>
icons makes for the best icon system. Scott Jehl wrote that just because you inline something doesn't mean you can't cache it. Let's see if Scott's idea can extend to SVG icons.
This page does the caching, whereas this one benefits from said caching.
18 | 19 |Here's the GitHub Repo.
20 | 21 | {% include "icons/icon-wheelchair.svg" %} 22 | 23 | {% include "icons/icon-cow.svg" %} 24 | 25 | {% include "icons/icon-alarm.svg" %} 26 | 27 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cached-icons", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "a-sync-waterfall": { 8 | "version": "1.0.1", 9 | "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", 10 | "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" 11 | }, 12 | "anymatch": { 13 | "version": "3.1.1", 14 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", 15 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", 16 | "optional": true, 17 | "requires": { 18 | "normalize-path": "^3.0.0", 19 | "picomatch": "^2.0.4" 20 | } 21 | }, 22 | "asap": { 23 | "version": "2.0.6", 24 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 25 | "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" 26 | }, 27 | "binary-extensions": { 28 | "version": "2.1.0", 29 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", 30 | "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", 31 | "optional": true 32 | }, 33 | "braces": { 34 | "version": "3.0.2", 35 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 36 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 37 | "optional": true, 38 | "requires": { 39 | "fill-range": "^7.0.1" 40 | } 41 | }, 42 | "chokidar": { 43 | "version": "3.4.3", 44 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", 45 | "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", 46 | "optional": true, 47 | "requires": { 48 | "anymatch": "~3.1.1", 49 | "braces": "~3.0.2", 50 | "fsevents": "~2.1.2", 51 | "glob-parent": "~5.1.0", 52 | "is-binary-path": "~2.1.0", 53 | "is-glob": "~4.0.1", 54 | "normalize-path": "~3.0.0", 55 | "readdirp": "~3.5.0" 56 | } 57 | }, 58 | "commander": { 59 | "version": "5.1.0", 60 | "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", 61 | "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" 62 | }, 63 | "fill-range": { 64 | "version": "7.0.1", 65 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 66 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 67 | "optional": true, 68 | "requires": { 69 | "to-regex-range": "^5.0.1" 70 | } 71 | }, 72 | "fsevents": { 73 | "version": "2.1.3", 74 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", 75 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", 76 | "optional": true 77 | }, 78 | "glob-parent": { 79 | "version": "5.1.1", 80 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 81 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 82 | "optional": true, 83 | "requires": { 84 | "is-glob": "^4.0.1" 85 | } 86 | }, 87 | "is-binary-path": { 88 | "version": "2.1.0", 89 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 90 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 91 | "optional": true, 92 | "requires": { 93 | "binary-extensions": "^2.0.0" 94 | } 95 | }, 96 | "is-extglob": { 97 | "version": "2.1.1", 98 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 99 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 100 | "optional": true 101 | }, 102 | "is-glob": { 103 | "version": "4.0.1", 104 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 105 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 106 | "optional": true, 107 | "requires": { 108 | "is-extglob": "^2.1.1" 109 | } 110 | }, 111 | "is-number": { 112 | "version": "7.0.0", 113 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 114 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 115 | "optional": true 116 | }, 117 | "normalize-path": { 118 | "version": "3.0.0", 119 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 120 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 121 | "optional": true 122 | }, 123 | "nunjucks": { 124 | "version": "3.2.2", 125 | "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.2.tgz", 126 | "integrity": "sha512-KUi85OoF2NMygwODAy28Lh9qHmq5hO3rBlbkYoC8v377h4l8Pt5qFjILl0LWpMbOrZ18CzfVVUvIHUIrtED3sA==", 127 | "requires": { 128 | "a-sync-waterfall": "^1.0.0", 129 | "asap": "^2.0.3", 130 | "chokidar": "^3.3.0", 131 | "commander": "^5.1.0" 132 | } 133 | }, 134 | "picomatch": { 135 | "version": "2.2.2", 136 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 137 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 138 | "optional": true 139 | }, 140 | "readdirp": { 141 | "version": "3.5.0", 142 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", 143 | "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", 144 | "optional": true, 145 | "requires": { 146 | "picomatch": "^2.2.1" 147 | } 148 | }, 149 | "to-regex-range": { 150 | "version": "5.0.1", 151 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 152 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 153 | "optional": true, 154 | "requires": { 155 | "is-number": "^7.0.0" 156 | } 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cached-icons", 3 | "version": "1.0.0", 4 | "description": "Can we use the [inline-cache-both](https://www.filamentgroup.com/lab/inlining-cache.html) technique?", 5 | "main": "sw.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "nunjucks": "^3.2.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /script/enhance-icons.js: -------------------------------------------------------------------------------- 1 | const icons = document.querySelectorAll("svg.icon"); 2 | 3 | icons.forEach(icon => { 4 | const url = icon.querySelector("use").getAttribute("xlink:href"); // might wanna look for href also 5 | fetch(url) 6 | .then(response => response.text()) 7 | .then(data => { 8 | /* This is probably a bit layout-thrashy. Someone smarter than me could probably fix that up. */ 9 | 10 | // Replace the with inline SVG 11 | const newEl = document.createElement("span"); 12 | newEl.innerHTML = data; 13 | icon.parentNode.replaceChild(newEl, icon); 14 | 15 | // Remove the s 16 | const parent = newEl.parentNode; 17 | while (newEl.firstChild) parent.insertBefore(newEl.firstChild, newEl); 18 | parent.removeChild(newEl); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /styles/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | font: 100%/1.4 system-ui; 3 | max-width: 500px; 4 | margin: 0 auto; 5 | } 6 | 7 | h1 { 8 | font-weight: 200; 9 | } 10 | 11 | .icon { 12 | width: 24px; 13 | height: 24px; 14 | } 15 | -------------------------------------------------------------------------------- /sw.js: -------------------------------------------------------------------------------- 1 | self.addEventListener("fetch", event => { 2 | let request = event.request; 3 | 4 | event.respondWith( 5 | caches.match(request).then(response => { 6 | return response || fetch(request); 7 | }) 8 | ); 9 | }); 10 | --------------------------------------------------------------------------------