React注記を使用してWebページのパフォーマンスを向上させる(feat.lighthouse)


ChawChawプロジェクトの反応注記の適用


反応には記録という機能があります.React.memo , useCallback , useMemoこの3つの機能は、構成部品の再実行を防止し、複数回の実行時間を短縮し、再レンダリングを最小限に抑えることができます.

React.memo


この機能は、親コンポーネントに適しているほど良いです.
デフォルトでは、ステータス変数として定義された変数が変更されると、リアクターは構成部品を再実行し、変更されたステータスを構成部品に反映します.
親構成部品でこの手順を実行すると、すべての依存する子構成部品が再実行されます.
したがって、サブコンポーネントで親コンポーネントから継承されたpropsが変更されていない場合は、再実行する必要はありません.
これらの概念において、React.memoは、対応する要素を取り囲む.また親からもらった道具に変更はありませんか.
浅い比較で比較する.
このような簡単な比較を行うために、useCallbackuseMemoが使用される.
詳細な操作手順

この時は使わないでください。


上記の2つのコードでは、PostModelはほとんどpropsをサブコンポーネントに渡します.すなわち、サブエレメントの立場では、PostModalが変化すると、サブエレメントに伝達されるpropsが毎回変化する.これで道具を比較する必要がなくなります.意味のない単純な比較演算を実行します.こんな時はいらない.
PostModal.tsx
const PostModal: React.FC<PostModalProps> = (props) => {
  const now = new Date();
  const dateArr = props.regDate.substring(0, 10).split("-");
  const stDate = new Date(
    Number(dateArr[0]),
    Number(dateArr[1]),
    Number(dateArr[2])
  );
  const endDate = new Date(
    now.getFullYear(),
    now.getMonth() + 1,
    now.getDate()
  );
  const pastDays =
    (endDate.getTime() - stDate.getTime()) / (1000 * 60 * 60 * 24);
  const repCountry = props.repCountry;
  const repLanguage = LocaleLanguage[props.repLanguage] || "";
  const repHopeLanguage = LocaleLanguage[props.repHopeLanguage] || "";
  const country = props.country;
  const language = useMemo(() => {
    return props.language.map((item) => LocaleLanguage[item] || "");
  }, [props.language]);
  const hopeLanguage = useMemo(() => {
    return props.hopeLanguage.map((item) => LocaleLanguage[item] || "");
  }, [props.hopeLanguage]);

  return (
    <PostModalBox>
      <PostModalImage src={`${props.imageUrl}`} />
      <PostUserName>{props.name}</PostUserName>
      <PostModalActive id={props.id} isLike={props.isLike} />
      <PostModalInfoList
        title="I am from"
        values={country}
        mainValue={repCountry}
      />
      <PostModalInfoList
        title="I can speak"
        values={language}
        mainValue={repLanguage}
      />
      <PostModalInfoList
        title="I want to speak"
        values={hopeLanguage}
        mainValue={repHopeLanguage}
      />
      <PostModalContent content={props.content} />
      <PostModalSocialList
        title="Contact to me"
        faceBookUrl={props.facebookUrl}
        instagramUrl={props.instagramUrl}
      />
      <PostModalInfo
        regDate={String(pastDays)}
        views={props.views}
        likes={props.likes}
      />
    </PostModalBox>
  );
};

export default React.memo(PostModal);

使用


LikeAlarm.tsx
const MLikeAlarm: React.FC = () => {
  const newLikes = useAppSelector((state) => state.chat.newLikes);

  const alarmlikeMessages = newLikes.map((item) => {
    return (
      <AlarmChatBox key={item.regDate + item.name}>
        <ChatBox
          imageUrl={`/Layout/heart.png`}
          regDate={item.regDate}
          sender={item.likeType}
          context={`${item.name}님이 ${item.likeType} 하셨습니다.`.substring(
            0,
            20
          )}
          type={LIKEALARM_TYPE}
        />
      </AlarmChatBox>
    );
  });

  return (
    <PushAlarmBox>
      {newLikes.length > 0 ? (
        alarmlikeMessages
      ) : (
        <EmptyAlarm title="No new likes Messages" />
      )}
    </PushAlarmBox>
  );
};

