Extract icon manifest & lists with babel at compile time

This commit is contained in:
Xevion
2023-02-16 04:24:10 -06:00
parent 44a9c3a2c5
commit ee6322c591
4 changed files with 56 additions and 0 deletions

4
.babelrc Normal file
View File

@@ -0,0 +1,4 @@
{
"presets": ["next/babel"],
"plugins": ["babel-plugin-macros"]
}

28
src/utils/getIcons.ts Normal file
View File

@@ -0,0 +1,28 @@
import codegen from "babel-plugin-codegen/macro";
/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */
// language=JavaScript
const fn = codegen`
const {IconsManifest} = require("react-icons/lib/cjs");
let codes = "(function (id) { switch (id) {";
IconsManifest.forEach(({id}) => {
codes += 'case "' + id + '":\\n return import(/* webpackChunkName: "' + id + '" */ "react-icons/' + id + '/index");\\n'
})
codes += '}})';
module.exports = codes; // module.exports = "import('react-icons/fa/index')"
`;
/* eslint-enable */
export function getIcons(id: string) {
/*
Dynamic Import with improved performance.
Macros are used to avoid bundling unnecessary modules.
Similar to this code
```
return import(`react-icons/${iconsId}/index`);
```
*/
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-return
return fn(id);
}

10
src/utils/iconList.ts Normal file
View File

@@ -0,0 +1,10 @@
// @ts-nocheck
// @codegen
/* eslint-disable */
// @ts-ignore
module.exports = require("./icons").ICON_SET_IDS
.map(setId => Object.keys(require(`react-icons/${setId}/index`)).map(id => (
{id, setId}
)))
.flat()

14
src/utils/icons.ts Normal file
View File

@@ -0,0 +1,14 @@
import * as ReactIconsLib from "react-icons/lib";
import type {IconManifest} from "react-icons";
// @ts-ignore TS7053 ;; This reaches into React Icon's internals so it really cannot be made typesafe for our purposes.
export const ALL_ICON_SETS: IconManifest[] = ReactIconsLib["IconsManifest"] as IconManifest[];
// An object referencing each of the icon sets, keyed by its 'id' (two/three letter identifier).
export const ALL_ICON_SETS_BY_ID: Record<string, IconManifest> = Object.fromEntries(ALL_ICON_SETS.map(set => [set.id, set]));
// A list of all the icon sets.
export const ICON_SET_IDS: string[] = Object.keys(ALL_ICON_SETS_BY_ID);
// A getter for code splitting loaders.
export const getIconById = (id: string): IconManifest | undefined => ALL_ICON_SETS_BY_ID[id];