I am using NextJS and trying to dynamically (using a param) to import the related icon library from 'react-icons' npm package.
Knowing that for ie. the icon FaAws from 'fa' library can be imported as the follow :
import { FaAws } from 'react-icons/fa';
The working code (that needs to be optimized) :
import { ComponentType } from "react";
import { IconType as IconLibrary } from "react-icons";
import * as Fa from "react-icons/fa";
import * as Fa6 from "react-icons/fa6";
import * as Ai from "react-icons/ai";
import * as Md from "react-icons/md";
import * as Si from "react-icons/si";
import * as Vsc from "react-icons/vsc";
import * as Gr from "react-icons/gr";
import * as Ri from "react-icons/ri";
import * as Fc from "react-icons/fc";
import * as Bi from "react-icons/bi";
import * as Bs from "react-icons/bs";
import * as Cg from "react-icons/cg";
import * as Ci from "react-icons/ci";
import * as Go from "react-icons/go";
import * as Gi from "react-icons/gi";
import * as Pi from "react-icons/pi";
import * as Di from "react-icons/di";
import { IconTypesType } from "./IconTypes";
type IconLibraryType = {
[key: string]: ComponentType<IconLibrary>;
}
type IconLibraryPropsType = {
type: IconTypesType;
code: string;
}
const Icon: React.FC<IconLibraryPropsType> = ({ type, code }) => {
const libraries = new Map([
['fa', (Fa as IconLibraryType)],
['fa6', (Fa6 as IconLibraryType)],
['ai', (Ai as IconLibraryType)],
['vsc', (Vsc as IconLibraryType)],
['si', (Si as IconLibraryType)],
['gr', (Gr as IconLibraryType)],
['ri', (Ri as IconLibraryType)],
['fc', (Fc as IconLibraryType)],
['bi', (Bi as IconLibraryType)],
['cg', (Cg as IconLibraryType)],
['ci', (Ci as IconLibraryType)],
['go', (Go as IconLibraryType)],
['gi', (Gi as IconLibraryType)],
['pi', (Pi as IconLibraryType)],
['di', (Di as IconLibraryType)],
['bs', (Bs as IconLibraryType)],
['md', (Md as IconLibraryType)]
]);
const IconComponent: ComponentType<any> = (libraries.get(type) as IconLibraryType)[code];
if (IconComponent) {
return <IconComponent />;
}
throw new Error(`Icon type : ${type} with name ${code} not found`);
};
export default Icon;
The code above is working but is also very heavy as I overload the build with all the libraries before I can reach the wanted icon.
Perhaps Modularized Imports in NextJS as per docs can solve my issue, but I don't know how to achieve it for all needed icons from the library.
Please note that I also want to leverage the NextJS server performance for this operation and avoid to lazy load all icons on the front, which will take time on the user-end.
What I have tried to optimize it :
I don't know if next/dynamic is suited for dynamic imports from npm_modules as I have not seen any example, but I have tried the following :
1-
const IconComponent: ComponentType<any> = dynamic(() =>
import(`react-icons/${type}`).then((module: IconLibraryType) => module[code]), {
ssr: false
}
);
Error :
- wait compiling...
- error ./node_modules/react-icons/LICENSE
Module parse failed: Unexpected token (1:10)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See
https://webpack.js.org/concepts#loaders
2-
const IconComponent: ComponentType<any> = dynamic(() =>
import(`react-icons/${type}/${code}`).then((module: IconLibraryType) => module.default), {
ssr: false
}
);
Error :
./node_modules/react-icons/ai/index.d.ts
Module parse failed: Unexpected token (3:7)
You may need an appropriate loader to handle this file type,
currently no loaders are configured to process this file. See
https://webpack.js.org/concepts#loaders
| // THIS FILE IS AUTO GENERATED
| import { IconTree, IconType } from '../lib'
> export declare const AiFillAccountBook: IconType;
| export declare const AiFillAlert: IconType;
| export declare const AiFillAlipayCircle: IconType;
Can someone please help on the matter.
Thanks.