Merge pull request #253 from simoleo89/feat/code-splitting

perf(bundle): lazy-load emoji-mart picker (defer ~82 KB gzip from first paint)
This commit is contained in:
DuckieTM
2026-06-18 12:28:49 +02:00
committed by GitHub
4 changed files with 38 additions and 11 deletions
+32
View File
@@ -0,0 +1,32 @@
import { ComponentType, FC, lazy, Suspense } from 'react';
type EmojiPickerProps = Record<string, unknown>;
/**
* emoji-mart's data bundle (`@emoji-mart/data`) is ~430 KB (~82 KB gzip) and was
* pulled into the initial app bundle by three always-mounted views that import it
* statically. The picker itself opens rarely, so we load both the data and the
* `<Picker>` component on demand via a dynamic import — deferring that payload out
* of first paint. Drop-in for `<Picker data={data} … />` (the `data` prop is
* injected here; forward every other prop unchanged).
*/
const PickerWithData = lazy(async () =>
{
const [ dataModule, pickerModule ] = await Promise.all([
import('@emoji-mart/data'),
import('@emoji-mart/react')
]);
const data = (dataModule as { default: unknown }).default;
const Picker = (pickerModule as { default: ComponentType<EmojiPickerProps> }).default;
const Wrapped: ComponentType<EmojiPickerProps> = props => <Picker data={ data } { ...props } />;
return { default: Wrapped };
});
export const LazyEmojiPicker: FC<EmojiPickerProps> = props => (
<Suspense fallback={ <div className="px-2 py-1 text-[11px] text-white/60"></div> }>
<PickerWithData { ...props } />
</Suspense>
);
@@ -2,8 +2,7 @@ import { PurchasePrefixComposer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useMemo, useRef, useState } from 'react';
import { LocalizeText, SanitizeHtml, SendMessageComposer, PRESET_PREFIX_EFFECTS, parsePrefixColors, getPrefixEffectStyle, PREFIX_EFFECT_KEYFRAMES } from '../../../../../api';
import { CatalogLayoutProps } from './CatalogLayout.types';
import data from '@emoji-mart/data';
import Picker from '@emoji-mart/react';
import { LazyEmojiPicker } from '../../../../../common/LazyEmojiPicker';
const PRESET_COLORS: string[] = [
'#FF0000', '#FF6600', '#FFCC00', '#33CC00', '#00CCFF',
@@ -222,8 +221,7 @@ export const CatalogLayoutCustomPrefixView: FC<CatalogLayoutProps> = props =>
<>
<div className="fixed inset-0" style={ { zIndex: 999, background: 'rgba(0,0,0,0.5)' } } onClick={ () => setShowIconPicker(false) } />
<div className="fixed rounded-xl overflow-hidden" style={ { zIndex: 1000, top: '50%', left: '50%', transform: 'translate(-50%, -50%)', boxShadow: '0 8px 32px rgba(0,0,0,0.6)' } }>
<Picker
data={ data }
<LazyEmojiPicker
locale="it"
onEmojiSelect={ (emoji: { native: string }) =>
{
@@ -1,6 +1,5 @@
import { AddLinkEventTracker, CustomPrefixPurchaseFailedEvent, ILinkEventTracker, PurchaseCatalogPrefixComposer, PurchaseNickIconComposer, PurchasePrefixComposer, RemoveLinkEventTracker, RequestNickIconsComposer, SetActiveNickIconComposer, SetActivePrefixComposer, SetDisplayOrderComposer, UserNickIconsEvent } from '@nitrots/nitro-renderer';
import data from '@emoji-mart/data';
import Picker from '@emoji-mart/react';
import { LazyEmojiPicker } from '../../common/LazyEmojiPicker';
import { FC, useEffect, useMemo, useState } from 'react';
import { INickIconItem, IPrefixItem, PRESET_PREFIX_EFFECTS, PRESET_PREFIX_FONTS, SendMessageComposer, getPrefixEffectStyle, getPrefixFontStyle, parsePrefixColors } from '../../api';
import { GetNickIconUrl } from '../../assets/images/user_custom/nick_icons';
@@ -575,8 +574,7 @@ export const CustomizeNickIconView: FC<{}> = () =>
<>
<div className="fixed inset-0 z-[999]" onClick={ () => setShowEmojiPicker(false) } />
<div className="fixed left-1/2 top-1/2 z-[1000] -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-xl shadow-2xl">
<Picker
data={ data }
<LazyEmojiPicker
locale="en"
onEmojiSelect={ (emoji: { native: string }) =>
{
@@ -1,6 +1,5 @@
import data from '@emoji-mart/data';
import Picker from '@emoji-mart/react';
import * as Popover from '@radix-ui/react-popover';
import { LazyEmojiPicker } from '../../../../common/LazyEmojiPicker';
import { FC, useState } from 'react';
interface ChatInputEmojiSelectorViewProps
@@ -26,7 +25,7 @@ export const ChatInputEmojiSelectorView: FC<ChatInputEmojiSelectorViewProps> = p
</Popover.Trigger>
<Popover.Portal>
<Popover.Content className="z-[1070]" side="top" sideOffset={ 8 }>
<Picker data={ data } onEmojiSelect={ handleEmojiSelect } />
<LazyEmojiPicker onEmojiSelect={ handleEmojiSelect } />
</Popover.Content>
</Popover.Portal>
</Popover.Root>