تکنیکهای بهینهسازی واکنش نشان میدهد که به شما کمک میکند کدهای عملکردی بیشتری بنویسید
بهینه سازی عملکرد یک جنبه حیاتی در توسعه برنامه های کاربردی وب است. کاربران انتظار دارند برنامه ها به سرعت بارگذاری شوند و به تعاملات خود به آرامی پاسخ دهند.
در اکوسیستم React، تکنیکهای بهینهسازی عملکرد میتوانند تجربه کاربر را با کاهش زمان بارگذاری و بهبود پاسخدهی بهطور قابلتوجهی افزایش دهند.
در این مقاله به هشت تکنیک موثر برای بهینه سازی عملکرد اپلیکیشن React می پردازیم.
فهرست مطالب
چرا بهینه سازی عملکرد مهم است
بهینه سازی عملکرد برنامه React به چند دلیل بسیار مهم است:
تجربه کاربری بهتر: یک برنامه با بارگذاری کند یا تاخیر می تواند منجر به تجربه کاربری ضعیف شود و بر کسب و کار شما تأثیر منفی بگذارد. کاربران انتظار تعامل سریع و پاسخگو دارند و بهینه سازی عملکرد به ارائه آن کمک می کند.
بهبود سئو: موتورهای جستجو مانند گوگل زمان بارگذاری صفحه و عملکرد کلی را هنگام رتبه بندی وب سایت ها در نظر می گیرند. برنامه ای که به خوبی بهینه شده باشد در نتایج جستجو رتبه بالاتری خواهد داشت و برای کاربران بالقوه بیشتر قابل مشاهده است.
کاهش نرخ پرش: اگر بارگیری یا پاسخگویی برنامه شما بیش از حد طول بکشد، کاربران احتمالاً آن را ترک میکنند و دیگر برنمیگردند. با بهینه سازی عملکرد، می توانید نرخ پرش را کاهش دهید و تعامل را افزایش دهید.
صرفه جویی در هزینه یک برنامه کاربردی کاربردی به منابع کمتری (مانند سرورها و حافظه) برای رسیدگی به حجم کاری یکسان نیاز دارد. این به معنای کاهش هزینه هاست و کاهش نیازهای زیرساختی است.
مزیت رقابتی: یک برنامه کاربردی سریع و کارآمد شما را از رقبایی که ممکن است برنامه هایشان کندتر یا کمتر بهینه شده باشد متمایز می کند. طبق تحقیقات انجام شده توسط پورتنت ، وب سایتی که در عرض یک ثانیه بارگذاری می شود دارای نرخ تبدیل پنج برابر بیشتر از سایتی است که بارگذاری آن ده ثانیه طول می کشد. پس ، اطمینان از عملکرد خوب برنامه های React برای حفظ کاربران و حفظ مزیت رقابتی بسیار مهم است.
8 تکنیک های بهینه سازی عملکرد React
در زیر هشت تکنیک بهینه سازی عملکرد React وجود دارد که می توانید برای افزایش سرعت برنامه های خود از آنها استفاده کنید.
تجسم فهرست
تجسم فهرست، یا پنجره، شامل نمایش تنها مواردی است که در حال حاضر روی صفحه قابل مشاهده است.
هنگامی که با تعداد زیادی آیتم در یک فهرست سروکار دارید، رندر کردن همه موارد به طور همزمان می تواند منجر به کندی عملکرد و مصرف مقدار قابل توجهی از حافظه شود. مجازیسازی فهرست با ارائه تنها زیرمجموعهای از آیتمهای فهرست که در حال حاضر در نمای قابل مشاهده است، این مشکل را برطرف میکند، که در حین حرکت کاربران در فهرست، منابع را حفظ میکند.
تکنیک مجازی سازی به صورت پویا آیتم های رندر شده را با موارد جدید جایگزین می کند و بخش قابل مشاهده فهرست را به روز و پاسخگو نگه می دارد. این به شما اجازه می دهد تا فهرست های بزرگ یا داده های جدولی را تنها با رندر کردن بخش قابل مشاهده، بازیافت اجزای مورد نیاز و بهینه سازی عملکرد اسکرول ارائه دهید.
روشهای مختلفی برای پیادهسازی تجسم فهرست در React وجود دارد، و یکی از آنها استفاده از یک کتابخانه محبوب به نام React Virtualized است.
برای نصب react-virtualized
می توانید از دستور زیر استفاده کنید:
npm install react-virtualized --save
پس از نصب react-virtualized
، می توانید کامپوننت ها و استایل های مورد نیاز را وارد کنید. در زیر مثالی از نحوه استفاده از مؤلفه List
برای ایجاد یک فهرست مجازی آورده شده است:
import React from 'react'; import { List } from 'react-virtualized'; import 'react-virtualized/styles.css'; // Import styles // Your list data const list = Array(5000).fill().map((_, index) => ({ id: index, name: `Item ${index}` })); // Function to render each row function rowRenderer({ index, key, style }) { return ( <div key={key} style={style}> {list[index].name} </div> ); } // Main component function MyVirtualizedList() { return ( <List width={300} height={300} rowCount={list.length} rowHeight={20} rowRenderer={rowRenderer} /> ); } export default MyVirtualizedList;
در این مثال، List
جزء اصلی ارائه شده توسط react-virtualized
است. تابع rowRenderer
نحوه رندر هر سطر را مشخص می کند. عناصر width
، height
، rowCount
، rowHeight
و rowRenderer
برای پیکربندی رفتار و ظاهر فهرست ضروری هستند.
برنامه های React می توانند حجم عظیمی از داده ها را با استفاده از مجازی سازی فهرست بدون به خطر انداختن عملکرد یا تجربه کاربر مدیریت کنند.
بارگذاری تنبل تصاویر
مشابه تکنیک مجازی سازی فهرست ، بارگذاری تنبل تصاویر از ایجاد گره های DOM غیر ضروری جلوگیری می کند و در نتیجه عملکرد را افزایش می دهد. بارگذاری تنبل به شما این امکان را می دهد که به جای بارگذاری همه تصاویر در بارگذاری صفحه، بارگذاری تصاویر را تا زمانی که مورد نیاز یا قابل مشاهده برای کاربر باشد به تعویق بیندازید یا به تعویق بیاندازید.
مفهوم بارگذاری تنبل این است که بارگذاری یک مکان یا یک نسخه کوچک با وضوح پایین از تصویر را آغاز کنیم، معمولاً یک تصویر کوچک با اندازه کوچک یا یک مکان نگهدار تار. هنگامی که کاربر صفحه را اسکرول می کند یا با آن تعامل می کند، تصویر واقعی به صورت پویا بارگذاری می شود و هنگامی که کاربر وارد پنجره نمایش می شود یا زمانی که قابل مشاهده می شود جایگزین مکان نگهدار می شود.
با استفاده از کتابخانه ها و تکنیک های مختلف می توان به بارگذاری تنبل در React دست یافت. یکی از کتابخانه های محبوب react-lazyload است.
برای نصب react-lazyload
می توانید از دستور زیر استفاده کنید:
npm install --save react-lazyload
در زیر نمونهای از کامپوننت ساده React است که از react-lazyload
برای پیادهسازی بارگذاری تنبل برای تصاویر استفاده میکند:
import React from 'react'; import LazyLoad from 'react-lazyload'; const MyLazyLoadedImage = ({ src, alt }) => { return ( <LazyLoad height={200} offset={100}> {/* The height and offset props control when the image should start loading */} <img src={src} alt={alt} /> </LazyLoad> ); }; export default MyLazyLoadedImage;
در این مثال، MyLazyLoadedImage
از مؤلفه LazyLoad
از react-lazyload
استفاده میکند. height
پایه ارتفاع مکاننما را مشخص میکند، و پایه offset
تعیین میکند که مکانگیر باید چقدر پایینتر از viewport شروع به بارگیری کند.
روش دیگر استفاده از Intersection Observer API است که یک API وب است که به شما امکان می دهد تشخیص دهید که چه زمانی یک عنصر به طور موثر وارد ویوپورت می شود یا وجود دارد. در اینجا نحوه استفاده از Intersection Observer API به همراه قلاب useEffect
در React آورده شده است:
import React, { useEffect, useRef } from 'react'; const IntersectionLazyLoad = ({ src, alt }) => { const imageRef = useRef(); useEffect(() => { const options = { root: null, // Use the viewport as the root rootMargin: '0px', // No margin around the root threshold: 0.5, // 50% of the image should be visible }; const observer = new IntersectionObserver(handleIntersection, options); if (imageRef.current) { observer.observe(imageRef.current); } return () => { // Cleanup the observer when the component is unmounted observer.disconnect(); }; }, []); const handleIntersection = (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { // Load the image when it becomes visible imageRef.current.src = src; imageRef.current.alt = alt; } }); }; return <img ref={imageRef} style={{ height: '200px' }} alt="Placeholder" />; }; export default IntersectionLazyLoad;
در این مثال، IntersectionLazyLoad
از Intersection Observer API استفاده میکند تا مشخص کند که چه زمانی تصویر در ویوپورت قابل مشاهده است.
با استفاده از این API به همراه قلاب React useEffect
، می توانید راه حل بارگذاری تنبل سفارشی خود را برای تصاویر در React پیاده سازی کنید.
حفظ کردن
Memoization در React تکنیکی است که برای بهینه سازی عملکرد اجزای عملکردی با ذخیره نتایج محاسبات گران قیمت یا فراخوانی تابع استفاده می شود. این به ویژه هنگام برخورد با توابع فشرده محاسباتی یا اغلب نامیده می شود با مقادیر ورودی یکسان مفید است، زیرا به جلوگیری از محاسبات اضافی کمک می کند و کارایی کلی برنامه را بهبود می بخشد.
در React، سه تکنیک برای حفظ کردن وجود دارد: React.memo()
، useMemo(),
و useCallback().
بیایید جزئیات هر کدام را تحلیل کنیم:
نحوه استفاده از React.memo()
این جزء درجه بالاتر اجزای کاملاً کاربردی را میپیچد تا در صورت بدون تغییر ماندن پایههای دریافتی، از رندر مجدد جلوگیری کند.
با استفاده از React.memo()
نتیجه رندر بر اساس props ذخیره می شود. اگر اجزاء از آخرین رندر تغییر نکرده باشند، React به جای انجام مجدد فرآیند رندر، از نتیجه رندر قبلی استفاده مجدد می کند. این باعث صرفه جویی در زمان و منابع می شود.
در زیر مثالی در مورد نحوه استفاده از React.memo
با یک جزء کاربردی آورده شده است:
import React from 'react'; const Post = ({ signedIn, post }) => { console.log('Rendering Post'); return ( <div> <h2>{post.title}</h2> <p>{post.content}</p> {signedIn && <button>Edit Post</button>} </div> ); }; export default React.memo(Post);
در کد بالا، Post
(جزء عملکردی) به signedIn
و post
props بستگی دارد. با قرار دادن آن با React.memo()
، React فقط در صورت تغییر signedIn
یا post
کامپوننت Post
دوباره رندر می کند.
اکنون می توانید از کامپوننت ذخیره شده مانند هر مؤلفه دیگری در برنامه خود استفاده کنید:
import React, { useState } from 'react'; import Post from './Post'; const App = () => { const [signedIn, setSignedIn] = useState(false); const post = { title: 'Hello World', content: 'Welcome to my blog!' }; return ( <div> <Post signedIn={signedIn} post={post} /> <button onClick={() => setSignedIn(!signedIn)}> Toggle Signed In </button> </div> ); }; export default App;
هنگامی که روی دکمه Toggle Signed In
کلیک می کنید، وضعیت signedIn
تغییر می کند. از آنجایی که Post
با React.memo()
پوشانده شده است، تنها زمانی که prop signedIn
تغییر کند دوباره رندر می شود، پس در زمان و منابع رندر صرفه جویی می شود.
نحوه استفاده از useMemo()
قلاب useMemo()
عملکرد را با به خاطر سپردن نتیجه یک فراخوانی تابع یا یک محاسبه گران قیمت بهینه می کند. نتیجه را در حافظه پنهان ذخیره می کند و تنها زمانی که مقادیر ورودی تغییر می کند دوباره آن را محاسبه می کند. در زیر مثالی در مورد نحوه استفاده از قلاب useMemo
در کامپوننت عملکردی آورده شده است:
import React, { useMemo } from 'react'; function App() { const [count, setCount] = React.useState(0); const [otherState, setOtherState] = React.useState(''); const expensiveComputation = (num) => { let i = 0; while (i < 1000000000) i++; return num * num; }; const memoizedValue = useMemo(() => expensiveComputation(count), [count]); return ( <div> <p>Count: {count}</p> <p>Square: {memoizedValue}</p> <button onClick={() => setCount(count + 1)}>Increase Count</button> <input type="text" onChange={(e) => setOtherState(e.target.value)} /> </div> ); } export default App;
در کد بالا، تابع expensiveComputation
یک عملیات فشرده منابع را شبیه سازی می کند، مانند مربع کردن یک عدد.
قلاب useMemo
برای ذخیره کردن نتیجه این محاسبه استفاده می شود. مقدار ذخیره شده در memoizedValue
فقط زمانی دوباره محاسبه می شود که حالت count
تغییر کند، زیرا count
به عنوان یک وابستگی در آرایه وابستگی useMemo
مشخص می شود. در نتیجه، با کلیک بر روی دکمه Increase Count
، وضعیت count
افزایش مییابد و باعث محاسبه مجدد مقدار ذخیرهشده میشود.
برعکس، تغییر otherState
از طریق فیلد ورودی باعث محاسبه مجدد نمی شود، زیرا otherState
در آرایه وابستگی useMemo
گنجانده نشده است.
نحوه استفاده از useCallback()
قلاب useCallback()
در React برای حفظ کردن یک تابع به جای به خاطر سپردن نتیجه تابع استفاده می شود. مخصوصاً هنگام انتقال رویدادها به عنوان لوازم جانبی به مؤلفههای فرزند برای جلوگیری از رندرهای غیرضروری مفید است.
useCallback()
تابع را به خاطر میسپارد و اطمینان حاصل میکند که تا زمانی که وابستگیها تغییر نکردهاند، در رندرهای مجدد یکسان باقی میماند.
این به ویژه هنگام انتقال عملکردها به عنوان پایه به اجزای فرزند مفید است و از رندرهای غیرضروری جلوگیری می کند. اغلب با React.memo()
استفاده می شود تا اطمینان حاصل شود که مؤلفه های فرزند در مواقع غیرضروری دوباره رندر نمی شوند. در زیر مثالی از نحوه استفاده از قلاب useCallback()
آورده شده است:
import React, { useState, useCallback } from 'react'; const ParentComponent = () => { const [count, setCount] = useState(0); // Define a function that increments the count state const incrementCount = () => { setCount(count + 1); }; // Memoize the incrementCount function using useCallback const memoizedIncrement = useCallback(incrementCount, [count]); return ( <div> <p>Count: {count}</p> <ChildComponent onIncrement={memoizedIncrement} /> </div> ); }; const ChildComponent = React.memo(({ onIncrement }) => { console.log('Child component rendered'); return ( <div> <button onClick={onIncrement}>Increment Count</button> </div> ); }); export default ParentComponent;
در کد بالا، ParentComponent
مسئول مدیریت یک متغیر حالت به نام count
است و تابعی به نام incrementCount
معرفی میکند که افزایش تعداد را مدیریت میکند. با استفاده از قلاب useCallback
، تابع incrementCount
به حافظه سپرده میشود و ثبات آن را در بین رندرها تضمین میکند، مگر اینکه هر یک از وابستگیهای آن، در این مورد، count
، تغییر کند.
از سوی دیگر، ChildComponent
یک جزء تو در تو در والد است. تابع ذخیره سازی شده onIncrement
را از والد به عنوان یک پایه دریافت می کند.
برای بهینهسازی عملکرد و جلوگیری از رندرهای غیرضروری هنگامی که props ثابت میمانند، ChildComponent
با React.memo()
پیچیده میشود. این تضمین میکند که مؤلفه فرزند تنها زمانی دوباره رندر میشود که لوازم آن، بهویژه عملکرد حافظهگذاریشده، تغییر کند و به فرآیند رندر کارآمدتر کمک کند.
توجه به این نکته مهم است که useCallback
باید به مقدار کم و فقط برای بخشهای حیاتی برنامه شما استفاده شود. استفاده بیش از حد useCallback
در واقع می تواند منجر به عملکرد بدتر به دلیل هزینه بالای خود ذخیره سازی شود. همیشه تأثیر عملکرد را قبل و بعد از استفاده از useCallback
اندازه گیری کنید تا مطمئن شوید که اثر مورد نظر را دارد.
وقایع درگیری و شکست
Throttling در React تکنیکی است که برای محدود کردن تعداد دفعات فراخوانی یک تابع یا یک رویداد کنترل کننده استفاده میشود. این تضمین می کند که تابع در یک بازه زمانی مشخص فراخوانی می شود و از اجرای بیش از حد مکرر آن جلوگیری می کند.
Throttling به شما امکان می دهد تا با تنظیم حداقل فاصله زمانی بین هر فراخوانی تابع، نرخ فراخوانی تابع را کنترل کنید. اگر تابع چندین بار در آن بازه زمانی فراخوانی شود، فقط اولین فراخوانی اجرا میشود و فراخوانیهای بعدی تا پایان فاصله نادیده گرفته میشوند.
حال، بیایید throttling را با یک مثال کد توضیح دهیم. اول، بدون گاز:
// Without throttling, this function will be called every time the event is triggered function handleResize() { console.log('Window resized'); } window.addEventListener('resize', handleResize);
با throttling، میتوانیم تعداد دفعات فراخوانی تابع handleResize
را محدود کنیم:
// Throttling function function throttle(func, delay) { let lastCall = 0; return function(...args) { const now = new Date().getTime(); if (now - lastCall < delay) { return; } lastCall = now; func(...args); }; } // Throttled event handler const throttledHandleResize = throttle(handleResize, 200); window.addEventListener('resize', throttledHandleResize)
در این مثال، تابع throttle
handleResize
را می پیچد و تضمین می کند که بیشتر از هر 200 میلی ثانیه فراخوانی نشود. اگر رویداد resize
بیشتر از آن اجرا شود، تابع handleResize
فقط یک بار در هر 200 میلی ثانیه اجرا میشود و پتانسیل مشکلات عملکرد ناشی از فراخوانیهای سریع و مکرر تابع را کاهش میدهد.
از سوی دیگر، Debouncing همچنین برای محدود کردن تعداد دفعاتی که یک تابع یا یک کنترل کننده رویداد فراخوانی می شود، استفاده می شود. این تضمین می کند که تابع فقط پس از یک دوره معین عدم فعالیت فراخوانی می شود. Debouncing به شما امکان می دهد تا زمانی که کاربر تایپ خود را تمام کند یا زمان خاصی از آخرین رویداد گذشته باشد، تماس تابع را به تعویق بیندازید.
برای مثال، تصور کنید که یک فیلد ورودی جستجو دارید و میخواهید یک درخواست API جستجو را تنها زمانی فعال کنید که کاربر تایپ خود را برای مدت معینی، مانند 300ms
به پایان رساند.
با حذف کردن، عملکرد جستجو تنها پس از اینکه کاربر تایپ 300ms
را متوقف کند، فراخوانی میشود. اگر کاربر در آن بازه زمانی به تایپ کردن ادامه دهد، فراخوانی تابع تا زمانی که مکث رخ دهد به تأخیر می افتد. بدون بازگرداندن، تابع برای هر ضربه زدن به کلید فراخوانی می شود، که به طور بالقوه منجر به فراخوانی بیش از حد تابع و محاسبات غیر ضروری می شود. بیایید با یک مثال کد نشان دهیم:
import React, { useState, useEffect } from 'react'; const SearchComponent = () => { const [searchTerm, setSearchTerm] = useState(''); // Function to simulate a search API request const searchAPI = (query) => { console.log(`Searching for: ${query}`); // In a real application, you would make an API request here }; // Debounce function to delay the searchAPI call const debounce = (func, delay) => { let timeoutId; return function (...args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => { func(...args); }, delay); }; }; // Debounced search function const debouncedSearch = debounce(searchAPI, 300); // useEffect to watch for changes in searchTerm and trigger debouncedSearch useEffect(() => { debouncedSearch(searchTerm); }, [searchTerm, debouncedSearch]); // Event handler for the search input const handleSearchChange = (event) => { setSearchTerm(event.target.value); }; return ( <div> <label htmlFor="search">Search:</label> <input type="text" id="search" value={searchTerm} onChange={handleSearchChange} placeholder="Type to search..." /> </div> ); }; export default SearchComponent;
با این تنظیمات، تابع searchAPI
تنها پس از اینکه کاربر تایپ 300 میلیثانیه را متوقف کند، فراخوانی میشود و از درخواستهای بیش از حد API جلوگیری میکند و عملکرد کلی عملکرد جستجو را بهبود میبخشد.
تقسیم کد
تقسیم کد در React تکنیکی است که برای تقسیم یک بسته بزرگ جاوا اسکریپت به قطعات کوچکتر و قابل مدیریت استفاده می شود. به جای بارگیری کل بسته نرم افزاری از قبل، تنها با بارگیری کد لازم برای یک بخش خاص از یک برنامه، به بهبود عملکرد کمک می کند.
هنگامی که یک برنامه React جدید توسعه می دهید، تمام کدهای جاوا اسکریپت شما معمولاً در یک فایل واحد جمع می شوند. این فایل شامل تمام اجزا، کتابخانه ها و سایر کدهای مورد نیاز برای عملکرد برنامه شما می باشد. اما همانطور که برنامه شما رشد می کند، اندازه باندل می تواند بسیار بزرگ شود و در نتیجه زمان بارگذاری اولیه برای کاربران شما کند می شود.
تقسیم کد به شما این امکان را می دهد که یک بسته را به چند تکه تقسیم کنید، که می تواند به طور انتخابی بر اساس نیازهای فعلی برنامه شما بارگذاری شود. به جای دانلود کل بسته نرم افزاری از قبل، زمانی که کاربر از یک صفحه خاص بازدید می کند یا یک اقدام خاص را راه اندازی می کند، فقط کد لازم واکشی و اجرا می شود.
در زیر یک مثال اساسی از تقسیم کد آورده شده است:
// AsyncComponent.js import React, { lazy, Suspense } from 'react'; const DynamicComponent = lazy(() => import('./DynamicComponent')); const AsyncComponent = () => ( <Suspense fallback={<div>Loading...</div>}> <DynamicComponent /> </Suspense> ); export default AsyncComponent; // DynamicComponent.js import React from 'react'; const DynamicComponent = () => ( <div> <p>This is a dynamically loaded component!</p> </div> ); export default DynamicComponent;
در این مثال، AsyncComponent
کامپوننتی است که از lazy
و Suspense
برای انجام تقسیم کد استفاده می کند. DynamicComponent
به صورت پویا با استفاده از دستور import() وارد می شود.
وقتی AsyncComponent
رندر میشود، React DynamicComponent
فقط در صورت نیاز بارگیری میکند و اندازه اولیه باندل را کاهش میدهد و عملکرد برنامه را بهبود میبخشد. پشتیبان بازگشتی در Suspense مشخص میکند که در حین انتظار برای حل شدن واردات پویا، چه چیزی رندر شود و تجربه کاربری بهتری را در طول فرآیند بارگیری ارائه دهد.
React Fragments
React Fragments یک ویژگی معرفی شده در React 16.2 است که به شما امکان می دهد چندین عنصر را بدون اضافه کردن یک گره DOM اضافی با هم گروه بندی کنید. این به ویژه زمانی مفید است که شما نیاز به بازگرداندن چندین عنصر از روش رندر یک مؤلفه دارید، اما نمیخواهید عناصر DOM غیرضروری را معرفی کنید که میتوانند روی طرح یا سبکهای برنامه شما تأثیر بگذارند.
تصور کنید در حال چیدمان کتاب ها در قفسه کتاب هستید. هر کتاب نشان دهنده یک جزء React و قفسه کتاب نشان دهنده DOM است.
به طور معمول، اگر چندین کتاب دارید، ممکن است بخواهید آنها را با هم تحت یک برچسب دسته بندی کنید (مشابه با عنصر DOM مانند <div>
). اما گاهی اوقات شما فقط می خواهید کتاب ها را بدون برچسب کنار هم قرار دهید زیرا خود برچسب ارزشی ندارد و فقط فضای فیزیکی را اشغال می کند.
React Fragments مانند گزینه ای برای چیدمان کتاب ها بدون برچسب است که باعث صرفه جویی در فضا و تمیزتر کردن چیدمان می شود.
در اینجا مثالی از نحوه استفاده از React Fragment ها آورده شده است:
import React from 'react'; function BookShelf() { return ( <> <Book title="React for Beginners" /> <Book title="Mastering Redux" /> <Book title="JavaScript Essentials" /> </> ); } function Book({ title }) { return <li>{title}</li>; } export default BookShelf;
در این مثال، مؤلفه BookShelf
فهرست ی از مؤلفههای Book
را بدون قرار دادن آنها در یک <div>
یا سایر عناصر DOM غیر ضروری برمیگرداند. در عوض، از نحو خلاصه <>
برای React Fragments استفاده می کند.
این منجر به یک ساختار DOM تمیزتر می شود که می تواند عملکرد برنامه React شما را با کاهش تعداد عناصری که مرورگر باید پردازش و ارائه کند، بهبود بخشد. استفاده از قطعات همچنین می تواند نشانه گذاری غیر ضروری را کاهش دهد و به درخت رندر تمیزتر و کارآمدتر کمک کند.
کارگران وب
جاوا اسکریپت به عنوان یک برنامه تک رشته ای طراحی شده برای انجام وظایف همزمان عمل می کند.
هنگامی که یک صفحه وب در حال رندر است، جاوا اسکریپت چندین کار را اجرا می کند، از جمله دستکاری عناصر DOM، مدیریت تعاملات UI، مدیریت داده های پاسخ API، و فعال کردن انیمیشن های CSS، همه در یک رشته واحد. علیرغم کارایی آن در مدیریت این وظایف، اجرای آنها در یک رشته می تواند گاهی اوقات منجر به گلوگاه های عملکرد شود.
Web Workers به عنوان راه حلی برای کاهش بار روی موضوع اصلی عمل می کند. آنها اجازه می دهند تا اسکریپت ها را در پس زمینه روی یک رشته مجزا، مجزا از رشته اصلی جاوا اسکریپت، اجرا کنند.
این جداسازی مدیریت وظایف محاسباتی فشرده، اجرای عملیات طولانی مدت یا مدیریت وظایفی را که ممکن است در غیر این صورت رشته اصلی را مسدود کند، امکان پذیر می کند. با انجام این کار، Web Workers به حفظ پاسخگویی رابط کاربری و عملکرد کلی برنامه کمک می کند.
برای استفاده از web worker در React، یک فایل جاوا اسکریپت جدید ایجاد کنید که حاوی کد رشته worker است:
// worker.js self.onmessage = function(event) { var input = event.data; var result = performHeavyComputation(input); postMessage(result); }; function performHeavyComputation(input) { // Insert your heavy computation logic here return input * 2; // Just a placeholder operation }
در کامپوننت React خود، Web Worker را نمونه سازی کنید و یک کانال ارتباطی با آن ایجاد کنید:
import React, { useEffect, useRef } from 'react'; function MyComponent() { const workerRef = useRef(); useEffect(() => { // Initialize the worker workerRef.current = new Worker('path-to-your-worker-file.js'); // Handle incoming messages from the worker workerRef.current.onmessage = (event) => { console.log('Message received from worker:', event.data); }; // Cleanup the worker when the component unmounts return () => { workerRef.current.terminate(); }; }, []); // Function to send a message to the worker const sendMessageToWorker = (message) => { workerRef.current.postMessage(message); }; // Rest of your component return ( // ... ); }
در این مثال، یک Web Worker در قلاب useEffect
مقداردهی اولیه شده و برای استفاده در آینده در یک ref ذخیره می شود. پیامهای کارگر با یک شنونده رویداد onmessage
مدیریت میشود و زمانی که مؤلفه برای پاک کردن منابع از مونتاژ خارج میشود، کارگر خاتمه مییابد. تابع sendMessageToWorker
نحوه برقراری ارتباط با کارگر با استفاده از postMessage
را نشان می دهد.
از قلاب انتقال استفاده کنید
قلاب useTransition
در React با اجازه دادن به علامت گذاری به روز رسانی های حالت به عنوان انتقال های غیر مسدود کننده، نقش اساسی در بهبود عملکرد برنامه ها ایفا می کند. این قابلیت React را قادر میسازد تا رندر این بهروزرسانیها را به تعویق بیاندازد و از مسدود شدن رابط کاربری جلوگیری کند و پاسخگویی کلی را افزایش دهد.
هنگام استفاده از useTransition,
بهروزرسانیهای حالت در تابع startTransition
بهعنوان انتقالهایی با اولویت پایین تلقی میشوند که مستعد قطع شدن بهروزرسانیهای حالت با اولویت بالاتر هستند. پس اگر یک بهروزرسانی با اولویت بالا در طول یک انتقال رخ دهد، React ممکن است تکمیل بهروزرسانی با اولویت بالا را در اولویت قرار دهد و انتقال در حال انجام را قطع کند.
این مکانیسم انتقال غیرمسدود برای جلوگیری از مسدود شدن رابط کاربری در طول عملیات فشرده مانند واکشی داده یا بهروزرسانیهای در مقیاس بزرگ ارزشمند است. با به تعویق انداختن رندر کردن مؤلفههای مرتبط با بهروزرسانیهای انتقال، React تضمین میکند که رابط کاربری حتی در سناریوهایی که در غیر این صورت ممکن است UI پاسخگو نباشد، پاسخگو باقی میماند.
این مثال استفاده از useTransition
را در یک جزء React نشان می دهد:
import React, { useState, useTransition } from 'react'; function MyComponent() { const [state, setState] = useState(initialState); const [isPending, startTransition] = useTransition(); function handleClick() { startTransition(() => { setState(newState); // This state update is marked as a transition }); } return ( <> {/* Your component JSX */} <button onClick={handleClick}>Update State</button> {isPending && <div>Loading...</div>} </> ); }
این مثال نشان میدهد که چگونه React از مسدود کردن UI در طول انتقالهایی که توسط اقدامات کاربر ایجاد میشود، اجتناب میکند و در صورت شناسایی بهروزرسانیهای حالت با اولویت بالاتر، امکان وقفه وجود دارد.
توجه داشته باشید که useTransition
بخشی از API حالت همزمان است که در React 18 و نسخههای بعدی معرفی شده است. به عنوان یک ابزار قدرتمند برای تغییر رفتار پیشفرض بهروزرسانیهای حالت، مطمئن شوید که با توجه به پیامدهای خاص تعویق رندر در زمینه برنامه خود، از آن با احتیاط استفاده میکنید.
نتیجه
بهینهسازی عملکرد یک برنامه React شامل ترکیبی از استراتژیها، از درک اساسی الگوریتم متفاوت React تا استفاده از آپشن های داخلی و ابزارهای شخص ثالث است.
با بکارگیری عاقلانه این تکنیکها، میتوانید برنامههایی ایجاد کنید که نه تنها از نظر بصری جذاب هستند، بلکه عملکردی نیز دارند که منجر به تجربه کلی بهتر کاربر میشود.
ارسال نظر