<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های محمدرضا.م</title><link>https://virgool.ir/feed/@mohammadreza.mn</link><description>فرانت‌اند دولوپری که فنجانش را خالی کرد ☕</description><language>fa</language><pubDate>2026-11-11 17:09:22</pubDate><image><url>https://files.virgool.ir/upload/users/90996/avatar/7cUpUH.png</url><title>محمدرضا.م</title><link>https://virgool.ir/@mohammadreza.mn</link></image><item><title>اصل پارکینسون را فراموش نکنیم</title><link>https://virgool.ir/@mohammadreza.mn/اصل-پارکینسون-را-فراموش-نکنیم-pek2k4smxutu</link><description>رابطه بین مدت زمان و مقدار تلاش برای انجام یک کار ثابتهر کاری به اندازه زمانی که برای آن تخصیص داده شود طول می‌کشدوقتی دانشجو هستید و در پایان هر ترم لازم است که یک مقاله ارائه دهید معمولاً این مقاله‌ها را تنها ۷۲ ساعت قبل از ضرب‌الاجل تحویل شروع و ۵ صبح آن‌ها را برای استاد خود ایمیل می‌کنید.تمام هفته را وقت دارید تا پژوهش خود را انجام دهید اما تا عصر جمعه کاری انجام نمی‌دهید و می‌خواهید آن را در چند ساعت باقی‌مانده به پایان ببرید.با اینکه می‌دانید جشن عروسی در پیش دارید اما برنامه‌ای برای کم کردن وزن خود ندارید و در ۴ هفته پایانی رژیم غذایی سنگینی می‌گیرید تا وزن خود را به ایده‌آل برسانید.شما و تیم‌تان دو هفته فرصت دارید تا یک باگ فیکس نسبتاً ساده را انجام دهید اما اینکار در واقع فقط باید چند ساعت طول بکشد ولی از آنجایی که می‌دانید زمان کافی در اختیار دارید، دامنه تسک را افزایش می‌دهید پس در حالی که شما در حال بررسی آن باگ هستید، تصمیم می‌گیرید چند مشکل مرتبط را نیز بررسی کنید. این کار باعث می‌شود که در مورد اولویت‌ها به مشکل بر بخورید و ندانید کدام کار را باید اول انجام دهید. در حالی که انجام کارهای دیگر نیز برای شما مفید خواهید بود اما در نهایت شما را از باگ فیکس اصلی دور خواهند کرد و در نهایت چیزی که واقعاً باید یک کار ساده باشد، تبدیل به چالشی می‌شود که در واقع به دو هفته برای تکمیل آن نیاز دارید.اگر یکی از موقعیت‌‌های بالا را تجربه کرده باشید، به راحتی درک می‌کنید که قانون پارکینسون چیست. ساده است شما مدت‌ها برای انجام کاری فرصت دارید، اما آن را انجام نمی‌دهید و ناگهان به ماشینی تبدیل می‌شوید که در لحظات پایانی کار را به اتمام می‌رساند.کار گسترش می یابد تا زمان موجود برای تکمیل آن پر شودهر گاه شما زمان زیادی را برای کاری ساده تخصیص دهید، آن کار به همان اندازه کش می آید و نه تنها تاثیری در کیفیت کار ندارد بلکه استرس و بار فکری آن کار را به مدت طولانی تری باید تحمل کنیدایریل نورث کوت پارکینسون تاریخ شناس و نویسنده انگلیسی در سال 1955 برای اولین بار این تعریف را در مجله ی طنز اکونومیست ارائه داد.اصل پارکینسون می گوید: &#34;هر کار به اندازه زمانی که برای آن تخصیص داده شده، طول می‌کشد&#34;. و این یعنی شما چه برای پروژه پایان ترم خود یک ماه وقت بگذارید چه یک هفته، در نهایت این پروژه را در آخرین روز تعیین شده به اتمام خواهید رساند.نکته ای که پارکینسون در یکی از مقالات خود به آن اشاره کرده، این است که سالانه 5 الی 7 درصد به تعداد کارمندان سازمانِ بروکراتیک بریتانیا اضافه می شود، هر چند کار سازمان تغییری پیدا نمیکند. بحث دیگر مربوط به بودجه است که وقتی برای کاری حس کنیم بودجه ی زیادی لازم است، به طور قطع کل آن بودجه را صرف آن کار میکنیم حتی اگر در واقعیت با نصف آن مقدار هم بشود پروژه را با همان کیفیت به اتمام رساند.پارکینسون بر این باور بود هرچه اندازه و حجم کار بزرگ شود، کارآمدی و بازده افراد پائین می‌آید.علت وجود اصل پارکینسون در واقع یک سیستم روانی است که به ذهن دستور میدهد نهایت استفاده از هر چیزی باید انجام بگیرد که یعنی نهایت استفاده از زمان، بودجه، افراد، فضا و ...این بدان معنی است که مثلا اگر شما یک هفته جهت انجام یک فعالیت 2 روزه زمان اختصاص بدهید پیچیدگی و سختی این فعالیت (از لحاظ روانی) به میزانی که یک هفته تمام وقت شما را پر کند افزایش می‌یابد. اگرچه ممکن است در زمان اضافی در نظر گرفته شده به جز تحمل فشار و استرس ناشی از انجام آن کار، هیچ کار اضافه دیگری انجام نشود.وقتی همکارتون از اصل پارکینسون بی خبر هستدر ادامه با چند روش برای استفاده از اصل پارکینسون در جهت افزایش راندمان آشنا می‌شویمداشتن راندمان یا بازده بالا یعنی هر کاری را با کیفیت مطلوب و در زمان کوتاه انجام دهیم.  یکی از راهبردی ترین روش ها این است که بدون در نظر داشتن مهلت انجام یک کار، برای به اتمام رساندن آن کار یک زمان ساختگی اما قراردادی تعیین کنیم. یعنی برای مثال اگر یک هفته برای کاری فرصت داریم، برای خودمان زمان قراردادی را سه روز تعیین کنیم و خود را موظف کنیم که در این بازه ی زمانی کار را به نتیجه برسانیم.از دیگر راه های اثربخش در این زمینه خرد کردن کارهای بزرگ است. به این شکل که اگر یک کار با بخش های مختلف داریم، آن را به زیربخش های جداگانه و با بازه های زمانی مجزا تقسیم کنیم تا به راندمان بالاتری برسیم.عوامل حواس پرتی را به حداقل برسانید و سعی بر حذف آنها داشته باشید تا یک محیط کاری متمرکز ایجاد کنید و بهره‌وری خود را به حداکثر برسانید.تمرکز بر کارهای ضروری، مهمترین کارهایی را که باید انجام شوند شناسایی کنید و آن‌ها را اولویت بندی کنید. این کار به شما کمک می کند تا از اتلاف وقت برای کارهای غیر ضروری جلوگیری کنید و از قانون پارکینسون بهتر استفاده کنید.از تکنیک پومودورو استفاده کنید، کار خود را به فواصل کوتاهتر 25 دقیقه‌ای تقسیم کنید و بین آن یک استراحت پنج دقیقه‌ای بگذارید. این امر می‌تواند به شما در حفظ تمرکز و جلوگیری از فرسودگی کمک کند.اجتناب از انجام چند کار موازی، تمرکز روی یک کار در یک زمان می تواند سازنده‌تر از تلاش برای انجام چندین کار به طور همزمان باشد.وظایف را محول کنید، اگر کار زیادی دارید بخشی از آن را به دیگران محول کنید تا بار کاری شما کاهش یابد.زمانی را که صرف کارها می‌کنید محدود کنید (Time Box)، برای هر کار یک تایمر تنظیم کنید و تلاش کنید تا آن را در آن محدوده زمانی کامل کنید.نکته بسیار مهمی که در استفاده از قانون پارکینسون باید مد نظر قرار دهیم این است که باید ضرب‌الاجل انجام کارها را به کمترین میزان ممکن برسانیم، نه آنکه آن‌قدر زمان را کم کنیم تا کیفیت کار به پایین‌ترین حد ممکن تنزل کند.ددلاین‌های سوزان و آتشیناصطکاک سازمانی چیزی ست که در مورد آن می خواهیم صحبت کنیم. اتفاقی که در رابطه با تعداد افراد درگیر یک پروژه می افتد. به این صورت که اگر حس کنیم کاری برای به انجام رسیدن نیاز به پنج نفر دارد، این کار دیگر با تعداد کمتر از پنج نفر در مهلت مقرر انجام نمی شود. حتی اگر آن کار را بشود با دو نفر در همان مدت زمان انجام داد.بسیاری از کارمندان تصور می‌کنند که با کار کردن تا دیر وقت یا انجام کارها از خانه، میزان تعهد خود به کارشان را به مدیران و همکارانشان نشان می‌دهند و مقدار بیشتری از امور را پیش می‌برند، اما حقیقت جور دیگری است. بسیاری از این کارمندان تصور دارند که کار بیشتری انجام می‌دهند و در حقیقت کار کم‌تری انجام می‌شود. این در حالی است که همیشه استرس و دلهره کار را نیز با خود به همراه دارند.از سوی دیگر انجام زودتر از موعد یك فعالیت معمولا پاداشی به همراه نداشته و ممكن است باعث شود تا مسئولیت دیگری به فرد داده شود. بنابراین گذراندن و اتلاف زمان برای انجام فعالیت به سود فرد است، زیرا فشار كاری كمتری به او وارد می‌شود.فقط توجه کنید که میان “حداقل زمان مورد نیاز جهت انجام یک فعالیت” و “با کمبود وقت مواجه شدن جهت انجام آن” تفاوت عمده‌ای وجود دارد. هدفی که باید به دنبال آن باشیم اجرای صحیح و بی نقص یک فعالیت در کوتاه ترین زمان ممکن است، نه اینکه کاری کنیم که، کارمان و یا حتی مشتری خود را از دست بدهیم! قانون پارکینسون این را نمی‌خواهد.</description><category>محمدرضا.م</category><author>محمدرضا.م</author><pubDate>Sun, 11 Feb 2024 21:05:07 +0330</pubDate></item><item><title>از کمیته TC39 چه خبر؟</title><link>https://virgool.ir/@mohammadreza.mn/از-کمیته-tc39-چه-خبر-dxl3zimn9l6z</link><description>twitter.com/bitandbangتو این مقاله قراره خیلی خلاصه و کوتاه با ecma و آخرین دستاوردهای کمیته TC39 آشنا بشیماکما یک سازمان سوئیسی هست که کار اون تعریف کردن استانداردهای بین‌المللی است و سازندگان جاوااسکریپت این زبان رو برای استانداردسازی به این سازمان ارائه دادن و اسم این استاندارد رو ECMA-262 گذاشته شد که ما با نام مستعار ECMAScript می‌شناسیم و به صورت خلاصه به اون ES گفته میشه، پس اکمااسکریپت یک استاندارد است و شامل یک سری ویژگی‌ها و مشخصات هست که زبانی مثل جاوااسکریپت نسخه‌ی پیاده‌سازی شده و عینی این استاندارد و ویژگی‌ها هست، البته زبان‌های دیگه‌ای مثل اکشن‌اسکریپت و جی‌اسکریپت هم طبق این استاندارد پیاده‌سازی شدن اما جاوااسکریپت معروف‌ترین زبانی هست که این استاندارد رو پیاده‌سازی کرده.جالبه بدونید یک زبان می‌تونه در کنار استانداردها و ویژگی‌های اکمااسکریپت، ویژگی‌های منحصر به فرد خودش رو هم داشته باشه. مثلاً توی جاوااسکریپت و نسخه‌ای که توی مرورگرها در دسترس هست، ما یک تابع داریم به اسم alert این تابع در استاندارد اکمااسکریپت وجود نداره و بقیه نسخه‌ها مجبور به پیاده‌سازی اون نیستن برای همین در محیطی مثل نود این تابع در دسترس نیست.کمیته TC39 از زیر مجموعه سازمان بین المللی ECMA هست که بر به روزرسانی ها و تغییراتی که در سازمان اعمال می شود نظارت می کند. وقتی پیشنهادی برای به روزرسانی جدید به ECMA ارسال می شود، باید مراحل مختلف زیر را طی کند و در این کمیته افرادی از شرکتهایی مثل مازیلا، گوگل، اپل، فیسبوک و ... حضور دارند. حالا که با ecma و tc39 آشنا شدیم در ادامه با هم بعضی از متدهای جدید جاوااسکریپت بررسی می‌کنیم:1_The toReversed() method of Array instances is the copying counterpart of the reverse() method. It returns a new array with the elements in reversed order.const numbers = [1, 2, 3, 4, 5, 6]&#xA;const toReversed= numbers.toReversed()&#xA;console.log({ numbers, toReversed})&#xA;&#xA;// { numbers: [1, 2, 3, 4, 5, 6], reversed: [6, 5, 4, 3, 2, 1] } 2_The toSorted() method of Array instances is the copying version of the sort() method. It returns a new array with the elements sorted in ascending order.const numbers = [2, 6, 4, 1, 3, 5]&#xA;const toSorted = numbers.toSorted()&#xA;console.log({ numbers, toSorted })&#xA;&#xA;// { numbers: [2, 6, 4, 1, 3, 5], toSorted: [1, 2, 3, 4, 5, 6] }3_The toSpliced() method of Array instances is the copying version of the splice() method. It returns a new array with some elements removed and/or replaced at a given index.const numbers = [1, 2, 3, 4, 5, 6]&#xA;const start = numbers.toSpliced(3)&#xA;const startAndDeleteCount = numbers.toSpliced(3, 2)&#xA;const addItem = numbers.toSpliced(3, 2, &#39;one&#39;, &#39;two&#39;)&#xA;console.log({ numbers, start, startAndDeleteCount, addItem })&#xA;&#xA;// { numbers: [1, 2, 3, 4, 5, 6], start: [1, 2, 3], startAndDeleteCount: [1, 2, 3, 6], addItem: [1, 2, 3, &#39;one&#39;, &#39;two&#39;, 6] }4_The with() method of Array instances is the copying version of using the bracket notation to change the value of a given index. It returns a new array with the element at the given index replaced with the given value.const numbers = [1, 2, 3]&#xA;const changeNumber = numbers.with(1, &#34;two&#34;)&#xA;console.log({ numbers, changeNumber })&#xA;&#xA;// { numbers: [1, 2, 3], changeNumber: [1, &#39;two&#39;, 3] }5_The findLast() method of Array instances iterates the array in reverse order and returns the value of the first element that satisfies the provided testing function. If no elements satisfy the testing function, undefined is returned.const numbers = [110, 220, 3, 4, 5, 6]&#xA;const findItem = numbers.findLast(number =&gt; number &gt; 4)&#xA;console.log({ numbers, findItem })&#xA;&#xA;// { numbers: [110, 220, 3, 4, 5, 6], findItem: 6 }6_The findLastIndex() method of Array instances iterates the array in reverse order and returns the index of the first element that satisfies the provided testing function. If no elements satisfy the testing function, -1 is returned.const numbers = [110, 220, 3, 4, 5, 6]&#xA;const findIndex = numbers.findLastIndex(number =&gt; number &gt; 4)&#xA;console.log({ numbers, findIndex })&#xA;&#xA;// { numbers: [110, 220, 3, 4, 5, 6], findIndex: 5 }7_The at() method of Array instances takes an integer value and returns the item at that index, allowing for positive and negative integers. Negative integers count back from the last item in the array.const numbers = [110, 220, 3, 4, 5, 6]&#xA;const item = numbers.at(3)&#xA;const lastItem = numbers.at(-1)&#xA;console.log({ numbers, item, lastItem })&#xA;&#xA;// { numbers: [110, 220, 3, 4, 5, 6], item: 4, lastItem: 6 }8_The flat() method of Array instances creates a new array with all sub-array elements concatenated into it recursively up to the specified depth.const numbers = [1, 2, [3, 4], 5, [[6], 7], [[[[8]]]]]&#xA;const flat = numbers.flat()&#xA;const flatDepth = numbers.flat(2)&#xA;const flatInfinity = numbers.flat(Infinity)&#xA;console.log({ numbers, flat, flatDepth, flatInfinity })&#xA;&#xA;// { numbers: [1, 2, [3, 4], 5, [[6], 7], [[[[8]]]]], flat: [1, 2, 3, 4, 5, [6], 7, [[[8]]]], flatDepth: [1, 2, 3, 4, 5, 6, 7, [[8]]], flatInfinity: [1, 2, 3, 4, 5, 6, 7, 8] }9_The flatMap() method of Array instances returns a new array formed by applying a given callback function to each element of the array, and then flattening the result by one level. It is identical to a map() followed by a flat() of depth 1 (arr.map(...args).flat()), but slightly more efficient than calling those two methods separately.const numbers = [1, 2, 3, 4, 5, 6]&#xA;const week = [&#34;Monday 1&#34;, &#34;Tuesday 2&#34;, &#34;Wednesday 3&#34;, &#34;Thursday 4&#34;, &#34;Friday 5&#34;, &#34;Saturday 6&#34;, &#34;Sunday 7&#34;]&#xA;const flatMap = numbers.flatMap((number) =&gt; [`n_${number}`, number * 2])&#xA;const flatMapAndSplit = week.flatMap((day) =&gt; day.split(&#34; &#34;))&#xA;console.log({ flatMap, flatMapAndSplit })&#xA;&#xA;// { flatMap: [&#39;n_1&#39;, 2, &#39;n_2&#39;, 4, &#39;n_3&#39;, 6, &#39;n_4&#39;, 8, &#39;n_5&#39;, 10, &#39;n_6&#39;, 12], flatMapAndSplit: [&#39;Monday&#39;, &#39;1&#39;, &#39;Tuesday&#39;, &#39;2&#39;, &#39;Wednesday&#39;, &#39;3&#39;, &#39;Thursday&#39;, &#39;4&#39;, &#39;Friday&#39;, &#39;5&#39;, &#39;Saturday&#39;, &#39;6&#39;, &#39;Sunday&#39;, &#39;7&#39;] }10_The trim, trimStart, trimEnd method of String values removes whitespace from this string and returns a new string, without modifying the original string.const string = &#39;    hello  &#39;&#xA;const trimStart = string.trimStart()&#xA;const trimEnd = string.trimEnd()&#xA;const trim = string.trim()&#xA;console.log({ string, trimStart, trimEnd, trim })&#xA;&#xA;// { string: &#39;    hello  &#39;, trimStart: &#39;hello  &#39;, trimEnd: &#39;    hello&#39;, trim: &#39;hello&#39;}11_The padEnd and padStart method of String values pads this string with a given string (repeated, if needed) so that the resulting string reaches a given length.const string = &#39;hello&#39;&#xA;const padEnd = string.padEnd(6)&#xA;const padEndAndItem = string.padEnd(10, &#39;...&#39;)&#xA;const padStart = string.padStart(6)&#xA;const padStartAndItem = string.padStart(10, &#39;...&#39;)&#xA;console.log({ string, padEnd, padEndAndItem, padStart, padStartAndItem })&#xA;&#xA;// { string: &#39;hello&#39;, padEnd: &#39;hello &#39;, padEndAndItem: &#39;hello.....&#39;, padStart: &#39; hello&#39;, padStartAndItem: &#39;.....hello&#39; }12_The startsWith and endsWith method of String values determines whether this string begins / ends with the characters of a specified string, returning true or false as appropriate.const string = &#39;Hello, how are you?&#39;&#xA;const startsWith = string.startsWith(&#39;Hello&#39;)&#xA;const startsWithAndPosition = string.startsWith(&#39;Hello&#39;, 3)&#xA;const endsWith = string.endsWith(&#39;?&#39;)&#xA;const endsWithAndPosition = string.startsWith(&#39;?&#39;, 3)&#xA;console.log({ string, startsWith, startsWithAndPosition, endsWith, endsWithAndPosition })&#xA;&#xA;// { string: &#39;Hello, how are you?&#39;, startsWith: true, startsWithAndPosition: false, endsWith: true, endsWithAndPosition: false }13_The hasOwnProperty() method of Object instances returns a boolean indicating whether this object has the specified property as its own property (as opposed to inheriting it).const objectHello = { hello: &#39;salam&#39; }&#xA;const objectFlower = Object.create(null)&#xA;objectFlower.dahlia = &#34;Dahlia is a genus of bushy, tuberous, herbaceous perennial plants native to Mexico and Central America.&#34;&#xA;&#xA;console.log(Object.hasOwn(objectHello, &#39;hello&#39;)) //true&#xA;console.log(Object.hasOwn(objectHello, &#39;toString&#39;)) //false&#xA;console.log(Object.hasOwn(objectFlower, &#39;dahlia&#39;)) //true&#xA;console.log(objectHello.hasOwnProperty(&#39;toString&#39;)) //false&#xA;console.log(objectHello.hasOwnProperty(&#39;hello&#39;)) //true&#xA;console.log(&#39;hello&#39; in objectHello) //true&#xA;console.log(&#39;toString&#39; in objectHello) //true&#xA;console.log(&#39;dahlia&#39; in objectFlower) //true&#xA;// console.log(objectFlower.hasOwnProperty(&#39;dahlia&#39;)) objectFlower.hasOwnProperty is not a function14_The Object.fromEntries() static method transforms a list of key-value pairs into an object.const array = [ [&#39;one&#39;, &#39;a&#39;], [&#39;two&#39;, &#39;b&#39;], [&#39;three&#39;, [&#39;c&#39;, &#39;d&#39;, &#39;e&#39;, &#39;f&#39;]] ]&#xA;console.log(Object.fromEntries(array))&#xA;&#xA;// { one: &#39;a&#39;, two: &#39;b&#39;, three: [&#39;c&#39;, &#39;d&#39;, &#39;e&#39;, &#39;f&#39;] }15_Top-level await enables developers to use the await keyword outside of async functions. It acts like a big async function causing other modules who import them to wait before they start evaluating their body.console.log(&#34;hello&#34;)&#xA;await new Promise(r =&gt; setTimeout(r, 1000))&#xA;console.log(&#34;bye&#34;)16_The logical OR assignment (||=) operator only evaluates the right operand and assigns to the left if the left operand is falsy.const user = { lastName: &#34;Hopkins&#34;, firstName: &#39;&#39;, age: 10, city: null }&#xA;user.lastName ||= &#34;---&#34;&#xA;user.firstName ||= &#39;Anthony&#39;&#xA;user.age &amp;&amp;= 85&#xA;user.city ??= &#34;Margam&#34;&#xA;console.log(user)&#xA;&#xA;// { lastName: &#39;Hopkins&#39;, firstName: &#39;Anthony&#39;, age: 85, city: &#39;Margam&#39; }منابع:https://github.com/tc39/proposals/blob/HEAD/finished-proposals.mdhttps://exploringjs.com/impatient-js/ch_new-javascript-features.htmlhttps://v8.dev/features/top-level-await</description><category>محمدرضا.م</category><author>محمدرضا.م</author><pubDate>Thu, 17 Aug 2023 14:24:09 +0330</pubDate></item><item><title>آشنایی با تست در فرانت</title><link>https://virgool.ir/@mohammadreza.mn/آشنایی-با-تست-در-فرانت-yxrklgauhxza</link><description>کد بدون تست مثل ساندویچ بدون سس هست ?تو این مقاله قراره خیلی خلاصه و کوتاه با انواع تست نویسی و ابزارهای آن در فرانت آشنا بشویمانواع تست‌‌ها :تست‌ها به صورت کلی به سه دسته Unit، Integration، End to End تقسیم بندی میشن، اگر بین این سه دسته مسابقه‌ای بر اساس شاخص‌های &#34;سرعت&#34; و &#34;هزینه&#34; برگزار کنیم قهرمان کم هزینه‌ و سریع‌ترین مدل تست نویسی unit میشه و نایب قرمان Integration و جایگاه سوم به عنوان گران‌ترین و کندترین مدل تست نویسی تعلق می‌گیره به E2E که البته این باخت از ارزشهای آن کم نمی‎کند چون هر کدام از این سه در میدان مخصوص به خودشان قهرمان هستند?تقسیم‌بندی مدل‌های تست نویسی با رسم شکل?تست Unit :در تست unit، هر بخش اختصاصی از کدهای برنامه را به صورت مجزا تست می‌کنیم تا مطمئن بشویم آن قسمت از کد مطابق انتظار ما کار می کند، به صورتی که کوچکترین بخش از یک برنامه با ارائه ورودی و اطمینان از اینکه خروجی مطابق انتظار ماست به صورت مستقل مورد تست قرار می‌گیرد و نباید کد مورد تست دارای وابستگی باشد، تست باید خیلی ساده و کوچک بوده و ایزوله و مستقل از سایر تست‌ها بدون وابستگی به محیط و زمان قابل اجرا باشد.Test-driven development (TDD)تست Integration :تستی که بر روی تعامل بین اجزا، ماژول‌ها و اشیایی که با هم کار می‌کنند تمرکز دارد و معمولا نسبت به unit تست زمان بیشتری برای نوشتن نیاز دارد، برای مثال اگر یک navigation bar با یک دکمه login / logout داشته باشیم توقع داریم که :- اگر کاربری به برنامه لاگین کرد، نوار پیمایش دکمه logout را نمایش دهد- اگر کاربر لاگین نکرده بود، دکمه login به او نمایش داده شودتست integration معمولاً به صورت مجزا اجرا می‌شود (برای مثال تست integration کامپوننت بدون تست بقیه برنامه) این سطح از تست است که اطمینان می‌دهد بخش‌های مختلف سیستم به درستی باهم تعامل دارند و داده‌ها و اطلاعات بین آنها به درستی پاس داده می‌شود. در باب مقایسه با unit تست باید گفت که در حالی که تست‌های unit از همدیگر جدا هستند و در واقع در یک فضای ایزوله شده قرار می‌گیرند تست‌های integration روی بخش‌هایی که ساید افکت دارند و یا ارتباط داشتن بین دو یا چند قسمت یا بخش‌هایی که نیازمند قسمت‌های دیگر سیستم هستند کار میکنند.وقتی فقط unitتست رو قبول داریم? تست E2E :sign up: pass?بالاترین سطح از تست‌های خودکار فرآیندی معروف به End-to-End می‌باشد که به عنوان تست E2E یا Functional Test هم شناخته می‌شود. وقتی می‌خواهیم ارتباط با کاربر را در یک نرم افزار تست کنیم از تست E2E استفاده می‌کنیم، هدف اصلی از تست E2E آزمایش تجربه کاربر نهایی با شبیه سازی سناریوی واقعی کاربر و اعتبارسنجی سیستم تحت آزمایش و اجزای آن برای یکپارچگی است. در این سطح تمام اکشن‌های کاربر از ابتدای وارد شدن به سیستم تا آخرین مرحله شبیه سازی می شود.فرض کنید در زمانی که کاربر روی یک دکمه کلیک میکند انتظار داریم چه اتفاقاتی در کل برنامه بیوفتد. روش کار در این مدل از تست به این صورت است که برنامه از محیط مرورگر استفاده میکند و میتوان ارتباط کاربر با app را شبیه سازی و تست کند. تفاوت این تست با تست عملکرد (integration) در گام به گام بودن مراحل تست است و همچنین دامنه آن شامل تمام توابع و سرویس ها می‌شود و از آن در زمانی استفاده می‌کنیم که یک فیچر به صورت کامل اجرا شده است زیرا از نظر مدت نوشتن تست بیشتر از دو مدل قبلی نیاز به زمان دارد.ابزارهای تست نویسی :حتی از استوری بوک عزیز میشه برای تست نویسی هم استفاده کردJest :یک فریمورک محبوب برای نوشتن تست در جاوا اسکریپت که توسط فیسبوک ارائه شده و تمرکز آن بر روی سادگی‌ است و با تمامی فریمورک‌های محبوب جاوا اسکریپت مثل React و React Native و... بدون هیچ پیکربندی خاصی قابل استفاده است، در jest مفاهیمی مانند mock و snapshot وجود دارد که بسیار کاربردی است، در واقع mock کردن (mocking) یک تکنیک تست نویسی است که در آن قسمتی از کد را با یک پیاده سازی دلخواه جایگزین میکنیم و از آن برای شبیه سازی یک عملیات واقعی استفاده میشه. معمولا ماک کردن زمانی استفاده میشه که یک متد یا کلاس، وابستگی یا وابستگی هایی داره که توی تستمون تداخل ایجاد میکنه.مثلا فرض کنید یک فانشن رو میخواین تست کنین که داخلش از سرویس اسمس استفاده شده، برای اینکه موقع تست به سرویس مربوطه وابسته نباشیم مقدار برگشتی سرویس اسمس را mock میکنیم.رندر کردن کامپوننت‌ها و تبدیل اونا به یه آبجکت pure JavaScript را Snapshot میگویند بدون اینکه وابستگی به DOM یا محیط اجرایی داشته باشیم. snapshot از سلسله مرتب view(یه چیزی شبیه به درخت DOM) که توسط ReactDOM یا React Native درست میشه رو بدون نیاز به مرورگر برای ما فراهم می آورد و می‌توانیم این shotها را با هم مقایسه کرده و روی اختلاف بین آنها شرط قبولی یا رد شدن تست را بگذاریم.testing-library :این فریم ورک هم مانند jest در هنگام استفاده از ری اکت به صورت CRA نصب میشود و نیازی به تنظیمات برای راه اندازی ندارد، از آن برای تست های مربوط به DOM استفاده میشود. برای مواردی مانند تست هوک ها، کاستوم هوک ها و ... نیز پکیج های مخصوص به خود را دارد.Enzyme :یکی از کتابخانه های کاربردی تست جاوا اسکریپت است که توسط airbnb ارائه شده و کار کردن با آن بسیار راحت است و همچنین متدهای بسیار کاربردی را برای دستکاری و کنترل DOM مجازی ری اکت بدون نیاز به مرورگر ارائه میدهد.شبیه سازی ایونت ها، دسترسی و قابیلت تغییر در مقادیر پراپس و استیت، رندر سطحی (Shallow rendering) از مزایای آن است، به عنوان مثال ویژگی رندر سطحی به ما این امکان رو میده که فقط کامپوننت والد مورد نظرمون رو رندر کنیم بدون اینکه نگران عملکرد کامپوننت‌های فرزند باشیم.Cypress :این فریم ورک مخصوص انجام تست های E2E (تعامل کاربر با برنامه) طراحی شده است و دارای پنل اختصاصی می باشد که در آن روند انجام تست به همراه وضعیت و اطلاعات مربوطه نمایش داده میشود و مانند سایر فریم ورک ها نتایج تست را در ترمینال نمایش نمیدهد.نمایی از برنامه در حال اجرای تست</description><category>محمدرضا.م</category><author>محمدرضا.م</author><pubDate>Tue, 03 Jan 2023 17:04:08 +0330</pubDate></item><item><title>پشت پرده event loop</title><link>https://virgool.ir/@mohammadreza.mn/پشت-پرده-event-loop-uqpp0okt7zew</link><description>جاوا اسکریپت ارتش یک نفره هست؟!چطور جاوا اسکریپت با وجود single-thread بودن می‌تواند &#34;هم زمان&#34; با ارسال request هم برای شما یک انیمیشن لودینگ نمایش دهد و هم کلی کار دیگه انجام بدهد؟برای یافتن جواب این سوال اول باید کمی به عقب برگردیم و ببینیم IO چیست ؟https://medium.com/@fjcalzado/asynchronous-javascript-8cc9a993bfd0کلمه IO مخفف شده input/output است و اگر میخواهید بدانید برنامه شما I/O-bound یا CPU-bound هست میتوانید با این سوال شروع کنید که با افزایش کدام دسته از منابع عملکرد برنامه شما بهتر میشود، بالا بردن قدرت CPU یا بیشتر کردن حافظه رم و سرعت هارد دیسک، کارت شبکهبه طور مثال در Node.js برنامه از نوع I/O-bound است و با افزایش سرعت هارد دیسک عملکرد کلی برنامه بهتر میشود و در مقابل سرویس رمزنگاری SHA-1 (تابع درهم ‌سازی در مقوله رمزنگاری است که یک ورودی می گیرد و یک مقدار درهم ۱۶۰ بیتی ( ۲۰ بایت ) تولید می کند) از نوع CPU-bound هست و با بالا بردن قدرت CPU زمان رمزنگاری کاهش می یابد.تقریبا تمام برنامه‌هایی که با جاوا اسکریپت نوشته می‌شوند به نحوی با عملیات IO مثل فرستادن request به سرور، هندل کردن input  کاربر و … سروکار دارند و همچنین می‌دانیم که عملیات IO معمولا نسبت به سرعت پردازش CPU، بسیار کند هستند و به زمان بیشتری برای کامل شدن احتیاج دارند.https://bytearcher.com/articles/io-vs-cpu-boundدو روش کلی برای انجام دادن IO وجود دارد:1. Blocking IOدر این روش وقتی یک request به سرور می‌فرستیم (یا هر عملیات IO دیگر) اجرای برنامه متوقف می‌شود و تا زمانی که سرور به request پاسخ ندهد thread که کد روی آن اجرا می‌شود block می‌شود.در بعضی زبان‌ها برای اینکه بتوانیم از blocking IO استفاده کنیم و درعین حال کل برنامه freeze نشود، می‌توانیم برای هر عملیات IO  یک thread جدید ایجاد کنیم تا بقیه‌ پردازش‌های برنامه در یک thread مجزا ادامه پیدا کنند. اما با توجه به اینکه جاوا اسکریپت فقط بر روی یک thread اجرا می‌شود امکان استفاده از این روش داخل جاوا اسکریپت را نداریم.2. Non-Blocking IOدر این روش بعد از فرستادن request به سرور صبر نمی‌کنیم تا request تکمیل شود و CPU بلافاصله می‌تواند بقیه پردازش‌های برنامه را انجام دهد ( non-blocking IO فقط یک مثال از asynchrony است)حالا که مشخص شد جاوا اسکریپت جزء برنامه‌های I/O-bound هست و از سیستم پاسخ‌دهی Non-Blocking استفاده میکند برویم سراغ دو برادر ناتنی به نام‌های Parallelism و Concurrency ??‍?‍??https://techdifferences.com/difference-between-concurrency-and-parallelism.html Parallelismدر parallelism همانطور که از اسم آن مشخص است چند تسک به صورت موازی و دقیقا در یک لحظه پردازش می‌شوند. برای پردازش parallel معمولا از چند thread (یا process) برای اجرای عملیات مختلف استفاده می‌شود. بنابراین با توجه به single-thread بودن جاوا اسکریپت عملا نمی‌توانیم دو کار را دقیقا در یک لحظه انجام دهیم.Concurrencyهمچنین Concurrency به این معنی است که چند تسک مختلف در یک بازه‌ زمانی انجام شوند (اما نه لزوما هم ‌زمان و در یک لحظه) در واقع concurrency مفهوم کلی‌تری نسبت به parallelism است و می‌توانیم بدون پردازش parallel هم، concurrency داشته باشیم.به عنوان مثال فرض کنید یک پروژه داریم که بخش‌های مختلفی دارد و اگر چند تیم بر روی بخش‌های مختلف این پروژه کار کنند بخش‌های مختلف پروژه به صورت هم ‌زمان و parallel پیشرفت می‌کند اما اگر فقط یک نفر روی این پروژه کار کند در یک لحظه فقط بر روی یک بخش از پروژه کار می‌شود و بخش‌های مختلف به صورت هم ‌زمان پیشرفت نمی‌کنند. اما همچنان پروژه به صورت concurrent انجام می‌شود. چرا که بخش‌های مختلف پروژه در یک بازه‌ زمانی با هم پیشرفت می‌کنند هر چند دقیقا در یک لحظه بر روی همه‌ بخش‌ها کار نمی‌شود.https://visihow.com/Choose_the_Right_Laptop_That_Fits_Your_Needs حالا که متوجه شدیم فقط با استفاده از یک thread هم می‌توانیم بیش از یک کار را در یک بازه‌ زمانی انجام دهیم بیایید نگاهی به دو روش کلی multitasking در نرم‌افزار داشته باشیم و در نهایت ببینیم کارکرد جاوا اسکریپت به کدام یکی از این دو روش نزدیکتر است.1. Preemptive Multitaskingدر این روش معمولا برای پردازش تسک‌های مختلف، چند thread ایجاد می‌شود و اگر اجرای یک thread بیش از حد زمان بگیرد سیستم عامل می‌تواند اجرای آن را متوقف کند در کل این threadها توسط سیستم عامل مدیریت می‌شوند و حتی ممکن است به صورت موازی (parallel) اجرا شوند.2. Cooperative Multitaskingدر این روش کل برنامه از دید سیستم عامل فقط بر روی یک thread اجرا می‌شود اما تسک‌های مختلف در داخل خود برنامه مدیریت می‌شوند به این صورت که در هر لحظه یک تسک اجرا می‌شود و مقداری پردازش روی CPU انجام می‌دهد سپس CPU را آزاد می‌کند (اصطلاحا yield می‌کند) تا تسک بعدی اجرا شود و به این ترتیب تسک‌های مختلف از یک thread به صورت اشتراکی استفاده می‌کنند.به این روش cooperative گفته می‌شود چون برای کارکرد درست کل سیستم همه‌ تسک‌ها باید با هم همکاری کنند و اگر یک تسک پردازش طولانی روی CPU انجام دهد کل برنامه کند می‌شود که در این روش مدیریت تسک‌های مختلف بر عهده‌ برنامه ‌نویس است و عملکرد جاوا اسکریپت به شدت شبیه به همین مدل است و تسک‌های concurrent به صورت اشتراکی از یک thread استفاده می‌کنند و ما به عنوان برنامه ‌نویس باید این تسک‌ها را به درستی مدیریت کنیم و اگر یک تابع، پردازش طولانی روی CPU انجام می‌دهد، باید آن را به چند تسک کوچک‌تر تقسیم کنیم تا کل برنامه کند نشود.تا اینجای کار متوجه شدیم که جاوا اسکریپت چندین تسک را در یک بازه‌ زمانی بر روی یک thread پردازش می‌کند و در هر لحظه فقط یک تسک را انجام می‌دهد.همکاری مرورگر و جاوا اسکریپتhttps://devrant.com/rants/841405/just-noticed-this-while-talking-to-someone-not-familiar-with-js-and-node-developبرنامه ما برای اجرا شدن نیاز به host environment دارد که می تواند مرورگر، Node.js ، Deno ، electron.js و ... باشد تا با کمک آن موارد زیر فراهم بشود1. Call Stack  (V8)2. Heap (V8)3. Task queue (macrotask queue and microtask queue)4. Event loop5. Web API and Web DOMhttps://cabulous.medium.com/how-v8-javascript-engine-works-5393832d80a7 Call Stackجاوا اسکریپت هم مثل خیلی از زبان‌های دیگر برای مشخص کردن اینکه در هر لحظه چه تابعی در حال اجرا است از ساختمان داده‌ Stack استفاده می‌کند به این صورت که با صدا شدن هر تابع، یک frame جدید به بالای call stack اضافه می‌شود (push) و با بازگشت از هر تابع، یک frame از بالای call stack حذف می‌شود (pop) و نکته مهم اینکه هر تسکی که وارد call stack می‌شود باید تا انتها اجرا شود تا تسک بعدی بتواند اجرا شود بنابراین اگر می‌خواهیم یک پردازش طولانی انجام دهیم، مثلا اگر بخواهیم روی یک آرایه‌ خیلی طولانی map بزنیم باید این کار را به چند تسک کوچک ‌تر تبدیل کنیم و در چند مرحله انجام دهیم یا اینکه تسک مورد نظر را به یک web worker منتقل کنیم.Task Queueوقتی از یکی از APIهای async مثل timeout استفاده می‌کنیم در واقع عملیات مورد نظر داخل hosting environment اتفاق می‌افتد و نه داخل انجین جاوا اسکریپت، مثلا اگر که داخل کد یک timeout با زمان ۲ثانیه و به همراه یک callback تعریف کنیم سپس این timer داخل مرورگر یا Node.js ایجاد می‌شود و کد جاوا اسکریپت می‌تواند به صورت Non-Blocking به اجرا شدن ادامه دهد اما بعد از حدود ۲ثانیه، مرورگر callback را به عنوان یک تسک داخل لیستی به نام Task Queue  قرار می‌دهد تا بعدتر این تسک‌ها داخل انجین جاوا اسکریپت اجرا شوند.به این ترتیب APIهای مختلف بعد از اتمام کارشان یک تسک به این صف از تسک‌ها اضافه می‌کنند تا بعدتر، این تسک‌ها به نوبت داخل call stack اجرا شوند اما چه مکانیزمی این تسک‌ها را از task queue به انجین جاوااسکریپت و call stack منتقل می‌کند ?Event Loopاحتمالا تا الان متوجه شده‌اید که Event Loop پل ارتباطی بین hosting environment و انجین جاوا اسکریپت است و مشاهده کردیم که عملیات async (مثل ارسال درخواست به سرور و استفاده از تایمر) داخل hosting environment انجام می‌شوند و بعد از اتمام عملیات، یک تسک به task queue اضافه می‌کند.https://suneetbansal.medium.com/event-loop-macro-vs-micro-task-javascript-bd4296768b64 پس event loop بین این تسک‌ها و انجین جاوا اسکریپت ارتباط برقرار می‌کند. در واقع event loop یک پروسه است که دائما اجرا می‌شود و هر بار چک می‌کند که اگر call stack خالی باشد، قدیمی‌ترین تسک داخل task queue را اجرا می‌کند (به call stack منتقل می‌کند)، همچنین به هر iteration از Event Loop یک tick گفته می‌شود.Heapقسمت call stack به یک فضای پیوسته (پشت سرهم) تو حافظه رم نیاز داره که این موضوع پردازش رو خیلی سریع میکنه اما این مدل فضا رو خیلی کم و سخت میتونی تو حافظه پیدا کنی برای همین مقادیر references و primitive data types در آن ذخیره میشن ولی مقادیر (objects, functions, array) non-primitive data types در heap قرار می گیرند که تمام این تصمیم گیری ها مربوط به نحوه مدیریت حافظه در جاوا اسکریپت هست.https://felixgerschau.com/javascript-memory-management/Task queue (Microtask and Macrotask Queue)کدهایی که به صورت sync هستن وارد task queue میشوند و فقط کدهای setTimeout , setInterval و event handler ها به داخل macrotask queue ریخته میشوند اما پرامیس ها یا همون کال بک هایی که داخل then مینویسیم به محض مشخص شدن وضعیت پرامیس از web api به داخل یه صف جدا و خاص به اسم microtask queue ریخته میشوند.https://getridbug.com/node-js/difference-between-microtask-and-macrotask-within-an-event-loop-context/اگر در کد با استفاده از setTimeout یک تسک به انتهای task queue اضافه کنیم و به محض اجرا شدن این تسک دوباره با استفاده از setTimeout یک تسک دیگر به انتهای task queue اضافه کنیم و این روند به صورت مداوم ادامه دهیم این کد باعث freeze شدن مرورگر نمی‌شود چرا که هر بار مرورگر این تسک‌ها را به انتهای صف اضافه می‌کند و به این ترتیب تسک‌های دیگر هم فرصت اجرا شدن پیدا می‌کنند اما اگر دوست دارید freeze شدن مرورگرتان را ببینید می‌توانید این کد را بعد از خواندن مقاله در تب console اجرا کنید?function applyBrowserFreeze() { Promise.resolve().then(() =&gt; { applyBrowserFreeze(); console.log(&#34;apply browser Freeze&#34;); }); } applyBrowserFreeze();https://suneetbansal.medium.com/event-loop-macro-vs-micro-task-javascript-bd4296768b64 اما گاهی می‌خواهیم این تسک‌ها  async باشن و به انتهای صف اضافه نشوند و دقیقا بعد از تسکی که الان در حال اجراست، اجرا شوند پس سراغ Microtask می رویم، بیشترین کاربرد microtaskها، در Promiseهای جاوا اسکریپت است.https://suneetbansal.medium.com/event-loop-macro-vs-micro-task-javascript-bd4296768b64  در واقع هر تسک زمانی که در حال اجرا شدن است می‌تواند چندین microtask ایجاد ‌کند و این microtaskها در یک صف دیگر به نام microtask queue قرار می‌گیرند و دقیقا بعد از تمام شدن تسکی که در حال اجراست (و قبل از اجرای تسک بعدی)، همه‌ی این microtaskها به ترتیب اجرا می‌شوند. یعنی microtaskها عملیات async هستند که بعد از هر تسک اجرا می‌شوند (و به انتهای صف تسک‌ها منتقل نمی‌شوند) و اولویت با microtaskها است و بعد macrotaskها پس حالا اولویت event loop برای انجام دقیقا به این ترتیب هست:اول call stack هستش که کد های sync داخلش ریخته میشونددوم microtask queue هستش که کال بک های پرامیس داخل آن ریخته میشوندسوم macrotask queue یا callback queue هستش که کال بک های زمان بندی شده در آن وجود دارندhttps://suneetbansal.medium.com/event-loop-macro-vs-micro-task-javascript-bd4296768b64 ?‍? برای درک بهتر کل فرایند می‌توانید وارد این لینک شده و کد بنویسید و اجرای آن را توسط event loop مشاهده کنید و همچنین برای دقیق تر شدن در تفاوت و اولویت بندی های Microtask و Macrotask ها می توانید از این لینک استفاده کنید و با کد نوشتن به صورت عملی آنها را تجربه کنید.</description><category>محمدرضا.م</category><author>محمدرضا.م</author><pubDate>Fri, 28 Oct 2022 15:46:09 +0330</pubDate></item><item><title>اشتراک گذاری لوکال هاست</title><link>https://virgool.ir/@mohammadreza.mn/لوکال-هاست-برای-همه-dsuksjrx1ux7</link><description>بیلد گرفتن پروژه و دیپلوی روی سرور خوبه اما نه همیشهصورت مسئله: پروژه هنوز به مرحله‌ای نرسیده که بشه ازش بیلد گرفت و روی سرور دیپلوی کرد اما نیاز هست کاربر که میتونه مدیر، طراح رابط کاربری، کارفرما و... باشه از روی سیستم خودش به محصول در حال دولوپ دسترسی پیدا کنه و بتونه باهاش کار کنهاینکه بشه قبل از بیلد گرفتن پروژه اون با دیگران به اشتراک گذاشت موردی هست که میتونه در زمان و انرژی تیم صرفه جویی کنه و به افراد اون سمت میز درک بهتری از پروژه بده، پس بریم سراغ راه حل‌‌ها ⛷️اشتراک گذاری آی پی آدرس؛شرایط استفاده از این راه حل اینجوری که همه افراد (مهمان) از جمله خود سیستمی که پروژه روی لوکال هاستش بالا هست (میزبان) باید به یک شبکه وصل باشن که اگه نباشن داستان کمی سخت تر میشه و میزبان آی پی آدرس سیستم خودش و پورتی که الان پروژه روش بالا هست رو در اختیار کاربرها قرار میده تا آنها با استفاده از این اطلاعات بتونن به لوکال هاست سیستم اش دسترسی پیدا کنن.خوب شما به عنوان میزبان برای پیدا کردن آی پی آدرس خودتون میتونید بعد از وصل شدن به شبکه‎‌ای که با بقیه هماهنگ کردید داخل ترمینال بزنید ipconfig و برای شماره پورت هم (که معمولا 3000 یا 5000 یا 80) باید به اعداد انتهای لوکال هاستتون نگاه کنید مثلا http://localhost:3000 که یعنی پورت 3000 است.حالا اون ور مهمان ها باید بعد از وارد کردن آدرس آی پی شما بزنن 3000: تا براشون لوکال هاست شما بالا بیاد ?تجربه خود من که منجر به شکست شد ? و امیدوارم برای شما هم زیاد منجر به موفقیت نشه چون تو این روش احتمال بروز مشکلات امنیتی وجود داره و زیاد توصیه نمیشه ازش استفاده کنیدبرنامه ngrok؛یک برنامه کوچک اما باحال که شعارش &#34;وقت بیشتری را صرف برنامه نویسی کنید&#34; هست و می تونید از اینجا دانلود کنیدش،از برنامه میتونید حتی بدون ثبت نام در وبسایت‌اش به راحتی با زدن یک خط استفاده کنید اما من ثبت نام می‌کنم تا ببینم چه چیزهایی داره ?محیط برنامه، البته من اینجا توکنی که از طریق ثبت نام گرفته بودم وارد کردمبعد از ثبت نام از طریق دستور  ****** ngrok authtoken توکن خودن در برنامه ذخیره کنید تا بتونید از داشبوردی که در وبسایت براتون باز شده استفاده کنید، حالا بریم سراغ چیزی که اصلا این برنامه رو به خاطرش دانلود کردیم.اول پروژه با هر ابزاری که باهاش کار میکنید اجرا کنید، اینجا من با vs code کار میکنم و پروژه هم ری اکت هست پس داخل ترمینال دستور yarn start وارد میکنم و پروژه برام روی پورت 3000 اجرا میشه، اگر هم خواستید پورت رو تغییر بدید میتونید برید داخل package.json و scripts و بعد مقدار start برابر با set PORT=**** &amp;&amp; react-scripts start بذارید که به جای ستاره پورتی که دوست دارید وارد میکنید.github.com/mohammadreza4mn راستی سورس این پروژه داخل گیت هاب من هست حالا برنامه ngrok باز میکنیم و طبق راهنما دستور ngrok http 3000 وارد میکنیم، دیگه لازم نیست که اینجا بگم مقدار 3000 از کجا آوردم ?لوکال هاست من برای همهخوب همین جور که می‌بینید دوتا لینک با پروتکل‌های http و https برام ساخته، دستش درد نکنه حالا نوبت من هست که یکی از این لینک‌ها رو برای مهمان‌های لوکال هاستم ارسال کنم ?لوکال هاستم جهانی شد D:خوش آمدید به لوکال هاست من ? الان مهمان‌ها از هر جایی با هر سیستمی که بتونه به اینترنت وصل بشه به لوکال هاست و طبعا به پروژه دسترسی دارن و میتونن آب و هوای شهر خودشون بررسی کنن، اما یه سوال من از کجا بدونم چه کسایی و چه مقدار به لوکال هاست من دسترسی دارن؟؟ ?بالاتر گفتم که داخل ngrok ثبت نام کردم تا ببینم چه چیزهایی ارائه میده اما اکثر مواردی که داخل داشبورد بود هنوز تو نسخه بتا هست و برای استفاده باید درخواست ارسال کنید تا براتون کلید ارسال کنن و خوب بقیه موارد مثل اینکه بتونید ساب دامین داشته باشید و... جز پلن‌های پولی حساب میشه اما داخل خود برنامه تعداد درخواست‌هایی که به لوکال هاستتون زده میشه به همراه وضعیت آنها رو بهتون نشون میده.پکیج localtunnel؛این پکیج رو می‌تونید با دستور npm install -g localtunnel در ترمینال به صورت سراسری روی سیستم خودتون یا با دستور yarn add localtunnel فقط روی پروژه مورد نظرتون نصب کنید و لینک گیت هابش هم این هست.ساده و مختصربعد از اجرا کردن پروژه داخل ترمینال با یه خط کد لوکال هاست شما آنلاین میشه ?lt --port **** --subdomain ****قسمت پورت که همون پورت لوکال هاست شما هست و قسمت ساب دامین هم (همونی که ngrok تو پلن پولی قرار داده بود ?) اختیاری هست و میتونه مثلا نام شرکت یا خود شما باشه یا میتونید نذارید و به صورت رندرم آدرس ساخته بشه و ادامه داستان هم مثل قبل هست که لینک ساخته شده برای مهمان ها ارسال میکنید و محدودیتی در تعداد و محل قرارگیری آنها نداره.</description><category>محمدرضا.م</category><author>محمدرضا.م</author><pubDate>Fri, 25 Sep 2020 16:46:03 +0330</pubDate></item><item><title>راهنمای خرید استیکر</title><link>https://virgool.ir/@mohammadreza.mn/خریدن-استیکر-بهانه-شد-gqgzsdw9slwm</link><description>pngtree.com وکتور از وبسایت شاید خریدن استیکر برای خیلی‌ها شامل رفتن به شهر کتاب یا جستجو کردن در گوگل و انتخاب طرح و رنگ استیکر دلخواه و بعد خریدن و چسباندن آن بشود اما برای من کمی فرق داشت...سلام من محمدرضا هستم یک معمار که تصمیم گرفت به جای خانه‌های گرم و دلنشین وب سایت‌های زیبا و کاربردپذیر طراحی کند و در این مطلب می‌خواهم درباره بررسی و کمی مقایسه دو وبسایت دوست داشتنی و باحال گیکتوری و فلربو بنویسم.هر دو این وبسایت‌ها دارای نکات مشترکی هستند اما مهم‌ترین آنها فروش استیکر است، اما استیکر چیست؟ در واژه یاب شکلک معنی شده است و در نوشته امیر حسین به معنی تصاویری که در قالب کارتونی برای بیان احساسات و رفتار و ... در فضای اینترنت مورد استفاده میشوند گفته شده و شاید هم برای شما تفاوت اموتیکون ، اسمایلی ، ایموجی و استیکر جالب باشد اما من برای جلوگیری از طولانی شدن متن فقط به دادن لینک اکتفا میکنم.گوگل محل آشنایی ما با خیلی از وبسایت‌ها است اما من اولین بار داخل توییتر با فربلو و بعد گیکتوری آشنا شدم و این یعنی آنها در محل درست به دنبال مشتری مشخصی خودشان هستند چون هر دو نگاه ویژه ای به برنامه نویس‌ها و افراد فعال در حوزه آی تی دارند و چه محلی بهتر از توییتر برای پیدا کردن افراد گیک و نوجویان این حوزه.گفتم گوگل محل آشنا شدن ما با خیلی از وبسایت‌ها است اما اینکه در جواب جستجوی ما موتورهای جستجوگر چه نتایجی را به ما نمایش بدهند به عوامل مختلفی بستگی دارد که آنها را به اسم سئو می شناسیم، هر چه قدر بهینه سازی برای موتورهای جستجو توسط تیم بهتر انجام شده باشد نرخ وردی بازدید کننده از موتورهای جستجوگر بیشتر میشود. به طور کلی برای سنجش عملکرد وبسایت از لحاظ سئو و سایر موارد تیم فنی از ابزارهایی مثل گوگل آنالیتیکس و سرچ کنسول استفاده می‌کند.#سئوwoorank.com اسکرین شات از   برای سنجیدن نمره سئو می‌توانید از سرویس‌های مختلفی از جمله ahrefs، woorank، moz و ... استفاده کنید که هر کدام دارای ویژگی‌های گوناگونی هستند. اکثر این سرویس‌ها به صورت فریمیوم عمل می‌کنند و موارد مشابهی را اندازه گیری کرده اما نمره نمایش داده آنها با هم متفاوت است، این نکته را در نظر داشته باشید که الگوریتم‌های گوگل همیشه در حال تغییر هستند و پارامترهای زیادی در نمره نهایی سئو یک وبسایت موثر است که حتی خیلی از این پارامترها توسط گوگل اعلام رسمی نمی‌شود و کارشناسان این حوزه آنها را شناسایی می‌کنند.از نظر سرویس woorank وبسایت فلربو دارای نمره سئو بهتری نسبت به گیکتوری است اما بازهم تاکید می‌کنم که شاید در یک سرویس دیگر نتیجه نمره سئو متفاوتی برای این دو وبسایت نمایش داده شود.اگر خواستید خیلی سریع محل قرارگیری وبسایتی را در نتایج جستجوی گوگل بررسی کنید پیشنهاد من اول رفتن بر روی حالت new incognito window در گوگل کروم و بعد جستجوی کلمه کلیدی آن وبسایت است.#الکسااسکرین شات از وبسایت الکسا در تاریخ 98/09/07الکسا یک سیستم رتبه بندی جهانی است که متعلق به آمازون می‌باشد و بر اساس تعداد بازدیدکنندگان و متوسط تعداد صفحاتی که هر نفر در سایت بازدید کرده است اقدام به رتبه بندی وبسایت‌ها می‌کند و همان طور که در تصویر بالا می‌بینید رتبه الکسا فلربو در ایران 5635 است و نسبت به گیکتوری از جایگاه بهتری برخوردار است.همین جا این نکته را هم بگم که آمارهایی مثل رتبه الکسا قابل دستکاری هستند و به نوعی آن قدر هم که عموم فکر می‌کنند قابل اتکا نیست.گفتم وقتی سئو وبسایت قوی باشد نرخ بازدید کننده از سمت موتورهای جستجوگر بیشتر میشود که این قسمت جز زیر مجموعه دیجیتال مارکتینگ حساب میشود، اما آیا بازدید کننده بیشتر برابر با درآمد بیشتر است؟ مسلما جواب نه است.یک مثال؛ وقتی برای خرید کردن به مراکز خرید می‌رویم از تعداد زیادی فروشگاه به واسطه دکور، برند، معرفی دوستان و ... دیدن می‌کنیم که در هر کدام میزان زمان متفاوتی را صرف بررسی محصولات می‌کنیم اما در تعداد کمی از این فروشگاه‌ها مثلا با فروشنده وارد گفتگو می‌شویم و در آخر هم فقط از یک فروشگاه خرید خودمان را انجام می‌دهیم.اسکرین شات از وبسایت الکسا در تاریخ 98/09/07 در مثال بالا (خرید از بین فروشگاه‌ها) به سه پارامتر اشاره شد: بازدیدعکس العمل (فعل صحبت کردن با فروشنده)خریددر قسمت Site Metrics الکسا به سه مورد جالب اشاره شده است که می‌توان آنها را به این شرح ترجمه کرد(به صورت کلی): Daily Pageviews per Visitor همان &#34;بازدید&#34; از فروشگاه و Daily Time on Site &#34;مدت زمان بازدید&#34; و Bounce Rate هم &#34;عکس العمل&#34; است که از همه بیشتر مورد توجه قرار می‌گیرد زیرا به نوعی اشاره دارد به طراحی وبسایت، Bounce Rate بالا مانند این است که مشتری‌ها وارد فروشگاه شما می‌شوند اما حتی به شما به عنوان صاحب فروشگاه سلام هم نمی‌کنند و بدون هیچ عکس العملی از فروشگاه شما خارج می‌شوند. در این شرایط شما به عنوان صاحب فروشگاه به فکر تغییر دکور، عوض کردن فروشندگان و ... می‌افتید.در این بخش بین فلربو و گیکتوری فاصله زیادی وجود نداره اما وضعیت گیکتوری با اینکه در حال افت هست اما او برنده است.#دیتاسنترdnslytics.com اسکرین شات از وبسایت قبلا من برای بدست آوردن نام شرکت و محلی که وبسایت‌ها بر روی آن میزبانی شده‌اند اول آدرس آی پی آنها را پیدا می‌کردم و بعد از طریق آن نام و محل دیتاسنتر را جستجو می‌کردم اما همیشه راه حل‌های بهتری هم وجود دارد :))هر دو وبسایت روی دیتاسنتر هتزنر آلمان میزبانی می‌شوند و از سرویس دی ان اس ابر آروان استفاده می‌کنند، من تجربه کمی دارم اما تو همین مدت زمان کم هم خاطره خوبی از دیتاسنتر آلمان ندارم و بعد از مشکلاتی که برای نزدیکه پیش آمد آن را بر روی دیتاسنتر آسیاتک قرار دادیم. هر دو وبسایت در این بخش مساوی هستند.#سرعتgtmetrix.com اسکرین شات از وبسایت یادش بخیر همین چند سال پیش بود که از باجه روزنامه فروشی کارت اینترنت می‌خریدیم و با سر و صدای مودم و اشغال شدن خط تلفن به اینترنت وصل می‌شدیم آن هم فقط با سرعت چند کیلوبیت اما حالا حتی می‌توانیم اینترنت نامحدود واقعی با سرعت بالا مثل زی‌تل داشته باشیم.صفحه اول وبسایت گیکتوری دارای حجم کمتری است و با سرعت بالاتری نسبت به فلربو برای کاربران ظاهر می‌شود.#اینستاگرامphlanx.com اسکرین شات از بزرگی شبکه‌های اجتماعی مانند توییتر و اینستاگرام را می‌توان به سادگی از تعداد نصب آنها در کافه بازار و سایر محل‌های فروش اپلیکیشن متوجه شد و این تعداد از کاربران در یک شبکه به معنی بالقوه بودن این محل‌ها برای تبلیغ کسب و کارها است که می‌تواند با روش‌های مختلفی بالفعل شود و درآمد بیش‌تر را برای آنها به ارمغان بیاورد.امروزه حتی فعالیت در شبکه‌های اجتماعی هم در نمره سئو و جایگاه وبسایت در نتایج جستجو تاثیرگذار است و برای سنجش آن می‌توان از سرویس‌های مختلفی استفاده کرد من از طریق phlanx حساب اینستاگرام فلربو و گیکتوری را بررسی کردم و بر اساس نرخ تعامل کاربران این دو صفحه وضعیت اینستاگرام فلربو بهتر از گیکتوری بود.#فروشگاه سازwappalyzer.com اسکرین شات از احتمالا در بخش #دیتاسنتر متوجه این موضوع شده‌اید که هر دو وبسایت با استفاده از فروشگاه ساز سازیتو ساخته شده‌اند و یا شاید حتی از روی مدل طراحی صفحات داخلی آنها نیز به این موضوع پی برده باشید، پیشنهاد می‌کنم برای آشنایی بیشتر با سازیتو این مطلب را بخوانید. به نظرم استفاده از سرویس‌های داخلی با وجود تمام کمی و کاستی‌های که دارند (شاید هم ندارند) مهم است زیرا استفاده تک تک ما از این سرویس‌ها است که موجب پیشرفت آنها و به سبب آن موفقیت خود ما می‌شود.#نتیجهمحتوای این صفحه پس از کسب اجازه از فلربو و گیکتوری عزیز منتشر شده است و صرفا یک بررسی و مقایسه کوتاه در مورد وبسایت‌های این دو فروشگاه استیکر بوده است که در آن فلربو با نتیجه 5به4 برنده شده و گیکتوری هم که با اختلاف یک امتیاز این مقایسه باخته است اما گیکتوری در مقابل از تنوع بیشتری در استیکرها و عدم ناموجود شدن محصول برخوردار است و فلربو هم که از قدیمی‌های این کار است، به نظر من در اینجا هر دو فروشگاه برنده هستند و نتیجه‌گیری اصلی را بر عهده کسانی می‌گذارم که از آنها خرید کرده‌اند اما به قول عزیزی: اگر در محله شما دوتا نانوایی خوب هست سعی کن از هر دو نان بخری تا در کسب رزق و روزی هر دوتای آنها شریک باشی.#به روز رسانی 1398/11 ?سلام من برگشتم تا این پست را با تجربه خریدی که از گیکتوری و فلربو بدست آوردم کامل کنم.پاکت‌هایی که به دستم رسید به همراه محتویات داخل آنهامن اول از فلربو خرید کردم و چون الان در فصل زمستان هستیم به همراه استیکرها یک بسته کوچک ارزن برای پرنده‌ها و یک پیام خیلی زیبا هم فرستاده بودن، خود پاکت اگر اشتباه نکنم از جنس کرافت بود که خیلی حس جالبی به همراه استیکر مهر و موم ایجاد می‌کرد.خود استیکرها رو از دو مدل براق و مات با روکش شنی انتخاب کرده بودم، که همینجا بهتون پیشنهاد میکنم بیشتر استیکرهای مات با روکش شنی را انتخاب کنید (در ادامه دلیل این پیشنهاد نشون میدم ?) و جنس نسبتا ضخیمی داشتن. هنگام چسباندن استیکرها حتما از قبل محل مربوطه تمیز کنید تا طول عمر چیدمان زیبایی که درست می‌کنید بیشتر باشه. راستی تمام اون لوگوهای کوچک فلربو که روی کارت استیکرها بود قابلیت جدا شدن داشت و میشود به جاهای مختلف چسباند.بعد از حدود چند هفته‌ای رفتم و  از گیکتوری خرید کردم و همین جور که در عکس بالا معلوم است علاوه بر قهوه‌ی دَمی نورسکای بن‌مانو که کد تخفیف خرید از سایت هم داشت یک کارت تخفیف مکتب خونه هم به همراه استیکرها ارسال کرده بودن. همه استیکرهای گیکتوری با روکش شنی هستند و کمی نسبت به فلربو نازک‌تر اند اما این به معنی قابل پاره شدن آنها نبود.در هر کارت استیکر یک متن زیبا هم وجود داشت و بر خلاف فلربو مدل جدا کردن استیکرها از کارت متفاوت و خیلی کاربردی بود.بیشتر توضیح میدم؛ داخل این صفحه از وبسایت فلربو امکان چیدمان استیکرها قبل از خرید وجود داره اما در هنگام چسباندن استیکرها قابلیت خاصی برای راحت‌تر چیدمان کردن آنها در نظر گرفته نشده در صورتی که در مدل کارت‌های استیکر گیکتوری یک لایه شفاف وجود دارد که استیکر بر روی آن قرار گرفته و بدون اینکه به قسمت چسبدار استیکر صدمه‌ای وارد شود میتوانید آنها را کاملا کنارهم روی سطح مورد نظرتان چیدمان کنید و سپس استیکرها را جدا کرده و بچسبانید.رنگ آبی؛ بودن یا نبودن! *دلیل پیشنهاد به روایت تصویردر چند خط بالا پیشنهاد کرده بودم به جای استیکرهای براق، استیکرهای مات با روکش شنی را انتخاب کنید که به دلیل وجود لایه محافظ در این مدل از استیکرها است. در تجربه خرید من (این تجربه صرفا متعلق به من است و آن را به کل تسری نمیدهم) رنگ آبی در فلربو از کیفیت مناسبی برخوردار نبود که در عکس بالا هم می‌بینید استیکر توییتر و ری‌اکت در اثر گذر زمان و تماس با پوشش کیف لپ تاپ رنگ خود را از دست داده‌اند. البته استیکر توییتری که رنگ پریده است را برای نمایش در عکس روی لایه شفاف کارت‌های گیکتوری قرار دادم و اینجا مشاهده می‌کنید که چقدر راحت میشه با وجود این لایه شفاف استیکرها را قبل از چسباندن چیدمان کرد.خریدن استیکر بهانه‌ای شد برای شروع نوشتن من در ویرگول و از این بابت خیلی خوشحال هستم که بعد از دوران بلاگفا،پرشین بلاگ و ... حالا می‌توانیم بر روی ویرگول مینیمال و دوست داشتی مطالب خودمان را منتشر کنیم. من در قسمت نظرات همیشه آماده دریافت نقد و پیشنهادات شما هستم و دعوت می‌کنم به قلبی که در قسمت پایین است رنگ اضافه کنید تا مانند ❤️ شما زیبا بشود.</description><category>محمدرضا.م</category><author>محمدرضا.م</author><pubDate>Tue, 03 Dec 2019 10:38:30 +0330</pubDate></item></channel></rss>