const LikeAlarm = React.memo(MLikeAlarm);
export { LikeAlarm };
上のコードはpropsで、何も受け取りません.つまり、親構成部品が再実行されても、再実行する必要はありません.再実行しても同じ運転が繰り返されるからです.
この場合は行動しなければならない.memoを使用して、親構成部品が再実行時に再実行されないことを浅い比較で確認します.

useCallback

useCallbackは、関数の参照値を格納します.デフォルトでは、JavaScriptは、関数もオブジェクトであるため、参照値を格納します.したがって、構成部品が再実行されると、関数の参照値が変更されます.参照値を注記するときに構成部品の再実行時にdeps配列の値が変更されない場合は、新しい関数は作成されず、既存の参照値を読み込み、関数を実行します.

この時に使いましょう。


上記のように、React.memoは浅い比較を行う.関数をサブエレメントとしてpropsに入れると、その関数は毎回再実行されて新しい参照値を持つので、同じ関数でも新しい参照値を持つ新しい関数としてサブエレメントに渡されます.React.memoを用いて浅い比較を行うサブエレメントでは、不変の関数であるため、再実行する必要がある.この場合、useCallbackを使用できます.
ChatRoom.tsx
const handleChangeInput: ChangeEventHandler<HTMLTextAreaElement> =
    useCallback((e) => {
      setMessage(e.target.value);
    }, []);

 const scrollToBottom = useCallback(() => {
    if (!chatMessageBox.current) return;
    chatMessageBox.current.scrollIntoView({
      behavior: "auto",
      block: "end",
      inline: "nearest",
    });
  }, []);

  useEffect(() => {
    scrollToBottom();
  }, [mainChatMessages.length, scrollToBottom]);
  return (
    <Outline>
      <Inner>
        <ChatRoomHeader
          selectLanguage={selectLanguage}
          setSelectLanguage={setSelectLanguage}
        />
        {isViewChatList ? (
          <ChatListWrapper>
            <ChatList />
          </ChatListWrapper>
        ) : (
          <>
            <MessageContainer>{messageBoxContent}</MessageContainer>
            <MessageInput
              onChange={handleChangeInput}
              sendMessage={sendMessage}
              value={message}
            />
          </>
        )}
      </Inner>
    </Outline>
  );
上記のコードから見ると、MessageInputおよびpropsを超え、handleChangeInputを超えている.useCallbackを使用して、関数値をMessageInput構成部品に格納し、再実行のたびに実行しないようにします.
また、useEffect()においても同様である.useEffectで関数を使用するにはdepsに関数を追加する必要があります.関数が毎回同じ関数である場合は、useEffectのコールバック関数が余分に再実行されないように関数値を保存する必要があります.
このような場合、useCallbackで囲まれた関数で関数を使用すると、同じ理由で中の関数をuseCallbackで囲まれます.

こんな時は使わないでください。


関数内のパラメータが毎回変化する場合、いずれにしてもパラメータのせいで関数が再生成されるので保存する必要はありません.いずれにしても、再生後に捨てる場合は不要です.

useMemo


オブジェクトには参照値があるため、毎回新しい値があります.
ChangeLanguageDropDown.tsx
const MChangeLanguageDropDown: React.FC<ChangeLanguageDropDownProps> = (
  props
) => {
  const { bodyBackgroundColor, bodyFontColor } = useContext(ThemeContext);
  const initialValue = LanguageLocale[props.selectLanguage[0]].toUpperCase();
  const options = useMemo(() => ["Korean", ...Object.keys(LanguageLocale)], []);

  return (
    <ChangeLanguageDropDownBox>
      <DropDown
        fontWeight="600"
        fontSize="1em"
        width="110px"
        height="30px"
        options={options}
        initialValue={initialValue}
        setValues={props.setSelectLanguage}
        value={initialValue}
        index={0}
        type={NOMAL_TYPE}
        backgroundColor={bodyBackgroundColor}
        color={bodyFontColor}
      >
        <ImEarth />
      </DropDown>
    </ChangeLanguageDropDownBox>
  );
};
const ChangeLanguageDropDown = React.memo(MChangeLanguageDropDown);
上のコードを見ると、optionsのたびに一定の値があります.別の値に依存して変更される値でもないので、毎回新しい参照値を作成する必要はありません.
したがって、userMemoを使用してオブジェクトを囲み、参照値を下げます.これにより、サブエレメントから受信すると、React.memoによる運転再開を防止することができる.

