Bundle as static reources #492
-
Hello Currently when used as a react component, each icon is inserted into source as a "svg" element. Thus, if you have 100 instances of the same icon in your code you will get 100 svg elements with full source. Prefferably, I would like to only keep reference to a static asset. Is this even possible? There are bigger magics happening at build time.\ Any help? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 3 replies
-
By "static", if you mean a single external (cacheable) sprite sheet, there's already an issue in which I have addressed that. It's simply a lot of complexity and maintenance to build a static analysis tool à la Tailwind. I'm not getting paid for this so I don't really feel like donating my labor toward that right now, but I'd happily consider an outside contribution. |
Beta Was this translation helpful? Give feedback.
-
Hello, thank you for your answer. I love your icon pack, and after many years with semantic-ui-react, I finally made the change. The icons are beautiful and crisp, and the variety is amazing. I'll ask one of my students if they are up for a challenge. The short-term solution over @phosphoricons/web would be to create a static analysis script to extract the payload for your icon generation API and save the result. Moving forward, you may consider re-packaging it to a webpack plugin that would swap the API request for the build step. This would be easily done for the icons/web. As for the react icons it would be a bit more tricky as you would also have to do some code modifications. But ... moving forward I do have a solution for making this much better. Once we have the static analysis script ready, we'll post back. |
Beta Was this translation helpful? Give feedback.
-
A quick and modifiable script that:
// @ts-nocheck
import fs from "fs";
import { globSync } from "glob";
function showProgress(item, total) {
const i = item / total * 20;
const dots = "#".repeat(i)
const left = 20 - i
const empty = " ".repeat(left)
/* need to use `process.stdout.write` becuase console.log print a newline character */
/* \r clear the current line and then print the other characters making it looks like it refresh*/
process.stdout.write(`\r[${dots}${empty}] ${Math.round(item/total) * 100}% ${item}/${total}`)
}
async function downloadIcons() {
// get all tsx files
const tsxFiles = globSync("./src/**/*.tsx");
const icons = {};
console.log("Step 1/3: Extracting Icons from files...")
const types = [];
for (let i = 0; i < tsxFiles.length; i++) {
const file = tsxFiles[i];
const content = fs.readFileSync(file, "utf-8");
const regex = /ph(-([^ ]+))? ph-([^ "]+)/g;
let match = regex.exec(content);
while (match) {
const type = match[2] || "regular";
const icon = match[3];
if (icons[type] == undefined) {
icons[type] = [];
}
if (!icons[type].includes(icon)) {
icons[type].push(icon);
}
if (!types.includes(match[0])) {
types.push(match[0]);
}
// console.log(`Found icon: ${icon} with type: ${type} in file: ${file}`);
match = regex.exec(content);
}
showProgress(i, tsxFiles.length);
}
showProgress(tsxFiles.length, tsxFiles.length);
console.log ("We found these icons: ");
console.log(JSON.stringify(icons, null, 2))
console.log("Step 2/3: Downloading icon fonts ...")
const request = await fetch("https://rektdeckard-fontpack.web.val.run/", {
method: "POST",
body: JSON.stringify({
"icons": icons,
"formats": [
"woff"
],
"inline": true
})
})
console.log("Step 3/3: Writing File ...");
const json = await request.json()
// console.log(json)
fs.writeFileSync("./src/phosphor.css", json.css, "utf-8")
fs.writeFileSync("./src/components/phosphor.ts",
`export type PhosphorIcons = "${types.join('" | \n "')}"`,
"utf-8");
console.log("Done!")
}
downloadIcons(); I also have this helper component, that either loads the icons from font or other library import type { PhosphorIcons } from "~/components/phosphor";
export type Icon = PhosphorIcons | React.FC;
export function Iconic({ Icon }: { Icon: Icon }) {
return typeof Icon === "string" ? <i className={Icon}></i> : <Icon />;
} |
Beta Was this translation helpful? Give feedback.
I would definitely consider shipping an SVG Sprite Sheet for each icon weight, possibly as another means of using the @phosphor-icons/web package. They'd be big, but they'd be simple and cacheable.
I would also consider adding Sprite Sheet generation to https://pack.phosphoricons.com (in fact, I think this is a good idea). It's not automatic and it doesn't integrate with build tools, but it DOES make it possible to have minimal, cacheable bundles.