Forwarded from Node Master (Iman Hosseini Pour)
همیشه ما همه تلاش داریم کد با Performance خوب توسعه بدیم بدون این که این موضوع رو تصور کنیم که داخل کدبیس های #JavaScript معمولا Performance شوخیه.
ولی امروز قراره درمورد یک ویژگی جدید که در آپدیت ES2025 به #JavaScript اضافه شده صحبت کنیم که بهمون کمک میکنه که Performance بهتری داشته باشیم. سمت #NodeJS در بیزینس لاجیک های پیچیده میتونه معجزه کنه. برای #FrontEnd هم کاربردی هست ولی باتوجه به این که مرورگر های قدیمی ساپورت نمیکنن خب قطعا به این زودی استفاده ازش رو نمیبینیم.
ویژگی جدید ما اضاف شدن یک static method جدید به Iterator هست.
حالا سوال پیش میاد که چطور این به ما کمک میکنه. فرض کنید یک array بزرگ دارید و میخواید data رو map کنید به یک شکل دیگه و برای این کار یک pipeline از map ها رو ایجاد کردید:
در نگاه اول مشکلی نداره ولی اگر با عینک Performance ببینیم دوتا مشکل میبینیم.
1. برای هر map مجبوریم یکبار کامل loop بزنیم خب 3 بار loop میزنیم پس داریم O(3n)
2. هربار که یک loop کامل میزنیم هربار داریم یک Array جدید بعد از map ایجاد میکنیم. به صورت خلاصه هر .map برابر هست با یک Array allocation جدید. خب اینجا یک array اورجینال داریم و 3 تا map پس 4 تا array allocation داریم.
ممکنه برای تازه کارترها سوال های زیر پیش بیاد:
1. خب چرا اصلا این استایل کد میزنیم؟
2. چرا همه رو داخل یک map انجام نمیدیم؟
پاسخ سوال اول:
- میتونیم با for ... of کار رو بهتر با یک loop در بیاریم ولی مسئله این هست که معمولا برنامه نویس های #JavaScript در اینجور مواقع حتی بدون این که خودشون بدونن دیدگاه Functional Programming دارن و خب از اونجایی که به صورت فلسفی FP ذات Declarative داره و به صورت فلسفی کار کردن با API ها Declarative خیلی راحت تر و لذت بخش تر از Imperative هست همچین چیزی رو میبینیم.
- اگر هم خیلی کنجکاوید بیشتر بدونید وقتش هست نگاهی به #Elixir #Scala یا حتی Lambda ها در #Java اونجا قشنگ متوجه میشید. یا اصلا مسیر رو برعکس برید و نگاهی به رویکرد #Golang کنید و فرق زمین تا آسمونی رو ببینید.
پاسخ سوال دوم:
- در بزینس لاجیک های پیچیده برای خوانایی کد داشتن map های بیشتر خیلی بهتر از این هست که یک map بزرگ داشته باشیم. منطقی هم هست چون خیلی بهمون God Object ها رو یادآوری میکنه.
خب حالا سوال پیش میاد چیکار کنیم؟ خیلی ساده هست کافیه فقط خط اول رو به این شکل عوض کنیم و array رو تبدیل کنیم به Iterator.
خب دوباره الان سوال پیش میاد که WTF الان چی شد؟ سادس.
ما دیتا رو تبدیل کردیم به یک Iterator که ذات Iterator ها به صورت Lazy هست یعنی تا وقتی که نیاز به consume شدن data نباشه هیچ پردازشی انجام نمیشه و اگر هم نیاز به map کردن باشه دقیقا در runtime به صورت on-demand برای هر index تبدیل انجام میشه و ما نیازی به alloc کردن حافظه اضافه برای Array نداریم و هیچ loop اضافه ای هم درکار نیست.
حالا به این نکات توجه کنید:
- هر iterator رو فقط یکبار میشه consume کرد و اگر نیاز باشه باید دوباره ازش بسازی. در حقیقت با .toArray داریم consume کردن رو شبیه سازی میکنیم و دومی مقدار خالی به ما میده به خاطر iterator بودن.
- در این قسمت به map ها باید توجه کرد که با هر بار call شدن یک Array جدید نمیسازن بلکه یک Iterator جدید که روی Iterator قبلی سوار هست رو به ما میده! پس در نتیجه با توجه به تعریف Iterator که بالاتر گفتم نه loop اضافه ای داریم و نه alloc اضافه.
حالا اگر یکم بیشتر دقت کنی میبینیم خیلی شبیه به stream ها هست. اصلا این دوتا api به شدت باهم سازگار هستن. در این حد که استریم ها رو میشه تبدیل کرد به iterator و برعکس. بقیه کد هم دقیقا به صورت مشابهه کار میکنه.
دل نوشته:
حقیقتا دیگ نمیشه تفاوت بین stream, iterator, generator, rxjs, web stream, رو تشخیص داد😂. همشون رو میتونی جایگزین هم استفاده کنی. ( دلایل مختلفی برای وجود این همه api برای یک کار هست )
ولی امروز قراره درمورد یک ویژگی جدید که در آپدیت ES2025 به #JavaScript اضافه شده صحبت کنیم که بهمون کمک میکنه که Performance بهتری داشته باشیم. سمت #NodeJS در بیزینس لاجیک های پیچیده میتونه معجزه کنه. برای #FrontEnd هم کاربردی هست ولی باتوجه به این که مرورگر های قدیمی ساپورت نمیکنن خب قطعا به این زودی استفاده ازش رو نمیبینیم.
ویژگی جدید ما اضاف شدن یک static method جدید به Iterator هست.
Iterator.from()
حالا سوال پیش میاد که چطور این به ما کمک میکنه. فرض کنید یک array بزرگ دارید و میخواید data رو map کنید به یک شکل دیگه و برای این کار یک pipeline از map ها رو ایجاد کردید:
const data = [1, 2, 3, 4, 5];
const final = data
.map((item) => item.toString())
.map((item) => `- ${item} -`)
.map((item) => `${item} ${new Date()}`);
در نگاه اول مشکلی نداره ولی اگر با عینک Performance ببینیم دوتا مشکل میبینیم.
1. برای هر map مجبوریم یکبار کامل loop بزنیم خب 3 بار loop میزنیم پس داریم O(3n)
2. هربار که یک loop کامل میزنیم هربار داریم یک Array جدید بعد از map ایجاد میکنیم. به صورت خلاصه هر .map برابر هست با یک Array allocation جدید. خب اینجا یک array اورجینال داریم و 3 تا map پس 4 تا array allocation داریم.
ممکنه برای تازه کارترها سوال های زیر پیش بیاد:
1. خب چرا اصلا این استایل کد میزنیم؟
2. چرا همه رو داخل یک map انجام نمیدیم؟
پاسخ سوال اول:
- میتونیم با for ... of کار رو بهتر با یک loop در بیاریم ولی مسئله این هست که معمولا برنامه نویس های #JavaScript در اینجور مواقع حتی بدون این که خودشون بدونن دیدگاه Functional Programming دارن و خب از اونجایی که به صورت فلسفی FP ذات Declarative داره و به صورت فلسفی کار کردن با API ها Declarative خیلی راحت تر و لذت بخش تر از Imperative هست همچین چیزی رو میبینیم.
- اگر هم خیلی کنجکاوید بیشتر بدونید وقتش هست نگاهی به #Elixir #Scala یا حتی Lambda ها در #Java اونجا قشنگ متوجه میشید. یا اصلا مسیر رو برعکس برید و نگاهی به رویکرد #Golang کنید و فرق زمین تا آسمونی رو ببینید.
پاسخ سوال دوم:
- در بزینس لاجیک های پیچیده برای خوانایی کد داشتن map های بیشتر خیلی بهتر از این هست که یک map بزرگ داشته باشیم. منطقی هم هست چون خیلی بهمون God Object ها رو یادآوری میکنه.
خب حالا سوال پیش میاد چیکار کنیم؟ خیلی ساده هست کافیه فقط خط اول رو به این شکل عوض کنیم و array رو تبدیل کنیم به Iterator.
const data = [1, 2, 3, 4, 5, 6]; ❌
const data = Iterator.from([1, 2, 3, 4, 5, 6]); ✅
خب دوباره الان سوال پیش میاد که WTF الان چی شد؟ سادس.
ما دیتا رو تبدیل کردیم به یک Iterator که ذات Iterator ها به صورت Lazy هست یعنی تا وقتی که نیاز به consume شدن data نباشه هیچ پردازشی انجام نمیشه و اگر هم نیاز به map کردن باشه دقیقا در runtime به صورت on-demand برای هر index تبدیل انجام میشه و ما نیازی به alloc کردن حافظه اضافه برای Array نداریم و هیچ loop اضافه ای هم درکار نیست.
حالا به این نکات توجه کنید:
- هر iterator رو فقط یکبار میشه consume کرد و اگر نیاز باشه باید دوباره ازش بسازی. در حقیقت با .toArray داریم consume کردن رو شبیه سازی میکنیم و دومی مقدار خالی به ما میده به خاطر iterator بودن.
const data = Iterator.from([1, 2, 3, 4, 5, 6]);
data.toArray()
data.toArray()
- در این قسمت به map ها باید توجه کرد که با هر بار call شدن یک Array جدید نمیسازن بلکه یک Iterator جدید که روی Iterator قبلی سوار هست رو به ما میده! پس در نتیجه با توجه به تعریف Iterator که بالاتر گفتم نه loop اضافه ای داریم و نه alloc اضافه.
const data = Iterator.from([1, 2, 3, 4, 5, 6]);
const final = data
.map((item) => item.toString())
.map((item) => `- ${item} -`)
.map((item) => `${item} ${new Date()}`);
حالا اگر یکم بیشتر دقت کنی میبینیم خیلی شبیه به stream ها هست. اصلا این دوتا api به شدت باهم سازگار هستن. در این حد که استریم ها رو میشه تبدیل کرد به iterator و برعکس. بقیه کد هم دقیقا به صورت مشابهه کار میکنه.
import { Readable } from "node:stream";
const data = Iterator.from([1, 2, 3, 4, 5, 6]);
const streamData = Readable.from(data);دل نوشته:
حقیقتا دیگ نمیشه تفاوت بین stream, iterator, generator, rxjs, web stream, رو تشخیص داد😂. همشون رو میتونی جایگزین هم استفاده کنی. ( دلایل مختلفی برای وجود این همه api برای یک کار هست )
👍3
🧠 تفاوت SSR و CSR و تأثیرش روی سئو
توی CSR (Client Side Rendering)، سرور یه فایل HTML ساده (معمولاً خالی) میفرسته. مرورگر بعدش باید کلی فایل JavaScript رو دانلود و اجرا کنه تا محتوای صفحه ساخته بشه. این یعنی محتوای واقعی دیرتر به دست رباتهای موتور جستجو میرسه و ممکنه ایندکس شدن صفحه عقب بیفته.
ولی توی SSR (Server Side Rendering)، سرور همون اول محتوای صفحه رو رندر میکنه و یه HTML کامل میفرسته.
در این صورت:
محتوای صفحه همون اول تو پاسخ رندر میشه.
ربات جستجو لازم نیست صبر کنه تا JS اجرا بشه، همون اول محتوا رو میخونه.
ایندکس شدن و رتبه گرفتن سریعتر انجام میشه.
نمونه تکنولوژیها و فریمورکهایی که SSR دارن:
Next.js برای React
Nuxt.js برای Vue
Angular Universal برای Angular
Sapper / SvelteKit برای Svelte
به همین دلیله که SSR برای سایتهایی مثل فروشگاه، بلاگ یا هر جایی که محتوای عمومی داره و میخوایم تو گوگل دیده بشه خیلی به درد میخوره. ولی برای اپلیکیشنهای داخلی یا داشبوردها که ایندکس شدن مهم نیست، همون CSR کافی هست.
توی CSR (Client Side Rendering)، سرور یه فایل HTML ساده (معمولاً خالی) میفرسته. مرورگر بعدش باید کلی فایل JavaScript رو دانلود و اجرا کنه تا محتوای صفحه ساخته بشه. این یعنی محتوای واقعی دیرتر به دست رباتهای موتور جستجو میرسه و ممکنه ایندکس شدن صفحه عقب بیفته.
ولی توی SSR (Server Side Rendering)، سرور همون اول محتوای صفحه رو رندر میکنه و یه HTML کامل میفرسته.
در این صورت:
محتوای صفحه همون اول تو پاسخ رندر میشه.
ربات جستجو لازم نیست صبر کنه تا JS اجرا بشه، همون اول محتوا رو میخونه.
ایندکس شدن و رتبه گرفتن سریعتر انجام میشه.
نمونه تکنولوژیها و فریمورکهایی که SSR دارن:
Next.js برای React
Nuxt.js برای Vue
Angular Universal برای Angular
Sapper / SvelteKit برای Svelte
به همین دلیله که SSR برای سایتهایی مثل فروشگاه، بلاگ یا هر جایی که محتوای عمومی داره و میخوایم تو گوگل دیده بشه خیلی به درد میخوره. ولی برای اپلیکیشنهای داخلی یا داشبوردها که ایندکس شدن مهم نیست، همون CSR کافی هست.
👍1
یه جاهایی دیدم بعضی از دوستان سر اینکه از چه لایبرری برای UI پروژه استفاده کنند خوبه بحث میکردن.
موردی که هست اینه که اگه شما پروژتون UI داره و دارین طبق اون پیش میرین ، اصلا منطقی نیست از هیچ لایبرری استفاده کنین! و خودتون باید کامپوننت هاش رو بنویسین.
مگر اینکه UI پروژه طبق همون لایبرری طراحی شده باشه.
وگرنه از نظر من کاستومایز کردن کامپوننت های یک لایبرری برای یک UI اختصاصی نه تنها منطقی نیست ، بله غیر حرفه ای هم هست.
موردی که هست اینه که اگه شما پروژتون UI داره و دارین طبق اون پیش میرین ، اصلا منطقی نیست از هیچ لایبرری استفاده کنین! و خودتون باید کامپوننت هاش رو بنویسین.
مگر اینکه UI پروژه طبق همون لایبرری طراحی شده باشه.
وگرنه از نظر من کاستومایز کردن کامپوننت های یک لایبرری برای یک UI اختصاصی نه تنها منطقی نیست ، بله غیر حرفه ای هم هست.
👍6
دوستان مدتیه سرم شلوغ شده وقت نکردم اینجا پست بذارم.
در طول کار مطالب زیادی به ذهنم میان که بذارم ، ولی چون توضیحشون یکم مفصل میشه از گذاشتن مطالب سطحی پرهیز کردم.
با این حال چه مفصل چه غیر مفصل سعی میکنم بذارم مطالب رو.
در طول کار مطالب زیادی به ذهنم میان که بذارم ، ولی چون توضیحشون یکم مفصل میشه از گذاشتن مطالب سطحی پرهیز کردم.
با این حال چه مفصل چه غیر مفصل سعی میکنم بذارم مطالب رو.
❤4
سید فرندز / برنامه نویسی / هک و امنیت / تکنولوژی
گوگل زحمت کشیده یک مدل امبدینگ جدید ساخته که خیلی شیک و تر و تمیز فارسی هم پشتیبانی میکنه. مدل EmbeddingGemma! یه مدل جدید هوش مصنوعی که قراره سر و شکل دنیای آنلاین ما رو عوض کنه. 🚀 حالا این مدل چی هست و به چه دردی میخوره؟ 🤔 فرض کن یه وبسایت فروشگاهی…
طبق تجربه ای که در استفاده از این مدل داشتم خیلی راضی کننده نبود برام.
به جاش مدل BGE-M3 رو پیشنهاد میکنم که با 567M پارامتر خیلی بهتر عمل کرد.
(منظورم از بین مدل های Open Source هست)
به جاش مدل BGE-M3 رو پیشنهاد میکنم که با 567M پارامتر خیلی بهتر عمل کرد.
(منظورم از بین مدل های Open Source هست)
یه دفتر بزرگ دارم ، داشتم تقسیم میکردم که از فلان صفحه تا فلان صفحه برای این موضوع ، و از فلان صفحه تا فلان صفحه برای یه موضوع دیگه و ... .
دیدم ناخودآگاه دارم از آرایه استفاده میکنم! شاید تعداد صفحاتی که برای هر موضوع انتخاب میکنم کم و بیش بشه و دفتر من هم که محدوده.
به جاش از لیست پیوندی استفاده کردم و توی هر صفحه ، اشاره کردم که صفحه بعدی دقیقا کجاست و ... .
به شما هم پیشنهاد میکنم که در این مواقع از لیست پیوندی استفاده کنید 😁
پ.ن:البته این برای من جواب میداد چون بیشتر مینویسم تا بخونم. اگه شما بیشتر میخونید تا بنویسید ، بذارید روی همون آرایه بمونه.
دیدم ناخودآگاه دارم از آرایه استفاده میکنم! شاید تعداد صفحاتی که برای هر موضوع انتخاب میکنم کم و بیش بشه و دفتر من هم که محدوده.
به جاش از لیست پیوندی استفاده کردم و توی هر صفحه ، اشاره کردم که صفحه بعدی دقیقا کجاست و ... .
به شما هم پیشنهاد میکنم که در این مواقع از لیست پیوندی استفاده کنید 😁
پ.ن:البته این برای من جواب میداد چون بیشتر مینویسم تا بخونم. اگه شما بیشتر میخونید تا بنویسید ، بذارید روی همون آرایه بمونه.
👍4❤1
اینا هم از سالن همراه اول بود که بیشتر یه حالت سرگرمی بدون هیجان بود.
و ظاهر سازی جالب.
و ظاهر سازی جالب.
😁2
این غرفه هم خوراک گیمر ها بود !
🔥2