LightHouseによるWebパフォーマンスの向上


Performance


性能の向上を測定するためにクロムを用いたLightHouse.このセクションでは、パフォーマンスは6つの異なる基準で測定されます.
冗長ではなく含蓄として定義し、ユーザーが表示するレンダリング時間を測定します.注釈をうまく適用すれば,性能の向上はこの部分で測定される.

Accessibility


この部分で多くの改善をした.

視覚障害者がウェブページを使用するときは、ページリーダーを使用します.このとき,リーダーがこれらのラベルを正しく説明できないと,アクセス性の低下として現れる.

input、labelをtextarea tagに追加


Li,ulラベル接続


button tagにtextがない場合はaria-labelまたはtextを追加します


などなど.
¥背景色とテキストのコントラストを強調し、この部分は信頼できないようです.オレンジと白は区別しやすいです

Best Practices


すべてのエラーコンソールを削除


@font-face:font-display swapを追加

  • フォントファイルを入力する前に、ユーザーが表示するフォントに置き換えることを示します.
    アンインストールアクティビティを使用したことがなく、なぜいつも交換させてくれたのか分かりません.

  • SEO


    title, description, opengraph, twitter, ...


    _app.tsx
     <DefaultSeo
                title={"ChawChaw 언어를 교환합시다.🗣"}
                description={"대학내 교환학생 언어교환 채팅 어플리케이션입니다."}
                canonical="https://www.chawchaw.vercel.app"
                openGraph={{
                  type: "website",
                  locale: "en_IE",
                  title: "ChawChaw 언어를 교환합시다.🗣",
                  description: "대학내 교환학생 언어교환 채팅 어플리케이션입니다.",
                  images: [
                    {
                      url: "https://i.ibb.co/m0NY7yQ/image.jpg",
                      width: 800,
                      height: 600,
                      alt: "ChawChaw 소개 이미지",
                    },
                  ],
                  url: "https://www.chawchaw.vercel.app",
                  site_name: "ChawChaw",
                }}
                twitter={{
                  handle: "@chawchawTwitter",
                  site: "chawchaw.vercel.app",
                  cardType: "summary",
                }}
                additionalLinkTags={[
                  {
                    type: "image/png",
                    sizes: "32x32",
                    href: "/Layout/chaw.png",
                    rel: "icon",
                  },
                ]}
                additionalMetaTags={[
                  {
                    name: "viewport",
                    content:
                      "viewport-fit=cover, width=device-width, initial-scale=1",
                  },
                ]}
              />
              <Component {...pageProps} />
    _document.tsx
    <Html lang="kr">
            <Head>
              <link
                href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@200;300;400;600;700;900&display=swap"
                rel="stylesheet"
              />
              <link rel="canonical" href="https://www.chawchaw.vercel.app" />
            </Head>
            <body>
              <div id="root">
                <Main />
                <NextScript />
              </div>
              <div id="notification"></div>
            </body>
          </Html>

    LightHouse測定結果

  • /home

    Before

    After
  • /account/login

    Before

    After
  • /account/signup

    Before

    After
  • /account/signup/webMailAuth

    Before

    After
  • /account/profile

    Before

    After
  • /account/setting

    Before

    After
  • /chat

    Before

    After
  • /post

    Before

    After
  • /manage/users

    Before

    After
  • /manage/users/detail

    Before

    After
  • /manage/statistics

    Before

    After
  • つまり、パフォーマンスが向上する前と後を比較して、すべての得点を加算してパーセントを向上させようとすると...!
    ぐつぐつ

    4026->4282平均6.36%上昇!


    期待されるパフォーマンスの改善点は次のとおりです。

  • /home : 96 -> 100
  • /manage/users : 97 -> 100
  • /manage/users/detail: 92->93
  • /manage/statistics : 97 -> 100
  • に等しい