2

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.

Youssef
  • 401
  • 1
  • 5
  • 23

0 Answers0