<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های آیین</title>
        <link>https://virgool.io/feed/@xenomorph</link>
        <description>یه برنامه‌نویس با انگیزه که بیشتر تو https://fa.aien.me میچرخه</description>
        <language>fa</language>
        <pubDate>2026-06-16 10:04:39</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/3181/avatar/Fd1Q0c.jpg?height=120&amp;width=120</url>
            <title>آیین</title>
            <link>https://virgool.io/@xenomorph</link>
        </image>

                    <item>
                <title>لینوکس یا ویندوز یا مک؟ مگه مهمه؟</title>
                <link>https://virgool.io/@xenomorph/%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%DB%8C%D8%A7-%D9%88%DB%8C%D9%86%D8%AF%D9%88%D8%B2-%DB%8C%D8%A7-%D9%85%DA%A9-%D9%85%DA%AF%D9%87-%D9%85%D9%87%D9%85%D9%87-xu7ongyhy0dv</link>
                <description>خب، امروز میخوام درباره یه بحث قدیمی بنویسم که انگار هنوز تموم نشده: &quot;لینوکس بهتره یا ویندوز یا مک؟&quot; ولی راستش، دنیا از این سوال عبور کرده و وقتشه ما هم عبور کنیم!ببینید، انتخاب سیستم‌عامل مثل انتخاب رنگ مورد علاقه‌ته، نه چیزی که بخوای سر اون با بقیه دعوا کنی! الان دیگه خیلی‌ها فهمیدن که این موضوع کاملاً سلیقه‌ایه و نمیشه نظر خودمون رو به زور به بقیه تحمیل کرد.ولی بذارید یه چیز خنده‌دار بگم... چرا بعضی از ماها فکر می‌کنیم انتخاب یه سیستم‌عامل خاص ما رو آدم بهتری می‌کنه؟! 😂 جدی، مگه با نصب لینوکس فرشته میشیم؟ یا با خرید مک، آی‌کیومون میره بالا؟اون حس &quot;خاص بودن&quot; رو می‌شناسی؟مخصوصاً بین ما آدم‌های فنی، عضو یه گروه &quot;خاص&quot; بودن، یه حس تعلق و شاید حتی &quot;برتری&quot; میده. آره، اعتراف کنیم... وقتی ترمینال باز می‌کنیم و کلی دستور عجیب غریب می‌زنیم، یه حس خفنی داریم، خصوصا وقتی چند نفر اطرافمون هستن و متوجه نمیشن ما دقیقا داریم چیکار میکنیم، ولی در واقع...ولی یادمون باشه که کار ما به عنوان متخصصین IT اینه که با هوشمندی، مردم رو به این دنیا نزدیک کنیم، نه اینکه بهشون حس &quot;ما برتریم و شما نمی‌فهمید&quot; رو بدیم!انعطاف‌پذیری کلید ماجراستمهم اینه که ما اونقدر منعطف باشیم که به مردم کمک کنیم &quot;بهترین انتخاب برای خودشون&quot; رو پیدا کنن، نه چیزی که &quot;ما رو خفن‌تر نشون بده&quot;. یعنی مثلا باید به این‌ها توجه کنیم:برای مطالعه‌ی ادامه مطلب به این آدرس رجوع کنید...</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Tue, 22 Apr 2025 11:48:09 +0330</pubDate>
            </item>
                    <item>
                <title>مشکل با «کدنویسی احساسی» یا همون Vibe Coding</title>
                <link>https://virgool.io/codenevis/%D9%85%D8%B4%DA%A9%D9%84-%D8%A8%D8%A7-%DA%A9%D8%AF%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%A7%D8%AD%D8%B3%D8%A7%D8%B3%DB%8C-%DB%8C%D8%A7-%D9%87%D9%85%D9%88%D9%86-vibe-coding-vhbl0j1t5oft</link>
                <description>چرا «کدنویسی احساسی» با توسعه محصول واقعی فرسنگ‌ها فاصله داره؟ تو دنیای امروز، همش از «کدنویسی احساسی» حرف میزنن ولی کسی نمیگه این با توسعه محصول فرق داره! من تو این پست شکاف عمیق بین اون اسکریپت ساده‌ای که رو لپ‌تاپ خودمون کار می‌کنه با محصولی که قراره بره دست مشتری رو نشون دادم.نمی‌دونی چرا برنامه‌نویسای باتجربه همیشه وقتی میگی &quot;این کار فقط دو روزه تمومه&quot; پوزخند می‌زنن؟ نمی‌فهمی چطور یه برنامه ساده اکسل بعد از تایمی خراب میشه و دیگه کار نمیکنه؟ این پست رو بخون تا بفهمی چرا کوپایلت و چت‌جی‌پی‌تی خوبن، ولی محصول سازی یه داستان کاملاً متفاوته:👈 https://fa.aien.me/issues-with-vibe-coding/</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Tue, 15 Apr 2025 10:27:30 +0330</pubDate>
            </item>
                    <item>
                <title>پس از انزوا: چالش‌های فرهنگی ایرانیان در بازگشت به جامعه جهانی</title>
                <link>https://virgool.io/@xenomorph/%D9%BE%D8%B3-%D8%A7%D8%B2-%D8%A7%D9%86%D8%B2%D9%88%D8%A7-%DA%86%D8%A7%D9%84%D8%B4-%D9%87%D8%A7%DB%8C-%D9%81%D8%B1%D9%87%D9%86%DA%AF%DB%8C-%D8%A7%DB%8C%D8%B1%D8%A7%D9%86%DB%8C%D8%A7%D9%86-%D8%AF%D8%B1-%D8%A8%D8%A7%D8%B2%DA%AF%D8%B4%D8%AA-%D8%A8%D9%87-%D8%AC%D8%A7%D9%85%D8%B9%D9%87-%D8%AC%D9%87%D8%A7%D9%86%DB%8C-epjurgjkq18f</link>
                <description>در این مقاله تحلیلی، به بررسی چالش‌های فرهنگی و اجتماعی می‌پردازم که ما ایرانیان پس از سال‌ها انزوا، در صورت بازگشت به جامعه جهانی با آن‌ها مواجه خواهیم شد.✅ آیا می‌دانستید فاصله ما با استانداردهای جهانی فقط به مسائل سیاسی و اقتصادی محدود نمی‌شود؟✅ چرا فردگرایی افراطی، ضعف در کار گروهی و اعتماد اجتماعی پایین می‌تواند مانعی جدی در مسیر موفقیت ما در عرصه بین‌المللی باشد؟✅ چه اصلاحاتی در نظام آموزشی و نگرش فرهنگی ما برای پیوستن موفق به جامعه جهانی ضروری است؟این مقاله تلاش می‌کند با نگاهی واقع‌بینانه اما امیدبخش، مسیری را ترسیم کند که می‌تواند ما را به جایگاهی شایسته در جهان امروز برساند.مقاله کامل را در وبلاگ من بخوانید...</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Thu, 20 Mar 2025 15:32:21 +0330</pubDate>
            </item>
                    <item>
                <title>خداحافظی با شبکه‌های اجتماعی</title>
                <link>https://virgool.io/@xenomorph/%D8%AE%D8%AF%D8%A7%D8%AD%D8%A7%D9%81%D8%B8%DB%8C-%D8%A8%D8%A7-%D8%B4%D8%A8%DA%A9%D9%87-%D9%87%D8%A7%DB%8C-%D8%A7%D8%AC%D8%AA%D9%85%D8%A7%D8%B9%DB%8C-x4c3qf5rsbdn</link>
                <description>راستش همیشه فکر می‌کردم مشکل از منه. پیش خودم می‌گفتم حتما اراده‌م ضعیفه، یا نمی‌تونم درست از وقتم استفاده کنم، یا شاید خیلی به فضای مجازی وابسته شدم. این شد که بارها و بارها سعی کردم از شبکه‌های اجتماعی فاصله بگیرم و هر دفعه با یه بهونه‌ای برگشتم. اما این‌بار قضیه فرق می‌کنه. بعد از کلی رفت و برگشت و تجربه‌های مختلف، به یه درک جدید رسیدم که می‌خوام باهاتون درمیون بذارم.از یه ترس مسخره تا یه فهم عمیق‌ترمیدونید چی باعث می‌شد هر دفعه برگردم؟ یه ترس مسخره: ترس از عقب موندن. همه‌ش نگران بودم نکنه یه اتفاق مهم بیفته و من نفهمم، یا دوستام به کمکم نیاز داشته باشن و من نباشم. حتی گاهی نگران می‌شدم نکنه یه خبر مهم رو از دست بدم یا از جریان زندگی دوستام و رویدادهای مختلف بی‌خبر بمونم.ولی هر بار که رفتم و برگشتم، یه چیز برام روشن‌تر شد: همه حالشون خوبه! آره، واقعا همینطوره، به همین اندازه عجیب، باورتون میشه؟ دنیا بدون اینکه من ۲۴ساعته آنلاین باشم هم می‌چرخه . دوستام و خانوادم بدون چک کردن‌های من هم نفس میکشن! اونا بدون اینکه من استوری‌هاشون رو ببینم هم زندگیشون رو می‌کنن. و جالب‌تر اینکه، اگه واقعا اتفاق مهمی بیفته، از یه راهی بهم خبر می‌رسه. انگار این ترس از دست دادن، بیشتر یه توهم بود تا واقعیت.یادش بخیر اون روزا...بعد برام یه سوال پیش اومد، جدا چرا؟ چرا اینقدر ترس؟ چرا قدیم اینطور نبود؟ چرا ۱۵ سال پیش همچین نگرانی‌هایی رو نداشتم؟این روزا که به گذشته فکر می‌کنم، دلم برای اینترنت قدیم تنگ میشه. یادتونه دوران یاهو چت و یاهو ۳۶۰ رو؟ بعدی نمیدونم که خیلی‌ها یادشون نیاد. وقتی با ذوق از مدرسه می‌دویدیم خونه که بریم تو اینترنت دنبال چیزای جدید بگردیم؟ اون موقع همه چی فرق می‌کرد. اینترنت واقعا مال ما بود.حالا چی شده؟ انگار شدیم مهمون یه خونه‌ی خیلی شیک که صاحبخونه‌ش چندتا شرکت بزرگن. میگن بیا تو، همه چی مجانیه، فقط یه شرط کوچولو داره: باید بذاری از همه کارات فیلم بگیریم، رفتارت رو کنترل کنیم، و هر وقت دلمون خواست بندازیمت بیرون. جالبه نه؟ انگار داریم تو یه سریال واقعیت‌نما (reality show) زندگی می‌کنیم، فقط با این تفاوت که خودمون داوطلبانه اومدیم توش!یه مشکل خیلی بزرگ‌ترولی میدونید چیه؟ قضیه فقط کنترل و نظارت نیست. یه مسئله‌ی خیلی عمیق‌تر این وسط هست: ما آدما اصلا آماده‌ی این حجم از ارتباط جهانی نبودیم! نه اینکه جنبه‌ش رو نداشته باشیم‌ها، نه. قضیه اینه که مغز ما، با این همه سال تکامل، یهو پرت شده وسط یه دنیای جدید که توش باید هر روز کلی اطلاعات رو پردازش کنه و با هزاران نفر در ارتباط باشه.این روزا به هر پستی که نگاه می‌کنی، یا کلیک‌بیته یا یه تلاش عجیب و غریب برای جلب توجه. انگار همه دارن داد می‌زنن &quot;منو ببین!&quot; و برای این دیده شدن حاضرن هر کاری بکنن. حتی بعضی‌ها راحت قوانین اخلاقی ساده رو زیر پا می‌ذارن، فقط برای اینکه چندتا لایک بیشتر بگیرن.یه مثال ساده میزنم. هممون با پدیده‌ی انحصارطلبی یا Monopolism آشنایی داریم. هممون پیامدهاش رو دیدم. اما فقط برای آشنایی بیشتر و اینکه با هم سر این مفهوم به تفاهم برسیم:انحصارطلبی (Monopolization): روندی که در آن یک شرکت یا سازمان بزرگ، با استفاده از قدرت اقتصادی و مقیاس عملیاتی خود، رقبای کوچکتر را از بازار خارج می‌کند و کنترل کامل یک بازار یا صنعت را در دست می‌گیرد.انحصار چندجانبه (Oligopoly): وضعیتی در بازار که در آن تعداد محدودی شرکت بزرگ (معمولاً بین ۲ تا ۵ شرکت) کنترل اکثریت بازار را در دست دارند. در این حالت، این شرکت‌ها به‌جای رقابت واقعی، معمولاً در یک تعادل استراتژیک با یکدیگر قرار می‌گیرند و عملاً بازار را بین خود تقسیم می‌کنند.دقیقا اتفاقی که تو اینترنت امروز میوفته، همین بحث انحصاره. اینترنت امروز عملا در اختیار ۵ شرکت بزرگ دنیاست: متا، مایکروسافت، گوگل، اپل و آمازون.اما این انحصار رو چطور میشه بهتر تجسم کرد؟ ۲۰ سال پیش و تو اوایل شهرت اینترنت، فضای اینترنت مثل یه شهر نسبتا بزرگ بود که توض پر از مغازه‌های کوچیک، کتاب‌خونه‌ها و کافه‌ها بود. این فضا‌ها اغلب توسط اشخاص اداره میشدن و شما به انتخاب خودتون یه جا، یا چندجا رو مثل یه پاتوق انتخاب میکردید و وقت آزدتون رو اونجا میگذروندید.این فضا گاها وب‌سایت‌های شخصی آدمها بود که خودشون مطالبشون رو مینوشتن و اونطور که دوست داشتن منتشر میکردن، یا بعضا شبکه‌های اجتماعی یکطرفه‌ی کوچیک مثل یاهو ۳۶۰، ای‌او‌ال و غیره بود. هر چند توی این فضا مشکلاتی وجود داشت، مثل تفاوت‌های فردی، تا تفاوت‌های ملیتی، اما در نهایت همه‌چیز به شخص خلاصه میشد. چیزی به اسم «وایرال» وجود نداشت و رقابت، معنای درست خودش رو داشت: آدمها واقعا تلاش میکردن تا دانش صحیح خودشون رو نشون بدن، واقعا برای تولید محتوا زمان میذاشتن و مطالبی مفید تولید میکردن!(همین الان که دارم این مطلب رو مینویسم، یاد وب‌سایت میررضا قادری افتادم که مدتهاست بروز نمیشه. یادمه یه زمانی حس خوب اینکه چند ساعت برای نوشتن یه مطلب وقت گذاشته بودیم تا کیفیت بالایی بشه، انگیزه‌ی نوشتنمون بود).تا اینکه یکروز اولین هایپر مارکت وسط شهر زده شد. یه هایپرمارکت به اسم فیسبوک. کم‌کم (ولی به سرعت زیاد) اتفاقات توی این شهر عوض شد و آدم‌ها یکجا جمع شدن. دیگه تقریبا کسی تو پاتوق‌ها نمیگشت و همه‌چیز، روی «روابط» متمرکز شد.از اون روز تا به اینجا، سیر تغییرات کم و بیش مشخصه. خیلی از افرادی که جتی نمیدونستن اینترنت چیه، به لطف شبکه‌های اجتماعی وارد اون شدن، اما بدون اینکه بدونن، چه چیز مزخرفی پشتش قایم شده و چه سیاست‌هایی، اونها رو از دنیایی که بیرون اون هایپر مارکت هست، بیخبر نگه داشتن.برای اونایی که هنوز درگیرن...اگه شما هم مثل خیلی‌ها هنوز درگیر این فضا هستید و نمی‌تونید ازش دل بکنید، می‌خوام یه چیزی بهتون بگم: این فقط شما نیستید! قضیه خیلی فراتر از داشتن یا نداشتن اراده‌ست.ببینید، شبکه‌های اجتماعی امروزی یه جوری طراحی شدن که مستقیم با مغز ما کار می‌کنن. اونا می‌دونن کدوم دکمه‌ها رو فشار بدن و چه عکس‌هایی، ویدئو‌هایی یا پست‌های وایرالی رو نشونمون بدن که ما نتونیم ازشون دل بکنیم. واسه همینه که خروج از این فضا به چیزی خیلی بیشتر از اراده نیاز داره. باید خودمون رو، نیازهامون رو، و البته ترس‌هامون رو عمیق‌تر بشناسیم.برای من، ترک شبکه‌های اجتماعی یکی از بهترین تصمیم‌هایی بود که تا حالا گرفتم. حس می‌کردم گم شدم. گوشیم تمام زندگیم را کنترل می‌کرد، هیچ سرگرمی نداشتم و حتی تو بهترین اوضاع هم استرس و اضطراب داشتم. شروع کردم به دنبال جواب‌هایی گشتن و فهمیدم که رابطم با شبکه‌های اجتماعی و در کل اینترنت خیلی ناسالم شده.وقتی از پلتفرم‌های مختلف که هر شب منو تو خودش می‌کشیدند بیرون اومدم (مهمترینش اینستاگرام، من هیچوقت تو تیک‌توک نبودم)، تونستم بهتر روی تحصیلات و کارم تمرکز کنم و سلامت روانم به طور قابل توجهی بهتر شد. همچنین وقت بیشتری برای گذروندن با خانواده و دوستام داشتم و حس آزادی از فشار مداوم برای نشون دادن تصویر کاملی از خود آنلاینم پیدا کردم. تمام اینها در نهایت به سه دلیل مهم برای خروج از شبکه‌های اجتماعی ختم شد:حواس‌پرتی مداومهر بار که نوتیفیکیشنی می‌رسه، مغز ما طوری تربیت شده که بهش واکنش نشون بده، که این میشه یه چرخه بی‌پایان از چک کردن شبکه‌های اجتماعی و از دست دادن تمرکز روی کارهایی که باید انجام بدیم اتفاق میوفته. این حواس‌پرتی مداوم می‌تونه تمرکز روی کارهای مهم رو سخت کنه و در نهایت باعث کاهش بهره‌وری‌مون بشه.اثرهای منفی روی سلامت روانواضحه و بارها هم گفته شده که تحقیقات نشون دادن که استفاده زیاد از شبکه‌های اجتماعی می‌تونه احساس اضطراب، افسردگی و تنهایی رو بیشتر کنه. همچنین، شبکه‌های اجتماعی می‌تونن حس واقعی بودن رو هم خراب کنن، چون مردم معمولاً فقط نکات مثبت زندگیشون رو منتشر می‌کنن و این باعث میشه احساس ناتوانی و انتظارات غیرواقعی پیدا کنن.رفرنس‌های علمی: D. Ostic et al., “Effects of Social Media Use on Psychological Well-Being: A Mediated model,” Frontiers in Psychology, vol. 12, Jun. 2021, doi: 10.3389/fpsyg.2021.678766.B. Keles, N. McCrae, and A. Grealish, “A systematic review: the influence of social media on depression, anxiety and psychological distress in adolescents,” International Journal of Adolescence and Youth, vol. 25, no. 1, pp. 79–93, Mar. 2019, doi: 10.1080/02673843.2019.1590851.Google Scholar Searchاز دست دادن حریم خصوصی:پلتفرم‌های شبکه‌های اجتماعی کلی اطلاعات شخصی جمع‌آوری و استفاده می‌کنن که می‌تونه برای تبلیغات هدفمند یا حتی به شرکت‌های سوم فروخته بشه. ترک شبکه‌های اجتماعی می‌تونه کمک کنه تا دوباره کنترل اطلاعات شخصی رو به دست بیاریم.یه امید بزرگولی یه خبر خوب دارم براتون: اینترنت خوب هنوز زنده‌ست! فقط باید از این چندتا اپ محبوب بیایم بیرون و یکم بیشتر بگردیم. دنیای دیجیتال خیلی بزرگ‌تر از اینستاگرام و توییتر (X) و فیسبوک و تیت‌توک و غیرست.برای کسایی که می‌خوان این راه رو برن، یه پیشنهاد دارم: اول از خودتون بپرسید &quot;من واقعا چرا از شبکه‌های اجتماعی استفاده می‌کنم؟&quot; بعد، و این مهم‌تره، از خودتون بپرسید &quot;تو زندگی واقعیم چه چیزی می‌تونه جای اینا رو برام پر کنه؟&quot;تصمیم من برای خروج از شبکه‌های اجتماعی یه تصمیم یهویی نبود. یه سفر طولانی بود که از یه ترس ساده شروع شد و رسید به یه درک عمیق‌تر از رابطه‌مون با این دنیای دیجیتال.یه سری مزایا هم دیدم توی این خروج:تمرکز و بهره‌وری بیشتربدون حواس‌پرتی مداوم نوتیفیکیشن‌ها و فیدها، می‌تونستم بهتر روی کارهای مهم تمرکز کنم و بهره‌وری‌م رو بالا ببرم.سلامتی روانی بهترترک شبکه‌های اجتماعی می‌تونه منجر به کاهش احساس اضطراب، افسردگی و تنهایی بشه و همچنین تصویر بدنی و اعتماد به نفس بهتری رو به ارمغان بیاره.روابط بهتربدون فشار دائمی برای نمایش یک تصویر عالی در فضای مجازی، می‌تونم بیشتر روی ساختن ارتباطای واقعی با آدمای دور و بر خودم تمرکز کنم.چطور شبکه‌های اجتماعی رو کنار بذاریم؟شروع کن به ارزیابی استفاده فعلیت از شبکه‌های اجتماعی. مثلا برای خودت بنویس که چقدر وقت صرف هر پلتفرم می‌کنی و ازشون چه استفاده‌ای می‌کنی. مشخص کن کدوم پلتفرم‌ها بیشتر حواست رو پرت می‌کنن یا انرژی منفی می‌دن و اونا رو برای ترک تو اولویت بذار.بعد یک هدف تعیین کن، مثلا یه تاریخ رو مشخص کن که می‌خوای از شبکه‌های اجتماعی کناره‌گیری کنی و یه برنامه برای رسیدن به این هدف بچین.بعدش یک دوره پاکسازی دیجیتالی انجام بده. تو این مرحله موثرترین راه برای ارزیابی دوباره استفاده‌ات از شبکه‌های اجتماعی، اینه که کاملاً از تکنولوژی‌های غیرضروری فاصله بگیری و به ذهنت استراحت بدی. بعد از این دوره، می‌تونی برگردی و با دیدی روشن‌تر بسنجی که آیا این تکنولوژی برات بیشتر سود داره یا ضرر، و تصمیم بگیری چطور/آیا دوباره اون رو به زندگیت راه بدی.ولی از همه‌ی اینا مهمتر اینه که قدم‌های کوچیک برداری. اگه به‌ فکر ترک یکباره شبکه‌های اجتماعی حس خوبی نداری، یا فکر میکنی نمیتونی یهو کنارشون بذاری، سعی کن به تدریج استفاده‌ت رو کم کنی. شروع کن به محدود کردن زمانی که هر روز برای شبکه اجتماعی می‌ذاری و به تدریج کمش کن تا به هدفی که داری برسی.و در نهایت فعالیت‌های جایگزین پیدا کن! به جای اینکه بی‌هدف تو اکسپلور‌ها بچرخی، به دنبال فعالیت‌های دیگه‌ای باش که برات شادی و رضایت به ایجاد کنن و در واقع مغزت رو تشویق کنن. این می‌تونه هر چیزی مثل کتاب خوندن، پیاده‌روی یا گذروندن وقت با دوستان و خانوادت باشه. هرچند که کار سختیه، چون باید با حجم زیادی از دوپامین که شبکه‌های اجتماعی تزریق میکنن مقابله کنی!واقعیت اینه که ترک شبکه‌های اجتماعی کار آسونی نیست و ممکنه زمان و تلاش بخواد تا به تغییراتش عادت کنی. اما با قدم‌های کوچیک و پیدا کردن فعالیت‌های جایگزین، می‌تونی کنترل زندگیت رو دوباره به‌دست بیاری و تغییرات مثبتی تو زندگیت ایجاد کنی.به یاد و احترام اون روزای خوب اینترنت، روزایی که آزادی و کشف کردن معنی واقعی داشت، تصمیم گرفتم از این فضای بسته و تکراری بیام بیرون. شاید این یه قدم کوچیک باشه، ولی می‌دونید چیه؟ همه‌ی تغییرای بزرگ با قدم‌های کوچیک شروع میشن.از این به بعد تلاشم اینه که توی وبسایت خودم فعالیت داشته باشم و در نهایت دنبال اجتماعات کوچکتر برای پیوست بگردم.با آرزوی موفقیت</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Sat, 25 Jan 2025 14:56:24 +0330</pubDate>
            </item>
                    <item>
                <title>چرا نباید از شماره تلفن برای احراز هویت استفاده کنیم؟</title>
                <link>https://virgool.io/@xenomorph/%DA%86%D8%B1%D8%A7-%D9%86%D8%A8%D8%A7%DB%8C%D8%AF-%D8%A7%D8%B2-%D8%B4%D9%85%D8%A7%D8%B1%D9%87-%D8%AA%D9%84%D9%81%D9%86-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%A7%D8%AD%D8%B1%D8%A7%D8%B2-%D9%87%D9%88%DB%8C%D8%AA-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%DA%A9%D9%86%DB%8C%D9%85-puwcswi9tcxw</link>
                <description>درود به همه‌ی خوانندگان عزیز. من بعد از مدتها دوباره دست به قلم شدم (البته دست به کیبورد). اما این دفعه در مورد یک نکته‌ی مهم میخوام بنویسم، که چندین بار از حتی دوستان نزدیکم دیدم که به اشتباه راه‌اندازی میشه: احراز هویت یا لاگین با شماره موبایل! می‌دونم که همه‌مون دنبال ساده‌ترین راه برای پیاده‌سازی سیستم لاگین هستیم و شاید الان با خودتون بگید &quot;خب چه ایرادی داره از شماره موبایل استفاده کنیم؟ همه دارن همین کار رو می‌کنن!&quot;اتفاقاً همین که همه دارن این کار رو می‌کنن، باعث شده که این موضوع به یه مشکل امنیتی تبدیل بشه. بذارید از اول براتون توضیح بدم.مشکل از کجا شروع میشه؟وقتی یه استارتاپ جدید راه می‌اندازیم، یه اپ جدید میخوایم بنویسیم که نیاز به ورود کاربر داره، همیشه دنبال ساده‌ترین راه‌ها هستیم. یه فرم ساده با شماره موبایل، یه کد تایید پیامکی، و تمام! کاربر ثبت‌نام می‌کنه و وارد اپلیکیشن میشه. به نظر عالی میاد، نه؟ تازه پیاده‌سازیش هم آسونه! اما این سادگی یه قیمت سنگین داره که شاید ازش خبر نداشته باشید. متاسفانه این روش هم به شدت توی ایران، که از لحاظ زیرساخت فنی تو بدترین حالت ممکنه، محبوبیت زیادی داره.چرا SMS امن نیست؟اول از همه بیاید یه نگاهی به تکنولوژی SMS بندازیم. می‌دونستید که پروتکل SMS مربوط به اوایل دهه ۹۰ میلادیه؟ یعنی داریم از یه فناوری که برای دوران نوکیا ۳۳۱۰ طراحی شده، برای امنیت اپلیکیشن‌های ۲۰۲۴ استفاده می‌کنیم!سیستم رمزنگاری شبکه‌ی 3G از الگوریتم‌های A5/1 و A5/3 استفاده می‌کنه که دیگه امن نیستن. هرچند این موضوع توی 4G و 5G خیلی بهتر شده، اما همچنان هکرها می‌تونن با تجهیزات نسبتاً ارزون‌قیمت، پیام‌های SMS رو رهگیری کنن. تصور کنید کد تایید حساب بانکی کاربرتون به جای اینکه به دست خودش برسه، مستقیم میره تو گوشی یه هکر!مشکل SIM Swapping چیه؟حالا بیاید به یه مشکل جدی‌تر نگاه کنیم: SIM Swapping یا همون جابجایی سیم‌کارت. این حمله اونقدر ساده‌ست که باورتون نمیشه. هکر کافیه چند تا اطلاعات ساده درباره کاربر شما پیدا کنه (که معمولاً از طریق شبکه‌های اجتماعی به راحتی قابل دسترسه)، بعد با یه تماس با اپراتور و یکم مهندسی اجتماعی، خودش رو جای کاربر جا بزنه.اپراتورها هم سیستم‌هایی دارن که باید سریع بتونن شماره‌ها رو از یه سیم‌کارت به سیم‌کارت دیگه منتقل کنن (مثلاً برای وقتی که گوشی کسی گم میشه). همین سیستم‌ها باعث میشه که انتقال شماره به سیم‌کارت هکر خیلی سریع انجام بشه.بازیافت شماره‌ها: یه مشکل پنهانیه مسئله دیگه که کمتر بهش توجه میشه، بازیافت شماره‌های موبایله. وقتی یه شماره موبایل مدتی غیرفعال می‌مونه (گاهی فقط ۹۰ روز!)، اپراتور اون رو به یه کاربر جدید واگذار می‌کنه. حالا فکر کنید کاربر قدیمی شما کلی سرویس و اپلیکیشن داشته که با اون شماره ثبت‌نام کرده. همه این حساب‌ها میفته دست کاربر جدید!محدودیت کاربرهااین هم خب واضحه که وقتی شماره موبال رو به عنوان سیستم احراز هویت اصلی میذارید، در واقع دارید در رو روی کاربرهای بین‌المللی میبنید. مثلا وقتی یکی بخواد از یه کشور دیگه وارد سیستم شما بشه و از خدماتتون استفاده کنه، به بن‌بست میخوره! حداقل با ایمیل اون یه‌ذره ارتباط با دنیای بیرون رو حفظ میکنید!داستان‌های واقعیاجازه بدید چند تا مثال واقعی براتون بزنم. سال ۲۰۱۹، یه هکر تونست از طریق SIM Swapping به حساب توییتر جک دورسی (مدیرعامل سابق توییتر) دسترسی پیدا کنه [منبع]. یا همین چند وقت پیش، یه گروه هکری تونستن با همین روش به حساب‌های کریپتوی چند نفر دسترسی پیدا کنن و میلیون‌ها دلار سرقت کنن [منبع].یه مورد دیگه که خیلی جالبه، داستان یه خانمی بود که شماره موبایلش رو از دست داده بود و وقتی دوباره فعالش کرد، متوجه شد تو این مدت یه نفر دیگه با همون شماره به کلی سرویس دسترسی داشته [منبع]!راه‌حل چیه؟خب حالا که این همه مشکل رو گفتیم، بیاید ببینیم چه راه‌حل‌هایی داریم:اول از همه، می‌تونید از سیستم ایمیل و رمز عبور استفاده کنید. درسته که قدیمی به نظر میاد، ولی هنوز هم یکی از امن‌ترین روش‌هاست. برای امنیت بیشتر، می‌تونید احراز هویت دو مرحله‌ای رو با اپلیکیشن‌هایی مثل Google Authenticator یا Authy پیاده‌سازی کنید.یه راه‌حل مدرن‌تر، استفاده از WebAuthn و FIDO2 هست. این پروتکل‌ها به کاربر اجازه میدن با اثر انگشت یا تشخیص چهره لاگین کنن. شرکت‌های بزرگی مثل گوگل و مایکروسافت دارن به این سمت میرن.اگه حتماً می‌خواید از شماره موبایل استفاده کنید، حداقل اون رو تنها روش احراز هویت نذارید. می‌تونید از ترکیب چند روش استفاده کنید.نکات فنی پیاده‌سازیبرای دوستانی که می‌خوان سیستم لاگین امن پیاده‌سازی کنن، چند تا نکته مهم:رمزهای عبور رو حتماً با الگوریتم‌های قوی مثل bcrypt یا Argon2 هش کنید. از ذخیره‌سازی مستقیم رمز تو دیتابیس جداً خودداری کنید.برای توکن‌های احراز هویت، از JWT با کلیدهای رمزنگاری قوی استفاده کنید و حتماً زمان انقضا براشون بذارید.اگه از OAuth استفاده می‌کنید، حواستون به امنیت redirect URL‌ها باشه. این یکی از نقاط آسیب‌پذیر معمول تو سیستم‌های لاگینه.برای جلوگیری از حملات Brute Force، حتماً سیستم محدودسازی تعداد تلاش (Rate Limiting) پیاده‌سازی کنید.فکر کردن به آیندهدنیای تکنولوژی با سرعت در حال تغییره. همین الان هم شرکت‌های بزرگ دارن به سمت روش‌های جدید احراز هویت مثل Passwordless Authentication میرن. شاید الان استفاده از شماره موبایل ساده‌تر به نظر برسه، ولی در درازمدت می‌تونه مشکلات زیادی ایجاد کنه.حواسمون باید به این باشه که ما به عنوان توسعه‌دهنده، مسئول امنیت داده‌های کاربرهامون هستیم. شاید پیاده‌سازی یه سیستم امن کمی زمان‌بر باشه، ولی ارزشش رو داره.نظر شما چیه؟ تجربه‌ای با این مشکلات داشتید؟ چه راه‌حل‌های دیگه‌ای به ذهنتون می‌رسه؟ خوشحال میشم نظراتتون رو تو کامنت‌ها بخونم.اگه این مطلب براتون مفید بود، حتماً با بقیه توسعه‌دهنده‌ها به اشتراک بذاریدش. هر چقدر آگاهی درباره این موضوع بیشتر بشه، می‌تونیم اپلیکیشن‌های امن‌تری بسازیم.یادتون باشه: امنیت یه مسابقه نیست که بخوایم توش اول بشیم، یه مسئولیته که باید جدی بگیریمش.</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Mon, 16 Dec 2024 21:03:59 +0330</pubDate>
            </item>
                    <item>
                <title>هنوز جای امید هست!</title>
                <link>https://virgool.io/@xenomorph/%D9%87%D9%86%D9%88%D8%B2-%D8%AC%D8%A7%DB%8C-%D8%A7%D9%85%DB%8C%D8%AF-%D9%87%D8%B3%D8%AA-t3lve6sokj5a</link>
                <description>عکس از Lina Trochezوقتی که اخبار رو نگاه میکنیم و به مشکلات زیادی که دنیای امروز ما باهاش سر و کله میزنه فکر میکنیم، نتایجی که میگیریم شاید اونقدرها هم که میخوایم، مثبت یا به نوعی Optimistic نیستن.ولی اگر تلاش کنیم کمی منطقی‌تر و آگاهانه‌تر موضوعات رو بررسی کنیم، به پیشرفت‌هایی که کردیم دقت کنیم، اینکه چقدر مسئولیت‌پذیرتر شدیم و داریم میشیم، اینکه چقدر مشتاقانه‌تر سعی میکنیم شرایط انسان‌ها و انسانیت رو بهبود بدیم، نتایجمون خیلی متفاوت‌تر میشن!آره درسته، مشکلات خیلی سختی وجود دارن، که نیاز به راه‌حل‌های سریعی دارن، هنوز مشکلاتی وجود دارن که ما براشون راه‌حلی نداریم: جرم و جنایت، فقر، نفرت، نابرابری و راستش خستگی، همه‌جا...ولی هنوز نکات مثبتی هستند  و هنوز میشه مثبت‌اندیش بود. آدمهایی هستن که با از خود گذشتگی به کسانی که نیاز دارن، کمک میکنن. شرکت‌هایی هستن که تلاش خستگی ناپذیری میکنن تا مثلا میزان دی‌اکسید‌کربن توی هوا رو کاهش بدن و هوا رو پاک‌تر کنن، یا شرکت‌هایی که دارن تلاش میکنن شرایط رو برای کارمندهاشون هموار و راحتتر کنن. افراد دیگه‌ای، همچنان خستگی‌ناپذیر در تلاشن، تا سطح انسانیت رو بالاتر ببرن...و این آدمها، نوابغ نیستن، میلیاردها و دانشمندای شناخته‌شده نیستن. اینها افرادی دقیقا مثل شما هستن، اینها، شما هستین! آدمهایی که اهمیت میدن، ارزش میذارن و هرروز تلاش میکنن کاری بهتر از دیروز انجام بدن، آدمهایی که سهم بیشتری میذارن برای بهبودی، تا دنیا واقعا به جای بهتری تبدیل بشه...خواستم با این نوشته از شما تشکر کنم، ادامه بدین، همچنان اهمیت بدین. بعضی وقت‌ها سخت و غیر ممکن بنظر میرسه، اما یادتون نره که «در نومیدی بسی امید است. پایان شب سیه سپید است»، و ما بدون شما به اون سپیدی نمیرسیم.مرسی از شما. مرسی از اینکه هنوز اهمیت میدین...</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Wed, 03 Mar 2021 19:16:55 +0330</pubDate>
            </item>
                    <item>
                <title>گراف‌کیو‌ال چیست؟</title>
                <link>https://virgool.io/@xenomorph/%DA%AF%D8%B1%D8%A7%D9%81-%DA%A9%DB%8C%D9%88-%D8%A7%D9%84-%DA%86%DB%8C%D8%B3%D8%AA-jq2asjduajqi</link>
                <description>برام مواردی پیش اومدن که لازم بوده برای کسی در مورد گراف‌کیو‌ال یا GraphQL توضیح بدم. اینکه چرا خوبه و کجاها میتونه خیلی کمک کنه.من اینجا اول در مورد خود گراف‌کیو‌ال توضیح میدم، و تو قدم بعدی نحوه‌ی پیاده سازی یک سرور گراف‌کیو‌ال رو.گراف کیو اِل چی هست؟خیلی خلاصه «یه زبان کوئری گرفتن برای ای‌پی‌آی». ولی این توضیح هم خیلی کوتاهه هم اطلاعات کافی نمیده، مگه اینه اول بدونیم کامل خود گراف‌کیو‌ال چی هست.گراف‌کیو‌ال یه زبانه برای ای‌پی‌آی که با دادن یک توضیح کامل از دیتایی که مد نظرتون هست، اونچه که خواستید رو در اختیارتون میذاره. در واقع به کلاینت کمک میکنه تا دقیقا بگه که چه چیزی رو میخواد و دقیقا همونچیز رو برمیگردونه.یک مثالفرض کنیم که یه ای‌پی‌آی مبتنی بر REST داریم. همچین چیزی:GET /productsبرای یادآوری، این سبک نوشتن یعنی شما یک درخواست GET رو مثلا به یه آدرسی مثل http://localhost:3000/products میفرستید.درخواست رو براش میفرستیم و همچین جوابی میگیریم:[
  {
    &amp;quotid&amp;quot: 1234,
    &amp;quotname&amp;quot: &amp;quotAspire M5&amp;quot,
    &amp;quotbrand&amp;quot: &amp;quotAcer&amp;quot,
    &amp;quotcategory&amp;quot: &amp;quotLaptop and Computers&amp;quot,
    &amp;quotfeatures&amp;quot: {
      &amp;quotweight&amp;quot: 1.23,
      &amp;quotdimensions&amp;quot: {
        &amp;quotheight&amp;quot: 23.4,
        &amp;quotwidth&amp;quot: 18.5,
        &amp;quotlength&amp;quot: 18.3
      }
    },
    &amp;quotspecs&amp;quot: {
      &amp;quotram&amp;quot: 16,
      &amp;quotcpu&amp;quot: 3.5,
      &amp;quotcpu_count&amp;quot: 8,
      &amp;quotthread_count&amp;quot: 8
    },
    &amp;quotprice&amp;quot: 699.99
  },
  {...}
]خب اینا اطلاعات یه سری لپتاپ هستن (مثلا) و ما میخوایم اینارو تو صفحه محصولاتمون نشون بدیم. اما ایده اینه که تو صفحه‌ی اصلی، تمام اطلاعات لپتاپ‌ها رو نذاریم، بلکه فقط مواردی که مورد نیاز ما هستن رو نشون میدیم. مثلا اسم لپتاپ و قیمتش. بعد که یوزر روی محصول کلیک کرد، مابقی اطلاعات رو نشون بدیم.اینجا به دوتا نکته توجه کنید:ما تمام اطلاعاتی که تو پاسخ به ما داده شده رو نیاز نداریم، فقط یک بخشیش مورد نیاز ماست وما برای صفحه اختصاصی محصول، باید یک درخواست دیگه به مثلا GET /products/1234بفرستیم تا اطلاعات محصول رو مجدد دریافت کنیم.اینجا یکی از جاهاییه که گراف‌کیو‌ال به کمک ما میاد!مقدمهفقط چیزهایی که لازم هست رو درخواست میدیمگراف‌کیو‌ال یک زبان کوئریه. یعنی باید بهش بگید دقیقا چی میخواید تا اونهم دقیقا همون رو بهتون بده. اما چطور این کار رو انجام بدیم؟ این دقیقا همون ویژگی اصلی گراف‌کیو‌ال هست، یعنی شما انتخاب میکنی که چه فیلدهایی باید برای شما ارسال بشن. فکر کنم یه مثال بتونه خوب نشون بده که چطور میشه. تجسم کنید که ما توی گراف‌کیو‌ال میتونیم چنین چیزی رو برای سرورمون بفرستیم:query {
  products {
    id
    name
    price
  }
}و در جوابش سرور گراف‌کیو‌ال به ما این رو میده:[
  {
    &amp;quotid&amp;quot: 1234,
    &amp;quotname&amp;quot: &amp;quotAspire M5&amp;quot,
    &amp;quotprice&amp;quot: 699.99
  },
  {
    ...
  }
]به همین سادگی! اما سوال اینه که چطور میشه اطلاعات فقط یک لپتاپ رو بدست آورد؟اینم خیلی سادست!query {
  product(id: &amp;quot1234&amp;quot) {
    id
    name
    brand
    category
    price
    features {
      weight
      dimensions {
        width
        height
        length
      }
    }
    specs {
      ram
      cpu
      cpu_count
      thread_count
    }
  }
}و جوابش:{
  &amp;quotid&amp;quot: 1234,
  &amp;quotname&amp;quot: &amp;quotAspire M5&amp;quot,
  &amp;quotbrand&amp;quot: &amp;quotAcer&amp;quot,
  &amp;quotcategory&amp;quot: &amp;quotLaptop and Computers&amp;quot,
  &amp;quotprice&amp;quot: 699.99,
  &amp;quotfeatures&amp;quot: {
    &amp;quotweight&amp;quot: 1.23,
    &amp;quotdimensions&amp;quot: {
      &amp;quotwidth&amp;quot: 18.5,
      &amp;quotheight&amp;quot: 23.4,
      &amp;quotlength&amp;quot: 18.3
    }
  },
  &amp;quotspecs&amp;quot: {
    &amp;quotram&amp;quot: 16,
    &amp;quotcpu&amp;quot: 3.5,
    &amp;quotcpu_count&amp;quot: 8,
    &amp;quotthread_count&amp;quot: 8
  }
}اما یک نکته دیگه راجع به گراف‌کیو‌ال موند.فقط یه یک آدرس درخواست میدیم!این قسمت خوب قضیست. توی گراف‌کیو‌ال، دقیقا بر عکس ای‌پی‌آی‌های REST، ما فقط یک Endpoint داریم که بهش درخواست میدیم. همینطور همه‌ی این درخواست‌ها رو فقط با یک Verb میفرستیم! یعنی دیگه خبری از Get برای گرفتن اطلاعات، Post برای ساختشون و مابقی برای بقیه‌ی کارها نیست!توی گراف‌کیو‌ال همه‌ی درخواست‌ها به همچین آدرسی ارسال میشن:POST /graphqlو نوع درخواست ما، یا همون Content-Typeکه توی Header میذاریم، به جای application/json، application/graphql میشه.در نتیجه سرور متوجه میشه که با یک درخواست گراف‌کیو‌ال طرفه.آشنایی با گراف‌کیو‌الگراف‌کیو‌ال، یک زبان مخصوص برای تعریف شکل داده‌هاست که سمت سرور اجرا میشه و خروجی لازم رو تحویل میده. چیزی که مهمه اینه که گراف‌کیو‌ال برای خودش یک Type System داره که باید در موردش حتما بدونیم.یک سرور گراف‌کیو‌ال، اصولا با ساختن تایپ‌ها یا types شروع میشه که توی هر تایپ، فیلدهای خاصی وجود داره. در نهایت به هر فیلد، یک فانکشن تخصیص داده میشه که این اتفاق سمت موتور میوفته، ما فقط فانکشن‌ها رو تعریف میکنیم و بهشون لاجیک میدیم.برای مثلا، یک سرور گراف‌کیو‌ال که که بهمون اطلاعات یک پست وبلاگ رو میده، حتما این دو تایپ رو داره:type Query {
  post: PostType
}

type PostType {
  title: String
  comments_count: Int
}که شما در نهایت با فرستادن یک درخواست مثل{
  post {
    comments_count
  }
}میتونید یک جواب شبیه به{
  &amp;quotpost&amp;quot: {
    &amp;quotcomments_count&amp;quot: 43
  }
}رو دریافت کنید...ادامه‌ی مطلب و آموزش‌های کاملتر رو تو وبسایت خودم میتونید داشته باشید.</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Sat, 06 Feb 2021 14:01:49 +0330</pubDate>
            </item>
                    <item>
                <title>بهترین فریم‌ورک برای برنامه‌نویسی؟</title>
                <link>https://virgool.io/coderlife/%D8%A8%D9%87%D8%AA%D8%B1%DB%8C%D9%86-%D9%81%D8%B1%DB%8C%D9%85-%D9%88%D8%B1%DA%A9-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-r5l7gs0ql152</link>
                <description>خیلی طولانیه، نمیخونم:هرچیزی که باهاش راحت‌تر هستید، شما رو زودتر به پولتون میرسونه و مشتریتون رو هم راضی نگه میداره میشه بهترین فریم‌ورک برای شما!بریم تو جزئیات:برنامه‌نویسی، یک حرفه هست. یه فرق بین یک مهندس نرم‌افزار و برنامه‌نویس وجود داره. یک برنامه‌نویس الزاما دانش مهندسی نداره، و یک مهندس نرم‌افزار الزاما دانش برنامه‌نویسی. از اینجاست که وقتی کسی ازمون بپرسه که «من میتونم برنامه‌نویس بشم؟» با وجود اینکه مثلا رشته‌ی تحصیلیش آبیاری گیاهان دریایی بوده (صرفا منظورم بی‌ربط بودن رشتست)، ما بهش میگیم «آره که میتونی، فقط کافیه یه درک از ریاضی (که اینجا منظورمون احتمالا الگوریتم حل مسئلست) داشته باشی...».اما اگه یکی بیاد و از ما بپرسه که «من میتونم مهندس نرم‌افزار بشم؟» اونجاست که یکم صبر میکنیم، فکر میکنیم و شرایط رو میسنجیم تا جوابی صرفا از روی باد هوا ندیم.راستش هدفم این نیست که راجع به مهندسی نرم‌افزار توضیح بدم. اما فکر میکنم برای چیزی که میخوام بگم، لازمه درموردش کمی حرف بزنم و تفاوت‌هاش با حرفه‌ی برنامه‌نویسی رو بگم.مهمترین تفاوت حرفه‌ی برنامه‌نویسی و مهندسی نرم‌افزار، توی تحصیلاتیه که یک مهندس میگذرونه. یک مهندس نرم‌افزار، با دانش مدیریتی و ریاضیاتی که کسب میکنه، موضوع (میتونید فرض کنید یک پروژه) رو از بالا نگاه میکنه، اون رو آنالیز میکنه و نیازهای مشتری رو میسنجه، کاربرها و مشتری‌های اون رو بررسی میکنه و در نهایت با یک راه حل مهندسی شده یا Engineered Solution برمی‌گرده. اصولا مهندسی نرم‌افزار یک کار تیمیه، در حالی که حرفه‌ی برنامه‌نویسی یک کار یک نفره.یک برنامه‌نویس، یا توسعه‌دهنده‌ی نرم‌افزار، کسیه که رهنمود‌ها یا Guidelineهای مهندس رو میگیره و اونها رو تبدیل به یک برنامه‌ی کامپیوتری میکنه. مهمترین ویژگی برنامه‌نویس‌ها اینه که خوب تجربه کسب میکنن و اکثرا تجربشون به دانشی که نیاز دارن برای اینکار میچربه.اما سریع تفاوت‌هاشون رو بررسی میکنم:تحصیلات: مهندس نرم‌افزار توی دانشگاه درس میخونه و مدرک مهندسی توی شاخه‌ی کامپیوتر میگیره. برنامه‌نویس به صورت خودآموز یاد میگیره و تجربه‌ی کاری کسب میکنه.مهندس نرم‌افزار معمار سیستم میشه، برنامه‌نویس کسیه که اون رو پیاده‌سازی میکنه.مهندسی نرم‌افزار کلی‌نگر و برنامه‌نویس جزئی‌نگر به حساب میاد.مهندس‌نرم‌افزار یک رویکرد علمی نسبت به حل مسئله داره و اون رو آنالیز میکنه، برنامه‌نویس تیکه‌های مختلف رو میسازه و روی یک موضوع در لحظه فوکوس میکنه.مهندس نرم‌افزار باید دانش تحلیلی زیاد و قدرت حل مسئله‌ی زیاد داشته باشه، برنامه‌نویس دانش زبان برنامه‌نویسی میخواد.مهندسین نرم‌افزار تو تیم‌های مهندسی کار میکنن و برنامه‌نویس‌ها قالبا به تنهایی.قبول دارم که گاهی تشخیص حد فاصل بین این دو واقعا سخت میشه، اما باید با خودمون روراست باشیم، برنامه‌نویس هستیم یا مهندس نرم‌افزار؟ اما این موضوع چه ربطی به فریم‌ورک داره؟ جدا، مگه انتخاب فریم‌ورک چی داره که لازمه فرق مهندسی نرم‌افزار و برنامه‌نویسی رو دونست؟ادامه رو اینجا بخونید....</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Fri, 05 Feb 2021 10:39:31 +0330</pubDate>
            </item>
                    <item>
                <title>تایپ‌های وابسته و توابع دوسویه</title>
                <link>https://virgool.io/@xenomorph/%D8%AA%D8%A7%DB%8C%D9%BE-%D9%87%D8%A7%DB%8C-%D9%88%D8%A7%D8%A8%D8%B3%D8%AA%D9%87-%D9%88-%D8%AA%D9%88%D8%A7%D8%A8%D8%B9-%D8%AF%D9%88%D8%B3%D9%88%DB%8C%D9%87-ejfzngfkyfw6</link>
                <description>قبل از اینکه وارد مفهوم پارامترها و توابع دوسویه بشم، باید اول چندتا مفهوم رو توضیح بدم. مفاهیمی که به جنریک‌ها و ماهیت ریاضیاتی توابع مربوط میشن.اگر درمورد جنریک‌ها نمیدونین، پیشنهاد میکنم که این مطلب امیررضا رو حتما بخونید. لازم هست که قبل از اینکه وارد این موضوع بشید، حتما در مورد جنریک‌ها آگاهی داشته باشید.Covariance و Contravarianceکوواریانس یا Covariance در واقع به وراثت برمی‌گرده. با یک مثال توضیح میدم، اگر تایپ B از A مشتق شده باشه، یعنی B وارث A هست یا به یه شکل دیگه، A کلاس پایه‌ی B محسوب میشه. در نتیجه B تمام متد‌ها و پراپرتی‌های A رو توی خودش داره.تو این حالت، میشه گفت که B از A بزرگتره. این ایده که B از A بزرگتره، یک ایده‌ی خیلی مهمه!بذارید یکم ریاضیاتی‌تر توضیح بدم، اگر B از A مشتق میشه، پس میشه گفت A&gt;B (من به جهت فلش خیلی دقت کردم، دقیقا درسته) و B هر آنچه که A داره رو توی خودش داره. حالا چون B همه‌ی چیز‌های A رو داره، ما میتونیم هرجا که از A استفاده شده، از B هم استفاده کنیم. گرچه این ارتباط اصطلاحا یک‌طرفه یا Asymmertical محسوب میشه. این ارتباط به عنوان اصل تعویض لیسکوف یا Liskov Substitution Principle هم شناخته میشه.توابعحالا بیاید ببینیم که این قائده چطور روی توابع هم استفاده میشه.اگه ما یک فانکشن رو تعریف کنیم که شیئی از جنس A رو به عنوان ورودی دریافت کنه، و شیئی از جنس B رو خارج کنه، یا در واقع:f(A) -&gt; B and A&gt;Bبرقرار باشه، طبق همین قانون ما میتونیم به عنوان ورودی تابع شیئی از جنس B رو بدیم، و شیئی از جنس B هم دریافت کنیم. در واقع میشه گفت که f(B) جایزه. میشه نوشت:class A {}

class B extends A {}

function f(p: A): B {
  return new B()
}

let myA: A = f(new B())به این معنی که اگه A&gt;B پارامتر ورودی A میتونه B هم باشه چون هرچی که A داره رو اون هم داره. پس با همین تعریف میشه گفت که پارامترهای ورودی کنتراواریانت یا Contravariant هستن و پارامترهای خروجی، کوواریانت یا Covariant.تایپ‌اسکریپتحالا بریم یکم در مورد زبان تایپ‌اسکریپ و یکی از ویژگی‌های کمتر شناخته شده‌ی اون صحبت کنیم، strictFunctionTypes! این آرگومان که میشه به کامپایلر پاس داد، به شما کمک میکنه که نوع دیگه‌ای از باگ‌ها رو شناسایی کنید و جلوشون رو بیگیرید.برای ادامه مطلب میتونید به سایت خودم مراجعه کنید :) اونجا توضیحات بیشتری در این رابطه میدم.با آرزوی موفقیت</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Fri, 29 Jan 2021 21:46:41 +0330</pubDate>
            </item>
                    <item>
                <title>دوباره به نوشتن رو آوردم!</title>
                <link>https://virgool.io/@xenomorph/%D8%AF%D9%88%D8%A8%D8%A7%D8%B1%D9%87-%D8%A8%D9%87-%D9%86%D9%88%D8%B4%D8%AA%D9%86-%D8%B1%D9%88-%D8%A2%D9%88%D8%B1%D8%AF%D9%85-jw1nogrenkby</link>
                <description>اولین پستخب من تصمیم گرفتم که بعد از یک مدت تقریبا طولانی (حدودا یک سال) دوباره به فارسی بنویسم.دلایلش مختلفن، تلاشم برای نوشتن به انگلیسی زیاد موفق نبود، چون باید روی یه موضوع زمان زیادی میگذاشتم تا کامل روش تسلط پیدا کنم. با خودم گفتم، چه کاریه، اول به فارسی می‌نویسم و بعد ترجمه میکنم.در نهایت به این ایده رسیدم که اول مطالب رو تو وبلاگ فارسیم بذارم و بعد یه نسخه‌ی دیگه توی انگلیسی.چه تغییراتی رو قرار هست ببینید؟واقعیتش تغییر زیادی صورت نگرفته. من همچنان قلمم همون قلم قبلیه، فقط قائدتا به مطالب عمیق‌تر میرسم.شاید یکی از بزرگترین تغییراتی که قابل لمس باشه، اینه که من بالاخره دست از سر سرور گرفتن و روی کلاد (AWS) کار کردن برداشتم و الان خیلی ساده سایتم رو با گتسبی ساختم و روی نتلیفای سرو کردم. برای نوشتن هم خب شاید همونطور که حدس زدید از مارکدان استفاده میکنم.چی به سر لیست روزنامت اومد؟پاکشون کردم ☺️ هر آنچه که ازش مونده بود رو. شاید دوباره شروع کنم، نمیدونم، اما اینبار فوکوس بیشتری رو روی مطالبم خواهم گذاشت. حتی احتمالش هست که یک چنل یوتیوب هم باز کنم.خوشحال میشم شما رو تو سایت فارسیم هم ببینم!با آرزوی موفقیت برای شماآیین</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Tue, 26 Jan 2021 12:27:49 +0330</pubDate>
            </item>
                    <item>
                <title>گراف‌کیو‌ال چیست؟ (لینک انگلیسی)</title>
                <link>https://virgool.io/@xenomorph/%DA%AF%D8%B1%D8%A7%D9%81%DA%A9%DB%8C%D9%88%D8%A7%D9%84-%DA%86%DB%8C%D8%B3%D8%AA-%D8%A7%D9%86%DA%AF%D9%84%DB%8C%D8%B3%DB%8C-ztuzcuh0kqje</link>
                <description>سلام و وقتتون بخیر.چندبار تلاش کردم که مطلب رو اینجا به اشتراک بذارم. اما متاسفانه زبان انگلیسی تو ویرگول پشتیبانی نمیشه و برای همین هم، چینش حروف به هم میریزه.اگر تمایل دارید، میتونید اصل مطلب رو از طریق این لینک پیدا کنید.سپاس فراوان</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Fri, 22 May 2020 16:26:13 +0430</pubDate>
            </item>
                    <item>
                <title>مطالب جدید، زبان جدید</title>
                <link>https://virgool.io/@xenomorph/%D9%85%D8%B7%D8%A7%D9%84%D8%A8-%D8%AC%D8%AF%DB%8C%D8%AF-%D8%B2%D8%A8%D8%A7%D9%86-%D8%AC%D8%AF%DB%8C%D8%AF-mcd2fa5bmhoj</link>
                <description>تصمیم گرفتم دوباره مطلب بنویسم. ?  اول اینکه سایت قبلیم رو دیگه تمدید نکردم، یعنی کلا با مطالب قبلیم خداحافظی کردم. ?البته چندتا دلیل وجود داره، یکی اینکه واقعا درست کردن یک مطلب خوب و حداقل بدرد بخور واقعا زمان‌بره و من اخیرا زمان کمی رو (متاسفانه) برای نوشتن میتونستم بذارم. ?دلیل دوم اینکه سایت قبلیم که با ری‌اکت و نکست‌جی‌اس و خانوادشون ساخته شده بود، به نگهداری نیاز داشت که خب زمان برای اونهم نداشتم. ?و مورد سوم اینکه، هرچند خواننده‌های فوق‌العاده خوبی رو داشتم،?  اما وضعیتی که از لحاظ زبانی درگیرش بودم من رو مجاب کرد که شروع به نوشتن به زبان انگلیسی کنم. مشکل خاصی هم نبود، صرفا با زبان انگلیسی میتونم خواننده‌های بیشتری داشته باشم.بعد رفتم سراغ سایت مدیوم. بدترین تجربه کاربریم رو باهاش داشتم! چرا یه خواننده باید محدود بشه به خوندن کلا ۵تا مطلب در ماه؟! ?بعد هم رفتم سایت dev.to. بد نبود اما خیلی شلوغ بود. در نتیجه تصمیم گرفتم دوباره یه سایت جدید با دامین جدید باز کنم و مطالبم رو اونجا با خیال راحت بنویسم. ?اگر شما هم از خواننده‌های من بودید و مطالبم براتون جالب بودن، باید بگم که اول از همه ازتون ممنونم، ? چون شما مهمترین منابع انگیزه‌ی من برای نوشتن بودید و هستید،? و دوم اینکه اگر سبک نوشتن من براتون جالب بود، پس احتمالا تو سایت جدیدم احساس غریبی نکنید و زود باهاش ارتباط برقرار کنید, فقط اینبار به انگلیسی.اگر دوست داشتید میتونید یه سری بهش بزنید آدرسش اینه: https://aien.meحالا اگر سایت ویرگول هم ساپورت زبان انگلیسی داشته باشه، مثل قبل یه نسخه از متنام رو بعد از انتشار شون اینجا هم کپی میکنم که در دسترستون باشن. ✏️بازم ممنون از همه و با آرزوی موفقیت هممون.سلامت باشید و فاصله ایمنی رو رعایت کنید. ?</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Thu, 16 Apr 2020 15:27:18 +0430</pubDate>
            </item>
                    <item>
                <title>با alias سریع‌تر کد بزنید!</title>
                <link>https://virgool.io/fsf-linux/%D8%A8%D8%A7-alias-%D8%B3%D8%B1%DB%8C%D8%B9%D8%AA%D8%B1-%DA%A9%D8%AF-%D8%A8%D8%B2%D9%86%DB%8C%D8%AF-dxfys8enofv3</link>
                <description>مقدمهالبته که دوست دارم یه متن بلند بنویسم! اما همزمان که دارم این مطلب رو مینویسم، دارم روی یه مطلب (چند نسخه‌ای) کار میکنم در باره‌ی برنامه‌نویسی وب. مثل همیشه، از صفر تا صدش، برای اونایی که تا حالا حتی برنامه‌نویسی هم نکردن! کار عجیبیه، کلی چیز باید بخونم و انجام بدم و یاد بگیرم. بگذریم...این مطلب من، قرار نیست خیلی طولانی باشه و پیشبینی میکنم که به مرور بروز رسانی بشه. داستانش هم از این قراره که، من علاقه ندارم کدها رو چندبار بنویسم. مد نظرم اینه که یه سری «کلید» برای خودم داشته باشم و جاهای مختلف ازشون استفاده کنم.لینوکسلینوکس یه هسته‌ی سیستم‌عامله. یعنی دستورات و فرایندهایی که یه سیستم‌عامل نیاز داره رو براش فراهم میکنه و یه راه ارتباطی بین سخت‌افزار و سیستم‌عامله. ضمنا، لینوکس متن بازه، یعنی میشه هرچیزی رو توش تغییر داد و شخصی‌سازی کرد.سیستم‌عامل‌های زیادی هم وجود دارن که مبتنی بر لینوکس هستن، یعنی، از هسته‌ی لینوکس استفاده میکنن و یه جورایی «توزیعی» یا Distributionای از لینوکس هستن (بین کاربرهای لینوکسی، به Distro هم معروفن). من اینجا سعی کردم در مورد سیستم‌عامل‌های لینوکس بیشتر توضیح بدم.شِل یا Shellخیلی ساده، شِل یا «تِرمینال» یه برنامه هست که دستورات رو از کاربر میگیره و اونا رو به سیستم‌عامل و در نهایت خروجی رو نمایش میده. شِلِ لینوکس یکی از مهمترین اجزای لینوکس به حساب میاد و یکی از محیط‌های مورد علاقه‌ی برنامه‌نویس‌هاست.اینجا من تصمیم دارم که روی یه سری از اصول این نرم‌افزار کار کنم و در نهایت یه سری از دستورات به درد بخور که خودمم استفاده میکنم رو بگم. ضمنا، اگر شما هم دستوراتی رو دارید، بهم بگید که اینجا آپدیت کنم.برای باز کردن نرم‌افزار تِرمینال، میتونید توی سیستم‌عامل لینوکسی دکمه‌ی Ctrl + Alt + T رو بزنید، یا دکمه‌ی CMD + Space رو توی سیستم‌عامل مک بزنید و دنبال Terminal بگردید.دستورات پایهاین دستورات رو بدون علامت $ اجرا کنید. $ یک نشانست و به این معنیه که دستور داره با مجوز یک «کاربر» و نه یک «مدیر» اجرا میشه. نشانه‌ی یک مدیر، علامت # هست.۱. pwdاین دستور به شما آدرس جایی که توش هستید رو میگه. وقتی ترمینال باز میشه، معمولا از پوشه‌ی Home شروع به کار میکنه. ضمنا، این آدرس‌ها Absolute هستن، یعنی از پوشه‌ی ریشه یا Root شروع میشن.$ pwd
/home/aien۲. lsاین دستور به شما محتویات پوشه‌ای که توش هستید رو میگه. اگر به آخرش -a هم اضافه کنید، میتونید فایل‌های مخفی رو هم ببینید.$ ls -a
.                Downloads      .gtk-bookmarks  .node-gyp            .rdm                                                       .vscode
..               .dropbox       .gtkrc-2.0      .npm                 .rediscli_history                                          Web
...۳. cdاین دستور به شما این امکان رو میده که جای خودتون رو عوض کنید. مثلا از پوشه‌ای که توش هستید، برید به یه پوشه‌ی دیگه.$ pwd
/home/aien/
$ cd /home/aien/Bilder
$ pwd
/home/aien/Bilder۴. mkdir و rmdirاین دستور به شما آدرس جایی که توش هستید رو میگه. وقتی ترمینال باز میشه، معمولا از پوشه‌ی Home شروع به کار میکنه. ضمنا، این آدرس‌ها Absolute هستن، یعنی از پوشه‌ی ریشه یا Root شروع میشن.$ mkdir sample
$ cd sample
$ pwd
/home/aien/Bolder/sample
$ cd ..
$ pwd
/home/aien/Bilder
$ rmdir sample
$ ls
...۵. touchاین دستور به شما امکان ساخت فایل‌ها رو میده.$ touch file.txt
$ ls
...
file.txt
...۶. rmاین دستور به شما امکان حذف فایل‌ها و تو بعضی شرایط، فولدرها رو میده.$ rm file.txt۷. cpاین دستور به شما امکان کپی کردن فایل‌ها رو میده. این دستور، دوتا ورودی دریافت میکنه، اولی آدرس جایی هست که فایل قرار داره و دومی آدرس جایی هست که فایل باید اونجا بره.$ touch file.txt
$ pwd
/home/aien/Bilder
$ cp ./file.txt /home/aien/Musik
$ cd /home/aien/Musik
$ pwd
/home/aien/Musik
$ ls
...
file.txt
...۸. mvاین دستور به شما امکان جابه‌جا کردن فایل‌ها رو میده و مثل دستور کپی عمل میکنه.$ pwd
/home/aien/Musik
$ mv file.txt /home/aien/Videos
$ ls
...
...
$ cd ../Videos
$ pwd
/home/aien/Videos
$ ls
...
file.txt
...۹. rmاین دستور به شما امکان حذف فایل‌ها و تو بعضی شرایط، فولدرها رو میده.$ rm file.txtدستورات حرفه‌ای‌تر۱. nanoاین دستور به شما امکان نوشتن داخل یک فایل رو میده. اگر اون فایل وجود نداشته باشه، اون رو ایجاد میکنه. بعد از اینکه داخل فایل نوشتید، کافیه Ctrl + X رو بزنید، Y رو بزنید و از برنامه خارج بشید. نوشته‌ها ذخیره شدن!$ nano file.txt۲. catاین دستور به شما امکان نمایش محتوای یک فایل رو میده.$ cat file.txt
In yek file nemune ast!دستور aliasدستور alias کمک میکنه تا دستور یا دستوراتی رو با اسامی دیگه صدا بزنیم و اجرا کنیم. شاید با خودتون بگید آخه چه کاربردی داره وقتی میتونم خودم دستور رو تایپ کنم؟موضوع اینه که گاهی نیاز هست دستوراتی رو اجرا کنیم که نسبتا پیچیده هستن و فقط تو بعضی چیزهای کوچیک فرق میکنن.برای شروع، دستور زیر رو تایپ کنید:$ aliasیه لیست طولانی از دستورات رو خواهید گرفت:-=&#039;cd -&#039;
...
l=&#039;ls -lah&#039;
...
serve=&#039;http-server -o -a localhost .&#039;
which-command=whenceآخر این لیست، دستور هست که نوشته l=&#x27;ls -lah&#x27;. اگر شما این دستور رو تو ترمینال بنویسید، یعنی بنویسید l، مثل این میمونه که به ترمینال گفتید دستورls -lah رو اجرا کنه.حالا برای نمونه، دستور زیر رو بزنید:$ alias p=&quot;pwd&quot;از این به بعد اگر من دستور p رو بزنم، انگار دستور pwd رو زدم، پس آدرس جایی که هستم رو میگیرم:$ alias p=&quot;pwd&quot;
$ p
/home/aienحالا فرض کنید که توی سیستمتون، نرم‌افزار Apache رو داشتید. برای دستکاری فایل اصلیش، لازم بود که مثلا nano رو با کل آدرس اون فایل وارد کنید. چی میشد اگر مینوشتید:$ alias a=&quot;nano /etc/httpd/conf/httpd.conf&quot;اونوقت به جای هربار تیاپ کردن دستور، فقط a رو اجرا میکردید و فایل رو دستکاری...چطور دستورات alias رو داعمی کنیماگر تو یه ترمینال، یه دستور alias رو وارد کنید، بعد از بستن اون ترمینال، دستورتون هم از بین میره و دفعه‌ی بعدی دوباره باید دوباره تعریفش کنید. راهکارش اینه که از فایل .bashrc استفاده کنید. خیلی ساده، دستور زیر رو بزنید:$ nano ~/.bashrcاین دستور، فایل .bashrc که توی پوشه‌ی Home شما هست رو باز میکنه. حالا دستور زیر رو به بالای این فایل اضافه کنید:alias p=&quot;pwd&quot;
alias bashrc=&quot;nano ~/.bashrc&quot;
...با این کار، هربار که دستور p رو بزنید، به جاش دستور pwd اجرا میشه. برای حذفش هم، کافیه دوباره اون رو از فایلتون حذف کنید (دستور زیر رو تو ترمینال بزنید تا فایلش باز بشه).$ bashrcدستورات پر کاربردیه لیست از دستورات پر کاربرد هست که توی سایت خودم گذاشتم. میتونید به اونجا سر بزنید و دستورات بروز شده رو ببینید.موفق باشید</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Wed, 31 Oct 2018 21:45:08 +0330</pubDate>
            </item>
                    <item>
                <title>با alias سریع‌تر کد بزنید!</title>
                <link>https://virgool.io/pullrequest/%D8%A8%D8%A7-alias-%D8%B3%D8%B1%DB%8C%D8%B9%D8%AA%D8%B1-%DA%A9%D8%AF-%D8%A8%D8%B2%D9%86%DB%8C%D8%AF-whyuymkvvoxc</link>
                <description>دستورات سریع لینوکسی برای برنامه‌نویس‌هامقدمهالبته که دوست دارم یه متن بلند بنویسم! اما همزمان که دارم این مطلب رو مینویسم، دارم روی یه مطلب (چند نسخه‌ای) کار میکنم در باره‌ی برنامه‌نویسی وب. مثل همیشه، از صفر تا صدش، برای اونایی که تا حالا حتی برنامه‌نویسی هم نکردن! کار عجیبیه، کلی چیز باید بخونم و انجام بدم و یاد بگیرم. بگذریم…این مطلب من، قرار نیست خیلی طولانی باشه و پیشبینی میکنم که به مرور بروز رسانی بشه. داستانش هم از این قراره که، من علاقه ندارم کدها رو چندبار بنویسم. مد نظرم اینه که یه سری «کلید» برای خودم داشته باشم و جاهای مختلف ازشون استفاده کنم.لینوکسلینوکس یه هسته‌ی سیستم‌عامله. یعنی دستورات و فرایندهایی که یه سیستم‌عامل نیاز داره رو براش فراهم میکنه و یه راه ارتباطی بین سخت‌افزار و سیستم‌عامله. ضمنا، لینوکس متن بازه، یعنی میشه هرچیزی رو توش تغییر داد و شخصی‌سازی کرد.سیستم‌عامل‌های زیادی هم وجود دارن که مبتنی بر لینوکس هستن، یعنی، از هسته‌ی لینوکس استفاده میکنن و یه جورایی «توزیعی» یا Distributionای از لینوکس هستن (بین کاربرهای لینوکسی، به Distro هم معروفن). من اینجا سعی کردم در مورد سیستم‌عامل‌های لینوکس بیشتر توضیح بدم.شِل یا Shellخیلی ساده، شِل یا «تِرمینال» یه برنامه هست که دستورات رو از کاربر میگیره و اونا رو به سیستم‌عامل و در نهایت خروجی رو نمایش میده. شِلِ لینوکس یکی از مهمترین اجزای لینوکس به حساب میاد و یکی از محیط‌های مورد علاقه‌ی برنامه‌نویس‌هاست.اینجا من تصمیم دارم که روی یه سری از اصول این نرم‌افزار کار کنم و در نهایت یه سری از دستورات به درد بخور که خودمم استفاده میکنم رو بگم. ضمنا، اگر شما هم دستوراتی رو دارید، بهم بگید که اینجا آپدیت کنم.برای باز کردن نرم‌افزار تِرمینال، میتونید توی سیستم‌عامل لینوکسی دکمه‌ی Ctrl + Alt + T رو بزنید، یا دکمه‌ی CMD + Space رو توی سیستم‌عامل مک بزنید و دنبال Terminal بگردید.دستورات پایهاین دستورات رو بدون علامت $ اجرا کنید. $ یک نشانست و به این معنیه که دستور داره با مجوز یک «کاربر» و نه یک «مدیر» اجرا میشه. نشانه‌ی یک مدیر، علامت # هست.۱. pwdاین دستور به شما آدرس جایی که توش هستید رو میگه. وقتی ترمینال باز میشه، معمولا از پوشه‌ی Home شروع به کار میکنه. ضمنا، این آدرس‌ها Absolute هستن، یعنی از پوشه‌ی ریشه یا Root شروع میشن.$ pwd
/home/aien۲. lsاین دستور به شما محتویات پوشه‌ای که توش هستید رو میگه. اگر به آخرش -a هم اضافه کنید، میتونید فایل‌های مخفی رو هم ببینید.$ ls -a
.                Downloads      .gtk-bookmarks  .node-gyp            .rdm                                                       .vscode
..               .dropbox       .gtkrc-2.0      .npm                 .rediscli\_history                                          Web
...۳. cdاین دستور به شما این امکان رو میده که جای خودتون رو عوض کنید. مثلا از پوشه‌ای که توش هستید، برید به یه پوشه‌ی دیگه.$ pwd
/home/aien/
$ cd /home/aien/Bilder
$ pwd
/home/aien/Bilder۴. mkdir و rmdirاین دستور به شما آدرس جایی که توش هستید رو میگه. وقتی ترمینال باز میشه، معمولا از پوشه‌ی Home شروع به کار میکنه. ضمنا، این آدرس‌ها Absolute هستن، یعنی از پوشه‌ی ریشه یا Root شروع میشن.$ mkdir sample
$ cd sample
$ pwd
/home/aien/Bolder/sample
$ cd ..
$ pwd
/home/aien/Bilder
$ rmdir sample
$ ls
...۵. touchاین دستور به شما امکان ساخت فایل‌ها رو میده.$ touch file.txt
$ ls
...
file.txt
...۶. rmاین دستور به شما امکان حذف فایل‌ها و تو بعضی شرایط، فولدرها رو میده.$ rm file.txt۷. cpاین دستور به شما امکان کپی کردن فایل‌ها رو میده. این دستور، دوتا ورودی دریافت میکنه، اولی آدرس جایی هست که فایل قرار داره و دومی آدرس جایی هست که فایل باید اونجا بره.$ touch file.txt
$ pwd
/home/aien/Bilder
$ cp ./file.txt /home/aien/Musik
$ cd /home/aien/Musik
$ pwd
/home/aien/Musik
$ ls
...
file.txt
...۸. mvاین دستور به شما امکان جابه‌جا کردن فایل‌ها رو میده و مثل دستور کپی عمل میکنه.$ pwd
/home/aien/Musik
$ mv file.txt /home/aien/Videos
$ ls
...
...
$ cd ../Videos
$ pwd
/home/aien/Videos
$ ls
...
file.txt
...۹. rmاین دستور به شما امکان حذف فایل‌ها و تو بعضی شرایط، فولدرها رو میده.$ rm file.txtدستورات حرفه‌ای‌تر۱. nanoاین دستور به شما امکان نوشتن داخل یک فایل رو میده. اگر اون فایل وجود نداشته باشه، اون رو ایجاد میکنه. بعد از اینکه داخل فایل نوشتید، کافیه Ctrl + X رو بزنید، Y رو بزنید و از برنامه خارج بشید. نوشته‌ها ذخیره شدن!$ nano file.txt۲. catاین دستور به شما امکان نمایش محتوای یک فایل رو میده.$ cat file.txt
In yek file nemune ast!دستور aliasدستور alias کمک میکنه تا دستور یا دستوراتی رو با اسامی دیگه صدا بزنیم و اجرا کنیم. شاید با خودتون بگید آخه چه کاربردی داره وقتی میتونم خودم دستور رو تایپ کنم؟موضوع اینه که گاهی نیاز هست دستوراتی رو اجرا کنیم که نسبتا پیچیده هستن و فقط تو بعضی چیزهای کوچیک فرق میکنن.برای شروع، دستور زیر رو تایپ کنید:$ aliasیه لیست طولانی از دستورات رو خواهید گرفت:-=&#039;cd -&#039;
...
l=&#039;ls -lah&#039;
...
serve=&#039;http-server -o -a localhost .&#039;
which-command=whenceآخر این لیست، دستور هست که نوشته l=&#x27;ls -lah&#x27;. اگر شما این دستور رو تو ترمینال بنویسید، یعنی بنویسید l، مثل این میمونه که به ترمینال گفتید دستورls -lah رو اجرا کنه.حالا برای نمونه، دستور زیر رو بزنید:$ alias p=&quot;pwd&quot;از این به بعد اگر من دستور p رو بزنم، انگار دستور pwd رو زدم، پس آدرس جایی که هستم رو میگیرم:$ alias p=&quot;pwd&quot;
$ p
/home/aienحالا فرض کنید که توی سیستمتون، نرم‌افزار Apache رو داشتید. برای دستکاری فایل اصلیش، لازم بود که مثلا nano رو با کل آدرس اون فایل وارد کنید. چی میشد اگر مینوشتید:$ alias a=&quot;nano /etc/httpd/conf/httpd.conf&quot;اونوقت به جای هربار تیاپ کردن دستور، فقط a رو اجرا میکردید و فایل رو دستکاری…چطور دستورات alias رو دائمی کنیماگر تو یه ترمینال، یه دستور alias رو وارد کنید، بعد از بستن اون ترمینال، دستورتون هم از بین میره و دفعه‌ی بعدی دوباره باید دوباره تعریفش کنید. راهکارش اینه که از فایل .bashrc استفاده کنید. خیلی ساده، دستور زیر رو بزنید:$ nano ~/.bashrcاین دستور، فایل .bashrc که توی پوشه‌ی Home شما هست رو باز میکنه. حالا دستور زیر رو به بالای این فایل اضافه کنید:alias p=&quot;pwd&quot;
alias bashrc=&quot;nano ~/.bashrc&quot;
...با این کار، هربار که دستور p رو بزنید، به جاش دستور pwd اجرا میشه. برای حذفش هم، کافیه دوباره اون رو از فایلتون حذف کنید (دستور زیر رو تو ترمینال بزنید تا فایلش باز بشه).$ bashrcدستورات پر کاربردیه لیست از دستورات پر کاربرد هست که توی سایت خودم گذاشتم. میتونید به اونجا سر بزنید و دستورات بروز شده رو ببینید.موفق باشید</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Wed, 31 Oct 2018 15:07:27 +0330</pubDate>
            </item>
                    <item>
                <title>داکر، داکر کامپز، کانتینرها و اتوماسیون</title>
                <link>https://virgool.io/pullrequest/%D8%AF%D8%A7%DA%A9%D8%B1-%D8%AF%D8%A7%DA%A9%D8%B1-%DA%A9%D8%A7%D9%85%D9%BE%D8%B2-%DA%A9%D8%A7%D9%86%D8%AA%DB%8C%D9%86%D8%B1%D9%87%D8%A7-%D9%88-%D8%A7%D8%AA%D9%88%D9%85%D8%A7%D8%B3%DB%8C%D9%88%D9%86-wp4sf7bcg10s</link>
                <description>داکر چی هست؟ داکر کامپز چیکار میکنه و چجوری میتونیم پروژمون رو اتوماسیون کنیم؟داکر، کانتینر و اتوماسیونمقدمهبالاخره بعد از یه مدت طولانی که از داون شدن سایتم میگذره، تونستم دوباره وصلش کنم و کانفیگای سمت سرور رو دوباره فیکس کنم. شاید جالب باشه ولی سرور من جای خلوتیه و چیز زیادی توش نیست و وب‌سایت خودم تنها برنامه‌ایه که توش اجرا میشه، اما نکته‌ی جالب اینه که موقع دیپلوی باهاش خیلی مشکل دارم. بگذریم، همین مشکلات باعث شد که به نوشتن این مطلب فکر کنم و تا جایی که میتونم در مورد داکر توضیح بدم.خواهش من مثل همیشه، انه که ان مطلب رو بخونید، ازش لذت ببرید و برای دوستاتون هم بفرستید و اگر جایی اشکالی دیدید، بهم خبر بدید. ضمنا، حقوق نویسنده رو هم فراموش نکنید و اگر جایی از این مطلب استفاده میکنید، اسم نویسنده اصلی (من، آیین) رو توش درج کنید.سپاسداکر (Docker) چی هست؟اول از همه، داکر اسم شرکتی هست که واژه کانتِینِر یا Container رو روانه‌ی دنیای آی‌تی کرده. البته که قبلا هم از این واژه استفاده‌های گسترده‌ای میشده، اما داکر باعث شده که واژه کانتِینِر معنی مشخص‌تر و دقیق‌تری پیدا کنه.خود نرم‌افزار داکر، یه سرویس برای مدیریت کانتینرها یا Container Service Manager هست. کلیدواژه‌هایی که میشه برای داکر استفاده کرد، توسعه‌دادن، دیپلوی کردن و اجرا کردن هستن. در واقع داکر هدفش اینه که وقتی برنامه‌نویس‌ها، نرم‌افزاری رو می‌نویسن، اون رو به کانتینرها منتقل و به سادگی اون رو هر جایی اجرا کنن.پلتفرم (سَکو؟!) کانتینر چی هست؟پلتفرم کانتینر یا Container Platform یه سرویس کامل برای سازمان‌ها و شرکت‌هاست که بتونن باهاش مشکلات مختلفی رو حل کنن. مهمترین ویژگی کانتینرها اینه که تمام نرم‌افزارهایی که برنامه لازم داره رو، توی خودشون نگه‌میدارن. اما یکم در مورد کانتینرها عمیق بشم…کانتینر یه پراسِس (Process) داکر هست که فقط روی لینوکس یا ویندوز اجرا میشه (ظاهرا برای مک هم هست ولی من جایی ندیدم) و داخل خودش هرچیزی که برای اجرا شدن نیاز داشته‌باشه رو داره. در واقع یه کانتینر یکمی شبیه به ماشین‌مجازی یا Virtual Machine هست با این تفاوت که هسته‌ی سیستم‌عامل میزبان یا Host رو به اشتراک میذاره.عکس بالا، اساسی‌ترین تفاوت کانتینرها با ماشین‌های مجازی رو نشون میده. چارت سمت راست کانتینر و سمت چپ، ماشین مجازی. زیر ساخت‌ها یا Infrastructures شبیه به هم، داکر از سیستم‌عامل میزبان و ماشین مجازی از Hypervisor که یه لایه هست تا برنامه‌های مورد نیاز سیستم‌عامل داخل ماشین رو فراهم کنه، استفاده میکنه. تو ماشین مجازی شما به یه سیستم‌عامل مهمان احتیاج دارید، مثلا توی سیستم‌عامل لینوکستون، ویندوز نصب میکنید، اما داکر اینطور نیست و از موتور خودش استفاده میکنه تا با سیستم‌عامل میزبان ارتباط برقرار کنه. تو ماشین مجازی شما سیستم‌عامل رو نصب میکنید که برنامه‌های لازم رو بتونید فراهم کنید. این قدم تو کانتینر از بین رفته (و دقیقا چیزیه که سرعت کانتینر رو به نسبت ماشین‌مجازی خیلی بیشتر می‌کنه). در نهایت کتابخونه‌ها و برنامه‌های لازم اجرا میشن و شما میتونید سیستمتون رو بالا بیارید.این رو اضافه میکنم، فرض کنید داکر همون نرم‌افزار Oracle VirtualBox یا VMWare هست و کانتینرها، همون سیستم‌عامل‌هایی که توشون نصب می‌کنیم.Containerization vs Virtualizationقبل از اینکه وارد این مبحث بشم، یه نگاهی به ترمینولوژی داکر داشته باشیم:موتور داکر یا Docker Engine قسمتی از داکر که وظیفه‌ی ایجاد و اجرای کانتینرها رو دارههاب داکر یا Docker Hubسرویسی از داکر برای به اشتراک‌گذاری کانتینرها با دیگرانداکر کامپوز یا Docker Composeابزاری که باهاش برنامه‌های چند کانتینری تعریف میکنیم. این ابزار از فایلهای Yaml استفاده میکنه تا فایل‌ها و تنظیمات رو کانفیگ کنه و کانتینر رو آماده اجرا کنه.در کل استفاده از این ابزار سه مرحله داره:محیط برنامه رو با یه Dockerfile تعریف میکنیم تا همه‌جا بشه ازش استفاده کرد.سرویس‌هایی که لازم هست برای اجرای این کانتینر رو تو فایل docker-compose.yml میذاریم تا با فایل Dockerfile یه جا اجرا بشن.دستور docker-compuse up رو اجرا میکنیم و تموم میشه!داکر ایمِج یا Docker Imageتو داکر، همه‌چیز بر اساس ایمِج‌ها ساخته شده!داکر فایل یا Docker fileدستوراتی که برای ساخت ایمِج لازم هست اینجا تعریف میشه.حالا کانتِینِریزِیشن در مقابل ویرچوالیزِیشن یا مجازی‌سازی چی هست؟هرچه‌قدر که زمان میگذره، تکنولوژی داکر بین حرفه‌ای‌های IT محبوبیت بیشتری پیدا می‌کنه، که باعث میشه برای برنامه‌نویس‌ها دونستن حداقل مبانی کانتینر‌ها به یک «باید» تبدیل بشه.صنعت IT هرروز درحال تغییر و پیشرفته و «سرعت و بهینه‌سازی» تبدیل به اساس این صنعت شدن. تکنولوژی‌ها سعی کردن روش‌های بهتری رو برای اتوماسیون ارائه بدن تا پروسه ساخت و تولید برنامه‌ها روراحتتر و سریع‌تر کنن.نمیدونم که آیا با Industry 4.0 آشنایی دارید یا نه، اما مجازی‌سازی یا ویرچوالیزیشن (Virtualization) سعی کرده تا این نسخه از صنعت IT رو بهینه‌تر و قابل‌حمل‌تر یا Portable کنه. با این‌حال، تکنولوژی مجازی‌سازی نقاط ضعف جدی رو داره، مثل کاهش محسوس پرفورمنس نرم‌افزارها که بخاطر وزن زیاد و ساختار سنگین VMها یا Virtual Machineها اتفاق میوفته. یا مثلا غیرقابل حمل بودن برنامه‌ها و کارایی پایین در مدیریت منابع سیستم و چیزهای دیگه از این دسته.اینجاست که صنعت IT رفته سراغ تکنولوژی داکر و کانتینریزیشن! دقیق‌تر میگم، موتور داکر برای کانتینریزیشن ساخته شده که مراحل بسته‌بندی، حمل و گسترش برنامه‌ها رو بسیار ساده کرده.شکافت هسته‌ی اتم!برای یادگیری و راه‌اندازی داکر، نیازی نیست فیزیک کوانتوم بلد باشید یا بتونید حداقل یکی از سوالای میلنیوم ریاضی رو حل کنید! فقط کافیه یکمی با محیط ترمینال و cli دوست باشید و یک تکست‌ادیتور هم کنار دستتون باشه، و خب قطعا داشتن یکمی دانش برنامه‌نویسی هم میتونه به کارتون بیاد!نصب و راه‌اندازی داکرگرفتن تمام ابزارهای مورد نیازتون برای داکر میتونه کمی خسته‌کننده به نظر برسه. اما توصیه‌ی من اینه که قبل از نصب داکر، حتما نرم‌افزار vscode رو دانلود کنید و در نهایت داکر رو برای سیستم‌عامل خودتون دریافت کنید.بعد از نصب داکر، دستور زیر رو اجرا کنید تا مطمئن بشیم همه‌چیز درست انجام شده:$ docker run hello-worldکه در پاسخش باید نتیجه‌ی زیر رو دریافت کنید:Hello from Docker.
This message shows that your installation appears to be working correctly.بازی با BusyBoxحالا که داکر نصب شده، بریم و یکم دستامون رو کثیف کنیم. برای اینکار یه کانتینر BusyBox (یه نرم‌افزار که یسری از ابزارهای Unix رو توی یه فایل به شما میده) رو نصب میکنیم تا طعم دستور docker run رو بچشیم.برای شروع، دستور زیر رو اجرا کنید:$ docker pull busyboxدقت داشته باشید که ممکن هست به ارور permission denied برخورد کنید. بهترین راه اینه که خودتون رو توی گروه docker اضافه کنید تا ازش پیشگری بشه.دستور pull ایمِج BusyBox رو از رجیستری داکر (Docker Registry) یا همون داکرهاب (Docker Hub)دریافت و اون روی روی سیستممون ذخیره میکنه. ضمنا شما میتونید دستور docker images رو اجرا کنید تا ببینید چه ایمِج‌هایی روی سیستمتون نصب شدن.REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
nexus.ida-analytics.de/ida/moira     latest              e3503776559a        6 days ago          387MB
nexus.ida-analytics.de/ida/grafana   latest              a1192aa71c7f        7 days ago          387MB
nexus.ida-analytics.de/ida/grafana                 6145fb02ee49        7 days ago          387MB
nexus.ida-analytics.de/ida/moira                   1323d422a434        7 days ago          387MB
busybox                              latest              8c811b4aec35        7 weeks ago         1.15MB Docker Runعالی شد! حالا وقتش شده که یه کانتینر داکر، مبتنی بر ایمِجی که گرفتیم رو اجرا کنیم. برای اینکار از دستور زیر استفاده میکنیم:$ docker run busybox
چی شد؟! چرا هیچ اتفاقی رخ نداد؟! خب، واقعیت اینه که کلی اتفاقات اینجا افتاده که با چشم غیر مسلح قابل رویت نیست :دی. وقتی که شما دستور run رو صدا میزنید، داکر ایمِجی که گفتید رو پیدا میکنه (اینجا میشه Busybox)، یه کانتینر براش میسازه و یه دستور رو توی کانتینر اجرا میکنه. اگر دقت کنید، تو دستور docker run busybox ما هیچ دستور اضافی رو فراهم نکردیم. بنابراین کانتینر ساخته شده، بالا اومده، یه دستور خالی رو اجرا کرده و خارج شده.دستور بالا رو میشه اینطور هم نوشت:$ docker run busybox echo &quot;Salam Donya!!&quot;
Salam Donya!!اینجا داکر، دستور echo رو اجرا کرده و در نهایت بسته شده. حالا فکر کنید میخواستید همه‌ی اینا رو با ماشین‌مجازی اجرا کنید! چقدر باید صبر می‌کردید؟حالا وقتش شده که دستور docker ps رو اجرا کنیم.$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMESاز اونجایی که هیچ کانتینری در حال اجرا نیست، ما هم یه لیست خالی رو دریافت کردیم. حالا یکم دستور رو دقیق‌تر میکنیم:$ docker ps -a
CONTAINER ID        IMAGE                                       COMMAND                CREATED             STATUS                      PORTS               NAMES
2059d101f971        busybox                                     &quot;echo Hallo&quot;           15 minutes ago      Exited (0) 15 minutes ago                       hopeful_nightingale
45f36d883bd4        busybox                                     &quot;sh&quot;                   15 minutes ago      Exited (0) 15 minutes ago                       kind_mcnulty
375b34dfa64c        nexus.ida-analytics.de/ida/moira:latest     &quot;/bin/moira&quot;           6 days ago          Exited (137) 6 days ago                         moira
45ba50ce36f9        nexus.ida-analytics.de/ida/grafana:latest   &quot;/bin/start_grafana&quot;   6 days ago          Exited (0) 6 days ago                           grafanaهمون‌طور که مشخصه، پارامتر -a دستور داده که لیست تمام کانتینرها، فاقد از وضعیتشون (که اینجا exitedهست) برگردونده بشه.شاید براتون سوال بشه که چطور میشه دستورات بیشتری رو توی کانتینر اجرا کرد؟ خیلی آسون. اگر با دستور ssh آشنایی داشته باشید، میخوایم اینجا یه کاری مشابه اون رو انجام بدیم:$ docker run -it busybox sh
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # pwd
/
/ # uptime
 22:30:58 up  3:26,  0 users,  load average: 1.54, 1.46, 1.48
/ #اجرا کردن دستور run با پارامتر -it باعث میشه که ما به داخل کانتینر (در واقع با ساخت یه سِشِن tty) بریم و دستوراتی که میخوایم رو اونجا اجرا کنیم.قبل از اینکه به مرحله‌ی بعدی برم، بهتون این نکته رو هم میگم که چطور میشه کانتینرها رو حذف کرد. بالاتر دیدیم که با اجرا کردن دستور docker ps -a میتونیم لیست تمام کانتینرهامون رو بدست بیاریم. برای حذف یه کانتینر کافیه که CONTAINER ID او کانتینر رو برداریم و بعد دستور docker rm CONTAINER_ID رو اجرا کنیم. که در پاسخش باید آی‌دی کانتینر دوباره به شما نمایش داده بشه.دستور زیر هم هست:$ docker rm $(docker ps -a -q -f status=exited)اجرا کردن این دستور، تمام کانتینرهایی که وضعیت exited دارن رو پاک میکنه.وب‌اَپ در داکرتا اینجا فهمیدیم که دستور docker run تا حدودی چطور کار میکنه، همزمان یکمی هم با کانتینرها بازی کردیم و با ترمینولوژی داکر بیشتر آشنا شدیم. حالا وقتش شده که بریم سراغ مسائل اساسی، و ببینیم که چطور میشه یه وب‌اَپ رو تو داکر دیپلوی یا Deploy کرد.سایت‌های استاتیکبذارید قدم‌های کوچک برداریم. اولین چیزی که میریم سراغش، دیپلوی کردن یه سایت استاتیک خیلی ساده هست. یه ایمِج رو از داکر‌هاب دریافت یا pull میکنیم و اجراش میکنیم تا ببینیم چقدر راه‌اندازی سایت‌های استاتیک کار آسونیه.ایمِجی که برای اینکار استفاده میکنیم، یه ایمِج از قبل آماده شدست:$ docker run prakhar1989/static-siteاز اونجایی که این ایمِج به صورت لوکال یا محلی تو سیستم ما نیست، داکر اون رو از رجیستری دریافت میکنه و بعد ایمِج رو اجرا میکنه. اگر همه‌چیز خوب پیش بره، شما پیام Nginx is running... رو خواهید دید. حالا که سرور راه‌افتاده، چطور میشه بهش دسترسی داشت؟ چطوری میشه فهمید تو چه پورتی اجرا شده؟خب تو این حالت، داکر هیچ پورتی رو نمایش یا اصطلاحا اِکسپوز (Expose) نمیکنه، برای همین لازم هست که مجددا دستور docker run رو اجرا کنیم تا پورت‌ها رو نمایش بدیم. همزمان هم باید کاری کنیم که ترمینال روی این حالت قفل نشه و ما بتونیم از ترمینال، بدون بستن سرور خارج بشیم. به این حالت میگن Detached Mode یا حالت جدا شده!$ docker run -d -P --name static-site prakhar1989/static-site
531b38e65151ba7ee133aff085d4c3e31d9ab349d0fed2b48b91cf28d53ca685تو دستور بالا، -d حالت detached mode رو اجرا و -P پورت‌هارو باز میکنه. --name هم اسمی رو برای کانتینر درنظر میگیره. حالا میتونیم پورت‌های باز شده رو پیدا کنیم:$ docker port static-site
443/tcp -&gt; 0.0.0.0:32768
80/tcp -&gt; 0.0.0.0:32769حالا، http://localhost:32769 رو باز کنید و نتیجه رو ببینید.همچنین میتونید یه آدرس پورت دلخواه هم به ایمِجتون بدید:$ docker run -p 8888:80 prakhar1989/static-site
Nginx is running...این دستور میگه که: به پورت ۸۸۸۸ سیستم هاست یا میزبان، هرچیزی که تو پورت ۸۰ ایمِج بود رو اختصاص بده. برای اینکه کانتینر رو متوقف کنید، دستور docker stop رو به همراه آی‌دی کانتینر اجرا کنید.مطمئن هستم که شما هم موافقید این کار واقعا آسون بود! فکر کنید شما یه سرور دارید و میخواید سایتتون رو روش راه‌اندازی کنید، کل کار اینه که داکر رو نصب کنید و دستورات بالا رو وارد کنید!ولی خب، این برای ما کافی نیست، چون ما دوست داریم بیشتر بدونیم :) برای همین باید یاد بگیریم چطور داکر ایمِج خودمون رو بسازیم…داکر ایمِج‌هاما با ایمِج‌ها تا حدودی آشنا شدیم، ولی تو این بخش میخوام عمیق‌تر شیرجه‌ بزنیم تو ایمِج‌ها و ببینیم اصلا ایمِج‌های داکر چی هستن… کاری که انجام دادیم این بود که ایمِج busybox رو از رجیستری دریافت یا pull کردیم، و به داکر گفتیم که یه کانتینر مبتنی بر اون ایمِج برامون بسازه. اول بیاید یه لیستی از ایمِج‌هامون رو بگیریم:$ docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
nexus.ida-analytics.de/ida/moira     latest              e3503776559a        7 days ago          387MB
nexus.ida-analytics.de/ida/grafana   latest              a1192aa71c7f        7 days ago          387MB
nexus.ida-analytics.de/ida/grafana                 6145fb02ee49        7 days ago          387MB
nexus.ida-analytics.de/ida/moira                   1323d422a434        7 days ago          387MB
busybox                              latest              8c811b4aec35        7 weeks ago         1.15MB
prakhar1989/static-site              latest              f01030e1dcf3        2 years ago         134MB این لیست، لیست همه‌ی ایمِج‌هایی هست که من روی این سیستمم نصب دارم و از رجیستری‌های مختلف دریافت کردم. TAG به یک نسخه‌ی مشخص از ایمِج اشاره می‌کنه و IMAGE ID به آی‌دی منحصر به فرد اون ایمِج.برای سادگی فهم، ایمِج‌ها رو به چشم ریپازیتوری‌های گیت ببینید. ایمِج‌ها میتونن کامیت بشن و ورژن‌های مختلفی داشته باشن، در حالت عادی هم، داکر نسخه latest رو دریافت میکنه که مشابه شاخه یا branch اصلی یا main تو گیت هست. مثلا میخوایم یه نسخه از اوبونتو رو دریافت کنیم:$ docker pull ubuntu:12.04برای اینکه از یه ایمِج استفاده کنید، یا میتونید اون رو از رجیستری داکر یا همون داکر هاب دریافت کنید یا یه ایمِج برای خودتون بسازید.مهم‌ترین چیزی که باید موقع انتخاب ایمِج‌ها تو ذهن داشته باشید، تفاوت بین ایمِج‌های پایه یا base و ایمِج‌های مبتنی یا child هستن:ایمِج‌های پایه یا Base images: ایمِج‌هایی هستند که بر هیچ ایمِج دیگه‌ای مبتنی نیستن، که معمولا (و نه همیشه) سیستم‌عامل هستن، وایمِج‌های مبتنی یا Child images: که مشخصا مبتنی بر ایمج‌های پایه هستن.و دو جور ایمِج رسمی و عیر رسمی هم داریم:ایمِج رسمی یا Official image: که توسط خود گروه داکر پشتیبانی و نگهداری میشن. معمولا تک‌کلمه‌ای هستن مثل ubuntu، busybox و hello-world. وایمِج‌های عیر رسمی یا Unofficial image: که توسط کاربرهایی مثل من و شما ساخته میشن و بر اساس ایمِج‌های اصلی هستن که معمولا شکل نمایششون user-name/image-name هست.اولین ایمِج ماحالا که درک بهتری از ایمِح‌های داکر داریم، وقتش شده که یه ایمِج برای خودمون بسازیم. برای اینکار، یه برنامه‌ی ساخته شده با ری‌اکت‌جی‌اس رو اصطلاحا داکرایز یا Dockerize میکنیم:$ npm i -g create-react-appاول که باید نصاب ری‌اکت رو نصب کنیم، و بعد پروژه رو میسازیم:$ create-react-app our-awesome-app
$ cd our-awesome-appاز اینجا به بعد هر کار خواستید با پروژه بکنید… اما در نهایت یه فایل به اسم Dockerfile تو پوشه‌ی اصلی پروژه بسازید و اون رو بازش کنید و محتوای زیر رو بهش اضافه کنید:FROM node:9.6.1

RUN mkdir /usr/src/app
WORKDIR /usr/src/app

ENV PATH /usr/src/app/node_modules/.bin:$PATH

COPY package.json /usr/src/app/package.json
RUN npm i --silent
RUN npm i react-scripts -g --silent

CMD \[&quot;npm&quot;, &quot;start&quot;\]و یه فایل .dockerignore بسازید (به . اول اسمش دقت کنید) و توش محتوای زیر رو بریزید:node_modulesو در نهایت ایمِج رو بسازید:$ docker build -t our-awesome-app .
...
Successfully built 8ab82c09e422
Successfully tagged our-awesome-app:latestو بعد از اتمام ساخت، کانتینر مربوط به ایمِجتون رو ایجاد و اجرا کنید:$ docker run -it \
  -v ${PWD}:/usr/src/app \
  -v /usr/src/app/node_modules \
  -p 3000:3000 \
  --rm \
  our-awesome-appبه همین سادگی! شما پروژتون رو داکرایز کردید :) حالا میتونید http://localhost:3000 رو باز کنید و ببینید پروژتون رو.داکر کامپُز (Docker Compose)تا اینجا با خود داکر سر و کله زدیم و تا حدودی اکوسیستمش رو شناختیم. منتهی همچنان ابزارهایی هستند که یادگیریشون برامون خیلی پر کاربرد خواهد بود. چندتا از این ابزارهای خوب:Docker Machine که کمک میکنه هاست‌های داکر روی کامپیوترتون، کلاد یا فضاهای ابری و حتی دیتا‌سنترتون بسازید،Docker Compose ابزاری برای ساخت اپلیکیشن‌های چند کانتینری داکر (چندتا کانتینر رو در کنار هم قرار میده) وDocker Swarm که ابزاری برای ساخت کلاسترها یا خوشه‌های کانتینریه.تو این بخش میخوایم بریم سراغ داکر کامپُز و ببینیم که چطور میشه اپلیکیشن‌های داکر مبتنی بر چند کانتینر ساخت.اینطور فرض کنید که یه کانتینر مسئول اجرای کدهای PHP، Go، JavaScript و زبان‌های دیگست، یه کانتینر دیتابیس MySql و MongoDb رو داره، یه کانتینر وب‌سرور Apache یا NginX و…گذشته‌ی داکر کامپُز جالبه، تقریبا چهار سال پیش (سال ۲۰۱۴) شرکتی به اسم OrchardUp ابزاری رو به اسم Fig به بازار عرضه کرد. هدف از ساخت Fig این بود که بشه محیط برنامه‌نویسی یا Development Environment مبتنی بر داکر ساخت و اونها رو ایزوله کرد، تا فضای کاری برنامه‌نویس‌ها مشابه به هم بشه.تا اینجا، داکر یه ابزاری بود برای ساخت پروسه‌ها یا Application Processes. بعد از این، داکر APIهای مختلفی رو ارائه داد که بشه پوشه‌ها رو بین کانتینرها به اشتراک گذاشت و پورتی رو از هاست به کانتینر فوروارد کرد، لاگ‌ها رو نمایش داد و غیره. ولی با همه‌ی اینها، داکر فقط یه چیز بود: ابزاری برای ساخت پروسه‌ها!با اینکه داکر این امکان رو میده تا بشه کانتینرهای مختلف رو با هم اورکِسترِیت یا Orchestrate کرد (به زبان ساده یعنی هماهنگی بینشون ایجاد کرد تا منظم و درست کار کنن)، همچنان با این کانتینرها به شکل «یک موجودیت» یا Single Entity برخورد نمیکنه. یعنی مهندس نرم‌افزار باید همه‌چیز رو خودش مدیریت کنه. اینجاست که حضور ابزاری مثل Fig خیلی بدرد خورد! از این به بعد مهندسین باید به این شکل بهش نگاه میکردن: «یک برنامه‌ی داکر رو اجرا کنیم که کلاستری از کانتینرها رو مدیریت میکنه» و نه اینکه صرفا یه کانتینر رو اجرا کنیم.مشخص شد که خیلی از بروبچه‌ها و مهندسینی که از داکر استفاده میکردن با این تعریف موافق بودن. برای همین هم وقتی که Fig در حال محبوب شدن بود، شرکت داکر اون رو خرید و اسمش رو به Docker Compose تغییر داد.خب، حالا اصلا کامپُز برای چی استفاده میشه؟ کامپُز یه ابزاره که کمک میکنه برنامه‌هایی رو با چند کانتینر اورکستریت کنیم. این ابزاری فایلی رو ایجاد میکنه به اسم docker-compose.yml که کل دستوراتی رو که لازم هست رو در خودش داره و اونها رو فقط با یه دستور اجرا میکنه.بذارید با هم برنامه‌ای رو که بالاتر با داکر ساختیم، اینبار با داکر کامپُز اجرا کنیم. برای اینکار فایل docker-compose.yml تو پوشه‌ی اصلی برنامه بسازید و محتوای زیر رو توش قرار بدید:version: &#039;3.5&#039;

services:

  our-awesome-app:
    container_name: our-awesome-app
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      \- &#039;.:/usr/src/app&#039;
      \- &#039;/usr/src/app/node_modules&#039;
    ports:
      \- &#039;3000:3000&#039;
    environment:
      \- NODE_ENV=developmentحالا کامپُز رو نصب کنیم…بعد از نصب کامپُز، دستور زیر رو اجرا کنید:$ docker-compose up -d --buildساختار داکر کامپُزاصلی‌ترین دلیل ساخت داکر کامپُز، ایجاد برنامه‌ها بر اساس معماری مایکروسرویس بود، یا درواقع کانتینرها و روابط بینشون. اما داکر کامپًز ویژگی‌های دیگه‌ای هم داره:ساخت یک ایمِج داکر (درصورتی که یک فایل Dockerfile معتبر تو پوشه‌ی اصلی موجود باشه) با دستور:docker-compose buildمقیاس‌بندی کانتینرها با دستور:docker-compose scale SERVICE=3نجات‌دادن یا درواقع اجرای مجدد کانتینرها در صورت پَنیک با دستور:docker-compose up --no-recreateیکی از مهم‌ترین دستورات داکر کامپُز، docker-compose up هست که اول دستور docker-compose build و بعد docker-compose run رو اجرا می‌کنه.جریان کار یا Workflow در داکر کامپُزجریان کار تو داکر کامپُز سادست:هر سرویس رو تو یه داکر فایل تعریف می‌کنیم (یک روش)،سرویس‌ها و روابطشون رو تو فایل docker-dompose.yml تعریف می‌کنیم ودستور docker-compose up رو اجرا می‌کنیم تا سیستم بالا بیاد.اما برای اینکه بهتر متوجه بشیم، میریم که چندتا اپ مختلف بسازیم تا روش‌ها دیگه برای استفاده از داکر کامپُز رو یاد بگیریمادامه‌ی مطلب رو میتونید از سایت خودم بخونید…</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Mon, 23 Jul 2018 16:01:42 +0430</pubDate>
            </item>
                    <item>
                <title>داکر، کانتینر و اتوماسیون</title>
                <link>https://virgool.io/cheyab-blog/%D8%AF%D8%A7%DA%A9%D8%B1-%DA%A9%D8%A7%D9%86%D8%AA%DB%8C%D9%86%D8%B1-%D9%88-%D8%A7%D8%AA%D9%88%D9%85%D8%A7%D8%B3%DB%8C%D9%88%D9%86-b1mi525hzvoe</link>
                <description>مقدمهبالاخره بعد از یه مدت طولانی که از داون شدن سایتم میگذره، تونستم دوباره وصلش کنم و کانفیگای سمت سرور رو دوباره فیکس کنم. شاید جالب باشه ولی سرور من جای خلوتیه و چیز زیادی توش نیست و وب‌سایت خودم تنها برنامه‌ایه که توش اجرا میشه، اما نکته‌ی جالب اینه که موقع دیپلوی باهاش خیلی مشکل دارم. بگذریم، همین مشکلات باعث شد که به نوشتن این مطلب فکر کنم و تا جایی که میتونم در مورد داکر توضیح بدم.خواهش من مثل همیشه، انه که ان مطلب رو بخونید، ازش لذت ببرید و برای دوستاتون هم بفرستید و اگر جایی اشکالی دیدید، بهم خبر بدید. ضمنا، حقوق نویسنده رو هم فراموش نکنید و اگر جایی از این مطلب استفاده میکنید، اسم نویسنده اصلی (من، آیین) رو توش درج کنید.سپاسداکر (Docker) چی هست؟اول از همه، داکر اسم شرکتی هست که واژه کانتِینِر یا Container رو روانه‌ی دنیای آی‌تی کرده. البته که قبلا هم از این واژه استفاده‌های گسترده‌ای میشده، اما داکر باعث شده که واژه کانتِینِر معنی مشخص‌تر و دقیق‌تری پیدا کنه.خود نرم‌افزار داکر، یه سرویس برای مدیریت کانتینرها یا Container Service Manager هست. کلیدواژه‌هایی که میشه برای داکر استفاده کرد، توسعه‌دادن، دیپلوی کردن و اجرا کردن هستن. در واقع داکر هدفش اینه که وقتی برنامه‌نویس‌ها، نرم‌افزاری رو می‌نویسن، اون رو به کانتینرها منتقل و به سادگی اون رو هر جایی اجرا کنن.پلتفرم (سَکو؟!) کانتینر چی هست؟پلتفرم کانتینر یا Container Platform یه سرویس کامل برای سازمان‌ها و شرکت‌هاست که بتونن باهاش مشکلات مختلفی رو حل کنن. مهمترین ویژگی کانتینرها اینه که تمام نرم‌افزارهایی که برنامه لازم داره رو، توی خودشون نگه‌میدارن. اما یکم در مورد کانتینرها عمیق بشم...کانتینر یه پراسِس (Process) داکر هست که فقط روی لینوکس یا ویندوز اجرا میشه (ظاهرا برای مک هم هست ولی من جایی ندیدم) و داخل خودش هرچیزی که برای اجرا شدن نیاز داشته‌باشه رو داره. در واقع یه کانتینر یکمی شبیه به ماشین‌مجازی یا Virtual Machine هست با این تفاوت که هسته‌ی سیستم‌عامل میزبان یا Host رو به اشتراک میذاره.عکس بالا، اساسی‌ترین تفاوت کانتینرها با ماشین‌های مجازی رو نشون میده. چارت سمت راست کانتینر و سمت چپ، ماشین مجازی. زیر ساخت‌ها یا Infrastructures شبیه به هم، داکر از سیستم‌عامل میزبان و ماشین مجازی از Hypervisor که یه لایه هست تا برنامه‌های مورد نیاز سیستم‌عامل داخل ماشین رو فراهم کنه، استفاده میکنه. تو ماشین مجازی شما به یه سیستم‌عامل مهمان احتیاج دارید، مثلا توی سیستم‌عامل لینوکستون، ویندوز نصب میکنید، اما داکر اینطور نیست و از موتور خودش استفاده میکنه تا با سیستم‌عامل میزبان ارتباط برقرار کنه. تو ماشین مجازی شما سیستم‌عامل رو نصب میکنید که برنامه‌های لازم رو بتونید فراهم کنید. این قدم تو کانتینر از بین رفته (و دقیقا چیزیه که سرعت کانتینر رو به نسبت ماشین‌مجازی خیلی بیشتر می‌کنه). در نهایت کتابخونه‌ها و برنامه‌های لازم اجرا میشن و شما میتونید سیستمتون رو بالا بیارید.این رو اضافه میکنم، فرض کنید داکر همون نرم‌افزار Oracle VirtualBox یا VMWare هست و کانتینرها، همون سیستم‌عامل‌هایی که توشون نصب می‌کنیم.Containerization vs Virtualizationقبل از اینکه وارد این مبحث بشم، یه نگاهی به ترمینولوژی داکر داشته باشیم:موتور داکر یا Docker Engineقسمتی از داکر که وظیفه‌ی ایجاد و اجرای کانتینرها رو دارههاب داکر یا Docker Hubسرویسی از داکر برای به اشتراک‌گذاری کانتینرها با دیگرانداکر کامپوز یا Docker Composeابزاری که باهاش برنامه‌های چند کانتینری تعریف میکنیم. این ابزار از فایلهای Yaml استفاده میکنه تا فایل‌ها و تنظیمات رو کانفیگ کنه و کانتینر رو آماده اجرا کنه.در کل استفاده از این ابزار سه مرحله داره:محیط برنامه رو با یه Dockerfile تعریف میکنیم تا همه‌جا بشه ازش استفاده کرد.سرویس‌هایی که لازم هست برای اجرای این کانتینر رو تو فایل docker-compose.yml میذاریم تا با فایل Dockerfile یه جا اجرا بشن.دستور docker-compuse up رو اجرا میکنیم و تموم میشه!داکر ایمِج یا Docker Imageتو داکر، همه‌چیز بر اساس ایمِج‌ها ساخته شده!داکر فایل یا Docker fileدستوراتی که برای ساخت ایمِج لازم هست اینجا تعریف میشه.حالا کانتِینِریزِیشن در مقابل ویرچوالیزِیشن یا مجازی‌سازی چی هست؟هرچه‌قدر که زمان میگذره، تکنولوژی داکر بین حرفه‌ای‌های IT محبوبیت بیشتری پیدا می‌کنه، که باعث میشه برای برنامه‌نویس‌ها دونستن حداقل مبانی کانتینر‌ها به یک «باید» تبدیل بشه.صنعت IT هرروز درحال تغییر و پیشرفته و «سرعت و بهینه‌سازی» تبدیل به اساس این صنعت شدن. تکنولوژی‌ها سعی کردن روش‌های بهتری رو برای اتوماسیون ارائه بدن تا پروسه ساخت و تولید برنامه‌ها روراحتتر و سریع‌تر کنن.نمیدونم که آیا با Industry 4.0 آشنایی دارید یا نه، اما مجازی‌سازی یا ویرچوالیزیشن (Virtualization) سعی کرده تا این نسخه از صنعت IT رو بهینه‌تر و قابل‌حمل‌تر یا Portable کنه. با این‌حال، تکنولوژی مجازی‌سازی نقاط ضعف جدی رو داره، مثل کاهش محسوس پرفورمنس نرم‌افزارها که بخاطر وزن زیاد و ساختار سنگین VMها یا Virtual Machineها اتفاق میوفته. یا مثلا غیرقابل حمل بودن برنامه‌ها و کارایی پایین در مدیریت منابع سیستم و چیزهای دیگه از این دسته.اینجاست که صنعت IT رفته سراغ تکنولوژی داکر و کانتینریزیشن! دقیق‌تر میگم، موتور داکر برای کانتینریزیشن ساخته شده که مراحل بسته‌بندی، حمل و گسترش برنامه‌ها رو بسیار ساده کرده. شکافت هسته‌ی اتم!برای یادگیری و راه‌اندازی داکر، نیازی نیست فیزیک کوانتوم بلد باشید یا بتونید حداقل یکی از سوالای میلنیوم ریاضی رو حل کنید! فقط کافیه یکمی با محیط ترمینال و cli دوست باشید و یک تکست‌ادیتور هم کنار دستتون باشه، و خب قطعا داشتن یکمی دانش برنامه‌نویسی هم میتونه به کارتون بیاد! نصب و راه‌اندازی داکرگرفتن تمام ابزارهای مورد نیازتون برای داکر میتونه کمی خسته‌کننده به نظر برسه. اما توصیه‌ی من اینه که قبل از نصب داکر، حتما نرم‌افزار vscode رو دانلود کنید و در نهایت داکر رو برای سیستم‌عامل خودتون دریافت کنید.بعد از نصب داکر، دستور زیر رو اجرا کنید تا مطمئن بشیم همه‌چیز درست انجام شده:$ docker run hello-worldکه در پاسخش باید نتیجه‌ی زیر رو دریافت کنید:Hello from Docker.
This message shows that your installation appears to be working correctly.
...بازی با BusyBoxحالا که داکر نصب شده، بریم و یکم دستامون رو کثیف کنیم. برای اینکار یه کانتینر BusyBox (یه نرم‌افزار که یسری از ابزارهای Unix رو توی یه فایل به شما میده) رو نصب میکنیم تا طعم دستور  docker run رو بچشیم.برای شروع، دستور زیر رو اجرا کنید:$ docker pull busyboxدقت داشته باشید که ممکن هست به ارور  permission denied برخورد کنید. بهترین راه اینه که خودتون رو توی گروه docker اضافه کنید تا ازش پیشگری بشه.دستور  pull ایمِج BusyBox رو از رجیستری داکر (Docker Registry) یا همون داکرهاب (Docker Hub) دریافت و اون روی روی سیستممون ذخیره میکنه. ضمنا شما میتونید دستور  docker images رو اجرا کنید تا ببینید چه ایمِج‌هایی روی سیستمتون نصب شدن.REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
nexus.ida-analytics.de/ida/moira     latest              e3503776559a        6 days ago          387MB
nexus.ida-analytics.de/ida/grafana   latest              a1192aa71c7f        7 days ago          387MB
nexus.ida-analytics.de/ida/grafana                 6145fb02ee49        7 days ago          387MB
nexus.ida-analytics.de/ida/moira                   1323d422a434        7 days ago          387MB
busybox                              latest              8c811b4aec35        7 weeks ago         1.15MB
Docker Runعالی شد! حالا وقتش شده که یه کانتینر داکر، مبتنی بر ایمِجی که گرفتیم رو اجرا کنیم. برای اینکار از دستور زیر استفاده میکنیم:$ docker run busybox
$چی شد؟! چرا هیچ اتفاقی رخ نداد؟! خب، واقعیت اینه که کلی اتفاقات اینجا افتاده که با چشم غیر مسلح قابل رویت نیست :دی. وقتی که شما دستور  run رو صدا میزنید، داکر ایمِجی که گفتید رو پیدا میکنه (اینجا میشه Busybox)، یه کانتینر براش میسازه و یه دستور رو توی کانتینر اجرا میکنه. اگر دقت کنید، تو دستور  docker run busybox ما هیچ دستور اضافی رو فراهم نکردیم. بنابراین کانتینر ساخته شده، بالا اومده، یه دستور خالی رو اجرا کرده و خارج شده.دستور بالا رو میشه اینطور هم نوشت:$ docker run busybox echo &quot;Salam Donya!!&quot;
Salam Donya!!اینجا داکر، دستور  echo رو اجرا کرده و در نهایت بسته شده. حالا فکر کنید میخواستید همه‌ی اینا رو با ماشین‌مجازی اجرا کنید! چقدر باید صبر می‌کردید؟حالا وقتش شده که دستور  docker ps رو اجرا کنیم.$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMESاز اونجایی که هیچ کانتینری در حال اجرا نیست، ما هم یه لیست خالی رو دریافت کردیم. حالا یکم دستور رو دقیق‌تر میکنیم:$ docker ps -a
CONTAINER ID        IMAGE                                       COMMAND                CREATED             STATUS                      PORTS               NAMES
2059d101f971        busybox                                     &quot;echo Hallo&quot;           15 minutes ago      Exited (0) 15 minutes ago                       hopeful_nightingale
45f36d883bd4        busybox                                     &quot;sh&quot;                   15 minutes ago      Exited (0) 15 minutes ago                       kind_mcnulty
375b34dfa64c        nexus.ida-analytics.de/ida/moira:latest     &quot;/bin/moira&quot;           6 days ago          Exited (137) 6 days ago                         moira
45ba50ce36f9        nexus.ida-analytics.de/ida/grafana:latest   &quot;/bin/start_grafana&quot;   6 days ago          Exited (0) 6 days ago                           grafanaهمون‌طور که مشخصه، پارامتر  -a دستور داده که لیست تمام کانتینرها، فاقد از وضعیتشون (که اینجا exited هست) برگردونده بشه.شاید براتون سوال بشه که چطور میشه دستورات بیشتری رو توی کانتینر اجرا کرد؟ خیلی آسون. اگر با دستور  ssh آشنایی داشته باشید، میخوایم اینجا یه کاری مشابه اون رو انجام بدیم:$ docker run -it busybox sh
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # pwd
/
/ # uptime
 22:30:58 up  3:26,  0 users,  load average: 1.54, 1.46, 1.48
/ #اجرا کردن دستور  run با پارامتر -it باعث میشه که ما به داخل کانتینر (در واقع با ساخت یه سِشِن tty) بریم و دستوراتی که میخوایم رو اونجا اجرا کنیم.قبل از اینکه به مرحله‌ی بعدی برم، بهتون این نکته رو هم میگم که چطور میشه کانتینرها رو حذف کرد. بالاتر دیدیم که با اجرا کردن دستور  docker ps -a میتونیم لیست تمام کانتینرهامون رو بدست بیاریم. برای حذف یه کانتینر کافیه که  CONTAINER ID او کانتینر رو برداریم و بعد دستور docker rm CONTAINER_ID رو اجرا کنیم. که در پاسخش باید آی‌دی کانتینر دوباره به شما نمایش داده بشه.دستور زیر هم هست:$ docker rm $(docker ps -a -q -f status=exited)اجرا کردن این دستور، تمام کانتینرهایی که وضعیت exited دارن رو پاک میکنه.وب‌اَپ تو داکرتا اینجا فهمیدیم که دستور  docker run تا حدودی چطور کار میکنه، همزمان یکمی هم با کانتینرها بازی کردیم و با ترمینولوژی داکر بیشتر آشنا شدیم. حالا وقتش شده که بریم سراغ مسائل اساسی، و ببینیم که چطور میشه یه وب‌اَپ رو تو داکر دیپلوی یا Deploy کرد.سایت‌های استاتیکبذارید قدم‌های کوچک برداریم. اولین چیزی که میریم سراغش، دیپلوی کردن یه سایت استاتیک خیلی ساده هست. یه ایمِج رو از داکر‌هاب دریافت یا pull میکنیم و اجراش میکنیم تا ببینیم چقدر راه‌اندازی سایت‌های استاتیک کار آسونیه.ایمِجی که برای اینکار استفاده میکنیم، یه ایمِج از قبل آماده شدست:$ docker run prakhar1989/static-siteاز اونجایی که این ایمِج به صورت لوکال یا محلی تو سیستم ما نیست، داکر اون رو از رجیستری دریافت میکنه و بعد ایمِج رو اجرا میکنه. اگر همه‌چیز خوب پیش بره، شما پیام  Nginx is running... رو خواهید دید. حالا که سرور راه‌افتاده، چطور میشه بهش دسترسی داشت؟ چطوری میشه فهمید تو چه پورتی اجرا شده؟خب تو این حالت، داکر هیچ پورتی رو نمایش یا اصطلاحا اِکسپوز (Expose) نمیکنه، برای همین لازم هست که مجددا دستور  docker run رو اجرا کنیم تا پورت‌ها رو نمایش بدیم. همزمان هم باید کاری کنیم که ترمینال روی این حالت قفل نشه و ما بتونیم از ترمینال، بدون بستن سرور خارج بشیم. به این حالت میگن Detached Mode یا حالت جدا شده!$ docker run -d -P --name static-site prakhar1989/static-site
531b38e65151ba7ee133aff085d4c3e31d9ab349d0fed2b48b91cf28d53ca685تو دستور بالا،  -d حالت detached mode رو اجرا و -P پورت‌هارو باز میکنه. --name هم اسمی رو برای کانتینر درنظر میگیره. حالا میتونیم پورت‌های باز شده رو پیدا کنیم:$ docker port static-site
443/tcp -&gt; 0.0.0.0:32768
80/tcp -&gt; 0.0.0.0:32769حالا، http://localhost:32769 رو باز کنید و نتیجه رو ببینید.?همچنین میتونید یه آدرس پورت دلخواه هم به ایمِجتون بدید:$ docker run -p 8888:80 prakhar1989/static-site
Nginx is running...این دستور میگه که: به پورت ۸۸۸۸ سیستم هاست یا میزبان، هرچیزی که تو پورت ۸۰ ایمِج بود رو اختصاص بده. برای اینکه کانتینر رو متوقف کنید، دستور  docker stop رو به همراه آی‌دی کانتینر اجرا کنید.مطمئن هستم که شما هم موافقید این کار واقعا آسون بود! فکر کنید شما یه سرور دارید و میخواید سایتتون رو روش راه‌اندازی کنید، کل کار اینه که داکر رو نصب کنید و دستورات بالا رو وارد کنید!ولی خب، این برای ما کافی نیست، چون ما دوست داریم بیشتر بدونیم :) برای همین باید یاد بگیریم چطور داکر ایمِج خودمون رو بسازیم...داکر ایمِج‌هاما با ایمِج‌ها تا حدودی آشنا شدیم، ولی تو این بخش میخوام عمیق‌تر شیرجه‌ بزنیم تو ایمِج‌ها و ببینیم اصلا ایمِج‌های داکر چی هستن... کاری که انجام دادیم این بود که ایمِج busybox رو از رجیستری دریافت یا pull کردیم، و به داکر گفتیم که یه کانتینر مبتنی بر اون ایمِج برامون بسازه. اول بیاید یه لیستی از ایمِج‌هامون رو بگیریم:$ docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
nexus.ida-analytics.de/ida/moira     latest              e3503776559a        7 days ago          387MB
nexus.ida-analytics.de/ida/grafana   latest              a1192aa71c7f        7 days ago          387MB
nexus.ida-analytics.de/ida/grafana                 6145fb02ee49        7 days ago          387MB
nexus.ida-analytics.de/ida/moira                   1323d422a434        7 days ago          387MB
busybox                              latest              8c811b4aec35        7 weeks ago         1.15MB
prakhar1989/static-site              latest              f01030e1dcf3        2 years ago         134MB
این لیست، لیست همه‌ی ایمِج‌هایی هست که من روی این سیستمم نصب دارم و از رجیستری‌های مختلف دریافت کردم. TAG به یک نسخه‌ی مشخص از ایمِج اشاره می‌کنه و IMAGE ID به آی‌دی منحصر به فرد اون ایمِج.برای سادگی فهم، ایمِج‌ها رو به چشم ریپازیتوری‌های گیت ببینید. ایمِج‌ها میتونن کامیت بشن و ورژن‌های مختلفی داشته باشن، در حالت عادی هم، داکر نسخه latest رو دریافت میکنه که مشابه شاخه یا branch اصلی یا main تو گیت هست. مثلا میخوایم یه نسخه از اوبونتو رو دریافت کنیم:$ docker pull ubuntu:12.04برای اینکه از یه ایمِج استفاده کنید، یا میتونید اون رو از رجیستری داکر یا همون داکر هاب دریافت کنید یا یه ایمِج برای خودتون بسازید.مهم‌ترین چیزی که باید موقع انتخاب ایمِج‌ها تو ذهن داشته باشید، تفاوت بین ایمِج‌های پایه یا base و ایمِج‌های مبتنی یا child هستن:ایمِج‌های پایه یا Base images: ایمِج‌هایی هستند که بر هیچ ایمِج دیگه‌ای مبتنی نیستن، که معمولا (و نه همیشه) سیستم‌عامل هستن، وایمِج‌های مبتنی یا Child images: که مشخصا مبتنی بر ایمج‌های پایه هستن.و دو جور ایمِج رسمی و عیر رسمی هم داریم:ایمِج رسمی یا Official image: که توسط خود گروه داکر پشتیبانی و نگهداری میشن. معمولا تک‌کلمه‌ای هستن مثل ubuntu، busybox و hello-world. وایمِج‌های عیر رسمی یا Unofficial image: که توسط کاربرهایی مثل من و شما ساخته میشن و بر اساس ایمِج‌های اصلی هستن که معمولا شکل نمایششون  user-name/image-name هست.اولین ایمِج ماحالا که درک بهتری از ایمِح‌های داکر داریم، وقتش شده که یه ایمِج برای خودمون بسازیم. برای اینکار، یه برنامه‌ی ساخته شده با ری‌اکت‌جی‌اس رو اصطلاحا داکرایز یا Dockerize میکنیم:$ npm i -g create-react-appاول که باید نصاب ری‌اکت رو نصب کنیم، و بعد پروژه رو میسازیم:$ create-react-app our-awesome-app
$ cd our-awesome-appاز اینجا به بعد هر کار خواستید با پروژه بکنید... اما در نهایت یه فایل به اسم  Dockerfile تو پوشه‌ی اصلی پروژه بسازید و اون رو بازش کنید و محتوای زیر رو بهش اضافه کنید:FROM node:9.6.1

RUN mkdir /usr/src/app
WORKDIR /usr/src/app

ENV PATH /usr/src/app/node_modules/.bin:$PATH

COPY package.json /usr/src/app/package.json
RUN npm i --silent
RUN npm i react-scripts -g --silent

CMD [&quot;npm&quot;, &quot;start&quot;]و یه فایل  .dockerignore بسازید (به . اول اسمش دقت کنید) و توش محتوای زیر رو بریزید:node_modulesو در نهایت ایمِج رو بسازید:$ docker build -t our-awesome-app .
...
Successfully built 8ab82c09e422
Successfully tagged our-awesome-app:latestو بعد از اتمام ساخت، کانتینر مربوط به ایمِجتون رو ایجاد و اجرا کنید:$ docker run -it \
  -v ${PWD}:/usr/src/app \
  -v /usr/src/app/node_modules \
  -p 3000:3000 \
  --rm \
  our-awesome-appبه همین سادگی! شما پروژتون رو داکرایز کردید :) حالا میتونید http://localhost:3000 رو باز کنید و ببینید پروژتون رو.داکر کامپُز (Docker Compose)تا اینجا با خود داکر سر و کله زدیم و تا حدودی اکوسیستمش رو شناختیم. منتهی همچنان ابزارهایی هستند که یادگیریشون برامون خیلی پر کاربرد خواهد بود. چندتا از این ابزارهای خوب:Docker Machine که کمک میکنه هاست‌های داکر روی کامپیوترتون، کلاد یا فضاهای ابری و حتی دیتا‌سنترتون بسازید،Docker Compose ابزاری برای ساخت اپلیکیشن‌های چند کانتینری داکر (چندتا کانتینر رو در کنار هم قرار میده) وDocker Swarm که ابزاری برای ساخت کلاسترها یا خوشه‌های کانتینریه.تو این بخش میخوایم بریم سراغ داکر کامپُز و ببینیم که چطور میشه اپلیکیشن‌های داکر مبتنی بر چند کانتینر ساخت.اینطور فرض کنید که یه کانتینر مسئول اجرای کدهای PHP، Go، JavaScript و زبان‌های دیگست، یه کانتینر دیتابیس MySql و MongoDb رو داره، یه کانتینر وب‌سرور Apache یا NginX و...گذشته‌ی داکر کامپُز جالبه، تقریبا چهار سال پیش (سال ۲۰۱۴) شرکتی به اسم OrchardUp ابزاری رو به اسم Fig به بازار عرضه کرد. هدف از ساخت Fig این بود که بشه محیط برنامه‌نویسی یا Development Environment مبتنی بر داکر ساخت و اونها رو ایزوله کرد، تا فضای کاری برنامه‌نویس‌ها مشابه به هم بشه.تا اینجا، داکر یه ابزاری بود برای ساخت پروسه‌ها یا Application Processes. بعد از این، داکر APIهای مختلفی رو ارائه داد که بشه پوشه‌ها رو بین کانتینرها به اشتراک گذاشت و پورتی رو از هاست به کانتینر فوروارد کرد، لاگ‌ها رو نمایش داد و غیره. ولی با همه‌ی اینها، داکر فقط یه چیز بود: ابزاری برای ساخت پروسه‌ها!با اینکه داکر این امکان رو میده تا بشه کانتینرهای مختلف رو با هم اورکِسترِیت یا Orchestrate کرد (به زبان ساده یعنی هماهنگی بینشون ایجاد کرد تا منظم و درست کار کنن)، همچنان با این کانتینرها به شکل «یک موجودیت» یا Single Entity برخورد نمیکنه. یعنی مهندس نرم‌افزار باید همه‌چیز رو خودش مدیریت کنه. اینجاست که حضور ابزاری مثل Fig خیلی بدرد خورد! از این به بعد مهندسین باید به این شکل بهش نگاه میکردن: «یک برنامه‌ی داکر رو اجرا کنیم که کلاستری از کانتینرها رو مدیریت میکنه» و نه اینکه صرفا یه کانتینر رو اجرا کنیم.مشخص شد که خیلی از بروبچه‌ها و مهندسینی که از داکر استفاده میکردن با این تعریف موافق بودن. برای همین هم وقتی که Fig در حال محبوب شدن بود، شرکت داکر اون رو خرید و اسمش رو به Docker Compose تغییر داد.خب، حالا اصلا کامپُز برای چی استفاده میشه؟ کامپُز یه ابزاره که کمک میکنه برنامه‌هایی رو با چند کانتینر اورکستریت کنیم. این ابزاری فایلی رو ایجاد میکنه به اسم  docker-compose.yml که کل دستوراتی رو که لازم هست رو در خودش داره و اونها رو فقط با یه دستور اجرا میکنه.بذارید با هم برنامه‌ای رو که بالاتر با داکر ساختیم، اینبار با داکر کامپُز اجرا کنیم. برای اینکار فایل  docker-compose.yml تو پوشه‌ی اصلی برنامه بسازید و محتوای زیر رو توش قرار بدید:version: &#039;3.5&#039;

services:

  our-awesome-app:
    container_name: our-awesome-app
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - &#039;.:/usr/src/app&#039;
      - &#039;/usr/src/app/node_modules&#039;
    ports:
      - &#039;3000:3000&#039;
    environment:
      - NODE_ENV=developmentحالا کامپُز رو نصب کنیم... بعد از نصب کامپُز، دستور زیر رو اجرا کنید:$ docker-compose up -d --buildساختار داکر کامپُزاصلی‌ترین دلیل ساخت داکر کامپُز، ایجاد برنامه‌ها بر اساس معماری مایکروسرویس بود، یا درواقع کانتینرها و روابط بینشون. اما داکر کامپًز ویژگی‌های دیگه‌ای هم داره:ساخت یک ایمِج داکر (درصورتی که یک فایل Dockerfile معتبر تو پوشه‌ی اصلی موجود باشه) با دستور: docker-compose buildمقیاس‌بندی کانتینرها با دستور:docker-compose scale SERVICE=3نجات‌دادن یا درواقع اجرای مجدد کانتینرها در صورت پَنیک با دستور:docker-compose up --no-recreateیکی از مهم‌ترین دستورات داکر کامپُز،  docker-compose up هست که اول دستور docker-compose build و بعد docker-compose run رو اجرا می‌کنه.جریان کار یا Workflow در داکر کامپُزجریان کار تو داکر کامپُز سادست:هر سرویس رو تو یه داکر فایل تعریف می‌کنیم (یک روش)،سرویس‌ها و روابطشون رو تو فایل  docker-dompose.yml تعریف می‌کنیم و دستور  docker-compose up رو اجرا می‌کنیم تا سیستم بالا بیاد.اما برای اینکه بهتر متوجه بشیم، میریم که چندتا اپ مختلف بسازیم تا روش‌ها دیگه برای استفاده از داکر کامپُز رو یاد بگیریمادامه‌ی مطلب رو میتونید از سایت خودم بخونید... https://www.saidi27.com/blog/%D8%AF%D8%A7%DA%A9%D8%B1-%DA%A9%D8%A7%D9%86%D8%AA%DB%8C%D9%86%D8%B1-%D9%88-%D8%A7%D8%AA%D9%88%D9%85%D8%A7%D8%B3%DB%8C%D9%88%D9%86 </description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Thu, 19 Jul 2018 22:35:13 +0430</pubDate>
            </item>
                    <item>
                <title>آشنایی با Symfony با ساختن یه وبلاگ به صورت پروژه ای</title>
                <link>https://virgool.io/pullrequest/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-symfony-%D8%A8%D8%A7-%D8%B3%D8%A7%D8%AE%D8%AA%D9%86-%DB%8C%D9%87-%D9%88%D8%A8%D9%84%D8%A7%DA%AF-%D8%A8%D9%87-%D8%B5%D9%88%D8%B1%D8%AA-%D9%BE%D8%B1%D9%88%DA%98%D9%87-%D8%A7%DB%8C-xkrvck3jrmcr</link>
                <description>eبین تعدا زیادی از تکنولوژی‌های وب که وجود دارن، پی‌اچ‌پی تو طول زمانی تغییرات سریعی رو پشت سر گذاشته و الان به یک زبان بالغ تبدیل شده.پی‌اچ‌پی امروز هم برای وب‌سایت‌ها و وب‌اپلیکیشن‌ها کوچیک و همینطور بزرگ استفاده میشه و شاید یکی از دلایل محبوبیتش، سادگیش باشه.با توجه به اینکه هرروز پیچیدگی وب‌اپلیکیشن‌ها بیشتر میشه، برنامه‌نویس‌ها بیشتر به استفاده از فریم‌ورک‌ها رو آوردن و حتی برای پروژه‌های کوچیکشون هم از اونا استفاده می‌کنن. شاید با خودتون بگید «فریم‌ورک چیه؟». فریم‌ورک‌ها اساسا چیزی بجز یکسری توابع و ساختاربندی‌های کلاسی نیستن که از قبل آماده شدن و قابل استفاده هستن، که مهمترین ویژگیشون اختراع نکردن چرخ از اول هست و این یعنی صرفه‌جویی زمان.تقریبا تمام زبان‌های برنامه‌نویسی برای خودشون فریم‌ورک‌هایی رو دارن که هرکدوم با هدفی ساخته شدن. یسری از فریم‌ورک‌های محبوب پی‌اچ‌پی، Zend Framework, Cake PHP, Smarty, Laravel و Symfony هستند، و من خودم بشخصه طرفدار سیمفونی هستم و دلایلش رو هم میگم. در نهایت سعی میکنم برای کسانی که دوست دارن با سیمفونی آشنا بشن، توضیحی از نحوه نصب و راه‌اندازی و کار مختصر باهاش رو توضیح بدم.انعطاف‌پذیریتو خیلی از پروژه‌هایی که کار کردم و دیدم، سیمفونی بهم ثابت کرد که خیلی زیاد انعطاف‌پذیره و یک انتخاب خوب برای کسب‌وکار. با قابلیت‌هایی مثل Dependency Injectorها یا Event Dispatcherها کاملا قابل تنظیم و شخصی‌سازی شده. سیمفونی یک ساختار OOP و SOA رو به صورت حرفه‌ای پیش برده که باعث شده برای کسایی که بخوان چه از ساختار Monolithic و چه از Micro Service بهره ببرن، گزینه‌ی مناسبی باشه، و این یعنی توسعه سریع، افزایش مقیاس پروژه و نگهداری راحت.برنامه‌نویس‌ها نیازی ندارن تا ویژگی‌های پایه و اساسی پروژه رو از اول بنویسن یا حتی بازنویسی کنن، مثل سرویس مدیرت فرم. سیمفونی برنامه‌نویس رو به چالش واقعی دعوت میکنه، محاسبات و مدیریت. بنظرم یکی از بهترین ویژگی‌های سیمفونی داشتن Web Debug Toolbar هست که حقیقتا یه دوست واقعی برای برنامه‌نویسه.ساختار تیکه تیکه! (باندل)بنظرم یکی از ویژگی‌های بسیار مثبت سیمفونی، ساختار تیکه تیکش هست. یعنی سیمفونی از اجزای کوچکتر ساخته شده که هرکدومشون جداگانه قابل استفاده هستن، یک نمونش HTTP Foundation که خیلی زیاد تو لاراول استفاده شده. در واقع خود سیمفونی، یک تیکه کوچیک از این تیکه‌هاست که در حقیقت وظیفش جمع کردن همه‌ی تیکه‌ها (اسم درستشون باندل هست) و در کنار هم قراردادنشونه. برای همین سیمفونی رو میشه به دو حالت استفاده کرد:یک فریم‌ورک کامل: کل ابزارهای سیمفونی و یک عالمه ابزاری که برنامه‌نویس‌های دیگه نوشتن رو کنار هم و یکجا داشته باشیدمیکرو فریم‌ورک‌ها: که درواقع شما توی پروژه‌ای که کار میکنید، بدون نصب سیمفونی، فقط از باندل‌های بدرد بخورش براش خودتون استفاده کنید، مثل FormBundleدر مورد TWIG!الان تو دنیایی هستیم که کمتر کسی علاقه‌ای به نوشتن ظاهر سایت و HTML بصورت دستی داره، بخصوص زمانی که تعداد فایلها قراره زیاد بشن و شما مجبور بشید به ازای هر صفحه یه فایل جدید بسازید. توییگ، یه موتور ساخت قالب هست که بهتون کمک خیلی زیادی توی طراحی میکنه. مثلا شما میتونید یک فایل html بسازید و داخلش از توییگ استفاده کنید و فقط متغیرها رو بهش پاس بدید. و اون برای شما به سادگی و سریع رندر کنه.سیمفونی به صورت پیشفرض از توییگ پشتیبانی میکنه و خیلی از زمان طراحی شما کم میکنه.داکترین (Doctrine)داکترین در واقع یک سری کتابخونه برای php هست که وظیفش ایجاد یک لایه‌ی اضافی برای ارتباط برنامه‌نویس با دیتابیسه، در حقیقت به جای اینکه برنامه‌نویس مجبور بشه کدهای sql رو دستی وارد کنه، با نصب داکترین، فقط به کدهای php بسنده میکنه و داکترین تمام کارهارو براش انجام میده.داکترین تبدیل به یک پروژه بالغ شده و بنظرم تمام امکانات مورد نیاز برنامه‌نویس رو در اختیارش قرار میده. خود داکترین شاخه‌های زیرمجموعه داره که مهمترین و پرمصرف‌ترینش Doctrin ORM هست که وظیفش بصورت ساده و خلاصه، تبدیل کلاس‌های php به مدل‌های دیتابیسی هست.سیمفونی بطور پیشفرض از Doctrine ORM پشتیبانی میکنه و نیازی نیست شما اون رو کانفیگ کنید.تست راحتبنظرم سیمفونی با ایده‌ی «تستینگ در اولویت» پیش رفته. Unit Testingها با استفاده از PHPUnit خیلی خوب از کدها جدا شدن مدیریتشون خیلی راحت شده. با یه کمک خیلی زیاد از PHPUnit این امکان برای برنامه‌نویس وجود داره تا به سادگی درخواست‌های http رو بازسازی، آزمایش و تست کنه بدون اینکه مجبور باشه کد زیادی رو با ابزار تست بزنه.در واقع این امکان سیمفونی حتی زمان زیادی رو هم توی تست حفظ میکنه و سرعت عمل رو بالا میبره. در مجموع اکوسیستم سیمفونی روی تستینگ و کیفیت بالای اون خیلی تمرکز داشته و موارد خوبی رو فراهم کرده.دیباگ مثل آب خوردنمحبوبترین ویژگی سیمفونی، Web Debug Tool هست که اطلاعات کاملی و دقیقی راجع به وضعیت فعلی درخواست‌ها، ترنسپایلر‌ها و غیره میده و حتی امکان تست سرعت رندر هم داره. Symfony Profiler همون ابزار دیباگینگ هست که در مورد تمام اتفاقات پروژه تو هر مرحله گزارش کامل و دقیق میده.نصب سیمفونیحتما براتون سوال شده که چطور میشه سیمفونی رو نصب و راه‌اندازی کرد. برای اینکار روش‌های مختلی وجود داره، اما بهترین روش که من هم ازش استفاده میکردم و راضی بودم، استفاده از نصاب خود سیمفونی هست که برای راه‌اندازیش میتونید به شکل زیر عمل کنید:دریافت فایل نصاببرای لینوکس و مکsudo curl -LsS https://symfony.com/installer -o /usr/bin/symfony
sudo chmod a+x /usr/bin/symfonyبرای ویندوزC:\&gt; php -r &quot;readfile(&#039;https://symfony.com/installer&#039;);&quot; &gt; symfonyاستفاده از نصابsymfony new helloWorld ltsحتما مطمئن باشد که از PHP Phar Extension استفاده میکنید!نصب Composerکامپوزر، در حقیقت یک Package Manager هست که پکیج‌هایی که تو ریپازیتوری کامپوزر وجود دارن رو براتون پیدا و بهترین رو از لحاظ مطابقت با ورژن‌های شما نصب میکنه.کامپوزر رو میتونید به سادگی از ریپازیتوری‌های توزیع لینوکستون پیدا کنید. مثلاsudo packman -S composerیاsudo apt-get install composerراه اندازی سرور و ادامه کد زدندایرکتوریتون رو به فولدر helloWorld تغییر بدبدcd helloWorldو سرور داخلی سیمفونی رو اجرا کنید:app/console server:runگام به گام با هم پیش بریمبیاید باهم یه وب‌سایت ساده بنویسیم. فکر میکنم یه وبلاگ میتونه گزینه مناسبی برای شروع باشه. پس اگر هنوز نصاب سیمفونی و کامپوزر رو نصب نکردید، برگردید عقب و انجامشون بدید تا در ادامه مشکلی نداشته باشید.قدم اول، راه اندازی پروژهsymfony new MyBlog ltsپس از اجرا، باید همچین پاسخی رو دریافت کنید:Downloading Symfony...

    5.4 MiB/5.4 MiB ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓  100%

 Preparing project...

   Symfony 2.8.24 was successfully installed. Now you can:

    * Change your current directory to ~/MyBlog

    * Configure your application in app/config/parameters.yml file.

    * Run your application:
        1. Execute the php app/console server:start command.
        2. Browse to the http://localhost:8000 URL.

    * Read the documentation at http://symfony.com/docو در نهایت دستور composer install رو داخل فولدر MyBlog اجرا کنید.حالا IDE یا ادیتورتون رو باز کنید و پروژه رو داخلش بیارید بالا.تنظیمات دیتابیستمام تنظیمات پروژه، داخل فولدر app/config قرار میگیرن. فولدر app موظف به نگهداری از تمام منابع اپلیکیشن هست، مثل قالب‌های توییگ، لاگ‌ها و تنظیمات و هسته اپلیکیشن.فایلهایی که داخل پوشه app/config هستن، معمولا با پسوند .yml یا .yaml قرار میگیرن که میتونم بگم از لحاظ کاربری مشابه .json هستن.حالا فایل app/config/parameters.yml رو باز کنید. با همچین ساختاری مواجه میشید:# This file is auto-generated during the composer install
parameters:
    database_host: 127.0.0.1
    database_port: null
    database_name: symfony
    database_user: root
    database_password: null
    mailer_transport: smtp
    mailer_host: 127.0.0.1
    mailer_user: null
    mailer_password: null
    secret: 90830183902924603f797e4b794ff7e8353e43e9تیکه اول درواقع تنظیمات عمومی اپ برای ارتباط با دیتابیس هست. این تنظیمات رو به:database_name: MyBlog #یا هر اسم دیگه‌ای که برای دیتابیس دوست دارید
database_user: root #یوزرنیم که باهاش به دیتابیس وصل میشید
database_password: null #پسورد دیتابیستون...تغییر بدید. من در حالت عادی با MySql کار میکنم، اما سیمفونی گزینه‌های دیگه‌ای هم مثل MongoDb و دیتابیس‌های دیگه داره و از اونا پشتیبانی میکنه.ساخت دیتابیسیکی از گزینه‌های خیلی خوب سیمفونی که من دوست دارم، کنسولش هست. که خیلی از کارهارو برای شما انجام میده. میتونید اطلاعات بیشتری راجع بهش رو صرفا با تایپ app/console بدست بیارید.الان فقط ساخت دیتابیس برامون کافیه تا بریم مراحل بعدی:app/console doctrine:database:createو پاسخش:Created database `MyBlog` for connection named defaultحالا چک کنیم که تا اینجا همه‌چیز خوب پیشرفته:app/console server:run

[OK] Server running on http://127.0.0.1:8000

// Quit the server with CONTROL-C.میتونید صفحه رو باز کنید و چک کنید. نوار سیاه پایین صفحه، همون Web Debug Tool هست که گفته بودم. بعد از اینکه مطمئن شدید اوضاع خوبه، پروسه رو قطع میکنیم و میریم گام بعدی.ساخت یک باندل برای مدیریت وبلاگیک نکته مهم، از اونجایی که سیمفونی ساختار تیکه تیکه داره (Bundle) شما میتونید هر قسمتی از سایت رو بر اساس ساختار خودتون به یک باندل تبدیل کنید. مثلا فرض میکنیم که وبلاگ سایت، برای خودش یه تیکه جداست، یعنی میتونیم خیلی راحت از پروژه حذفش کنیم و دیگه کاربرا بلاگی نبینن. برای اینکار، یه باندل جدید میسازیم:app/console generate:bundle

 
  Welcome to the Symfony bundle generator!  
 

Are you planning on sharing this bundle across multiple applications? [no]: 

Your application code must be written in bundles. This command helps
you generate them easily.

Give your bundle a descriptive name, like BlogBundle.
Bundle name: MyBlogBundle

Bundles are usually generated into the src/ directory. Unless you&#039;re
doing something custom, hit enter to keep this default!

Target Directory [src/]: 

What format do you want to use for your generated configuration?

Configuration format (annotation, yml, xml, php) [annotation]: 

 
  Bundle generation  
 

&gt; Generating a sample bundle skeleton into app/../src/MyBlogBundle
  created ./app/../src/MyBlogBundle/
  created ./app/../src/MyBlogBundle/MyBlogBundle.php
  created ./app/../src/MyBlogBundle/Controller/
  created ./app/../src/MyBlogBundle/Controller/DefaultController.php
  created ./app/../tests/MyBlogBundle/Controller/
  created ./app/../tests/MyBlogBundle/Controller/DefaultControllerTest.php
  created ./app/../src/MyBlogBundle/Resources/views/Default/
  created ./app/../src/MyBlogBundle/Resources/views/Default/index.html.twig
  created ./app/../src/MyBlogBundle/Resources/config/
  created ./app/../src/MyBlogBundle/Resources/config/services.yml
&gt; Checking that the bundle is autoloaded
&gt; Enabling the bundle inside app/AppKernel.php
  updated ./app/AppKernel.php
&gt; Importing the bundle&#039;s routes from the app/config/routing.yml file
  updated ./app/config/routing.yml
&gt; Importing the bundle&#039;s services.yml from the app/config/config.yml file
  updated ./app/config/config.yml

 
  Everything is OK! Now get to work :).سوال اول اینه:Are you planning on sharing this bundle across multiple applications? [no]که اگر جوابتون yes باشه، تمام فایلهای باندل، مثل قالب‌ها، تنظیمات و غیره رو توی خود فولدر باندل میریزه که شما بتونید راحت جداش کنید. در غیر این صورت، قالب‌ها داخل فولدر app/Resources/views ریخته میشن. (که عملا جدا کردنشون کار سختی میشه…)برای ادامه آموزشمون، میتونید این گزینه رو همینطور رها کنید (اینتر بزنید) و بریم سراغ سوال بعدی:Bundle name: MyBlogBundleاین اسم، ارتباطی با اسم پروژه نداره، یهو به ذهنم رسید، شما میتونید از BlogBundleیا HaminjuriBundle استفاده کنید… مهم اینه که حتما کلمه Bundle به آخرش، به صورت CamelCase اضافه بشه. سوال بعدی این خواهد بود:Target Directory [src/]:تمام باندل‌های سایت شما (مگر زمانی که خودتون کانفیگ کنید) داخل فولدر src ریخته میشن، درواقع شما ۹۹٪ زمانتون رو تو این فولدر صرف میکنید. ماهم این گزینه رو به حال خودش رها میکنیم.Configuration format (annotation, yml, xml, php) [annotation]نوع تنظیماتی که باندل قرار داشته باشه چطوره، میتونید از هر نوعی که گفته استفاده کنید ولی من annotation رو ترجیح میدم چون خیلی راحت میشه تغییرش داد و مدیریتش خیلی آسونتر هست. پس فقط اینتر رو میزنم و میرم سراغ گام بعدی!ساخت یک مدل ساده از پست وبلاگخب، تا اینجا خوب پیشرفتیم. فرض میکنیم کاربرای ما، نیازی به مدلسازی پیچیده‌ای ندارن و در حد ساده‌ی آموزش ما براشون کافیه. یک پست وبلاگ چه چیزا‌هایی احتیاج داره؟عنوان (title) از نوع رشته‌ای (string) که حتما باید وارد بشه (not nullable) و نباید تکراری باشه (unique)متن نوشته (content) از نوع متنی (text) که حتما باید وارد بشه (not nullable)تاریخ ساخت (createdAt) از نوع تاریخ (data) که حتما باید وارد بشه (not nullable)دوباره میریم سراغ کنسول:app/console doctrine:generate:entity

 
  Welcome to the Doctrine2 entity generator 
  
This command helps you generate Doctrine2 entities.

First, you need to give the entity name you want to generate.
You must use the shortcut notation like AcmeBlogBundle:Post.

The Entity shortcut name: BlogBundle:Postاینجا بهش میگیم که این انتیتی (entity)، یا همون مدلمون، مربوط به کدوم باندل هست. اسم باندل که باهم درست کردیم دو نقطه اسم انتیتی که میشه پست…Configuration format (yml, xml, php, or annotation) [annotation]همچنان با انوتیشن پیش میریم. از اینجا به بعد ازتون میخواد که پراپرتی‌های مدل رو مشخص کنید. زمانی که کارتون تموم شد، میتونید اینتر رو بزنید و ادامه رو به کنسول بسپارید. پس پیش میریم:New field name (press &lt;return&gt; to stop adding fields): title
Field type [string]: 
Field length [255]: 
Is nullable [false]: 
Unique [false]: true

New field name (press &lt;return&gt; to stop adding fields): content
Field type [string]: text
Is nullable [false]: 
Unique [false]: 

New field name (press &lt;return&gt; to stop adding fields): createdAt
Field type [string]: date
Is nullable [false]: 
Unique [false]: 

New field name (press &lt;return&gt; to stop adding fields): 

 
  Entity generation  
 

  created ./src/BlogBundle/Entity/
  created ./src/BlogBundle/Entity/Post.php
&gt; Generating entity class src/BlogBundle/Entity/Post.php: OK!
&gt; Generating repository class src/BlogBundle/Repository/PostRepository.php: OK!

 
  Everything is OK! Now get to work :).حالا اگر برید داخل src/BlogBundle/Entity متوجه میشید که فایل Post.phpبراتون ساخته شده. این فایل در واقع یه کلاس ساده PHP هست که صرفا پراپرتی‌های مدل رو نگه‌داری میکنه. در واقع این همون مدل پست ماست که میتونید بعدا خیلی راحت تغییرش بدید.ضمنا همزمان با ساخت این مدل، یک فایل هم داخل src/BlogBundle/Repositoryبه نام PostRepository.php ساخته شده، که در واقع وظیفه اصلیش اینه:یک جاهایی از پروژه شما نیاز پیدا میکنید تا مثلا یک رکورد خاص رو از دیتابیس، با محاسبات خاصی دریافت کنید. اینجا میتونید تمام دستورات لازم رو بنویسید تا همه‌جا بشه به سادگی ازشون استفاده کرد.حالا که مدل ساخته شد، اون رو به دیتابیس منتقل میکنیم تا ساختار دیتابیس با مدل‌های ما یکی بشه:app/console doctrine:schema:update --force
Updating database schema...
Database schema updated successfully! &quot;1&quot; queries were executedچرا از آرگومان --force استفاده کردیم؟ یک دلیلش اینه که مطمئن باشیم داریم درست پیش میریم. پیش میاد زمانی که احتمالا دستور رو اشتباه وارد کنیم و باعث بشیم تا دیتابیس بهم بریزه. مورد بعدی اینکه شما میتونید از آرگومان --dump-sql هم استفاده کنید تا ببینید دقیقا چه دستوری به SQL اجرا میشه.ساخت فرم برای مدیریت پست‌هاتا اینجا خوب پیشرفتیم. حالا باید این امکان رو برای کاربر فراهم کنیم، تا بتونه پست‌ها رو کراد (CRUD = Create, Read, Update and Delete) کنه. خوبی سیمفونی اینه که تقریبا تمام این کارها رو با کنسول میشه انجام داد. پس:app/console doctrine:generate:crud

 
  Welcome to the Doctrine2 CRUD generator

This command helps you generate CRUD controllers and templates.

First, give the name of the existing entity for which you want to generate a CRUD
(use the shortcut notation like AcmeBlogBundle:Post)

The Entity shortcut name: BlogBundle:Post

By default, the generator creates two actions: list and show.
You can also ask it to generate &quot;write&quot; actions: new, update, and delete.

Do you want to generate the &quot;write&quot; actions [no]? yes

Determine the format to use for the generated CRUD.

Configuration format (yml, xml, php, or annotation) [annotation]: 

Determine the routes prefix (all the routes will be &quot;mounted&quot; under this
prefix: /prefix/, /prefix/new, ...).

Routes prefix [/post]: /blog

 
  Summary before generation  
 

You are going to generate a CRUD controller for &quot;BlogBundle:Post&quot;
using the &quot;annotation&quot; format.

Do you confirm generation [yes]? 

 
  CRUD generation  
 

  created ./src/BlogBundle/Controller//PostController.php
  created ./app/Resources/views/post/
  created ./app/Resources/views/post/index.html.twig
  created ./app/Resources/views/post/show.html.twig
  created ./app/Resources/views/post/new.html.twig
  created ./app/Resources/views/post/edit.html.twig
  created ./src/BlogBundle/Tests/Controller/
  created ./src/BlogBundle/Tests/Controller//PostControllerTest.php
Generating the CRUD code: OK
  created ./src/BlogBundle/Form/
  created ./src/BlogBundle/Form/PostType.php
Generating the Form code: OK
Updating the routing: OK

 
  Everything is OK! Now get to work :).بذارید مرحله به مرحله توضیح بدم. اول دستور app/console doctrine:generate:crud رو زدم. بعد ازم پرسید که برای چه انتیتی میخوام کراد بسازم و من هم BlogBundle:Post رو وارد کردم. بعد ازم پرسید که پیشوند مسیرم برای کاربر چیه، در واقع کاربر از چه مسیری توی سایت میتونه به این عملیات‌ها دسترسی داشته باشه. خودش بصورت پیشفرض، اسم انتیتی (Post) رو در نظر گرفته بود و من به /blogتغییرش دادم. و در نهایت پرسید که آیا مطمئن هستم؟ و منم مطمئنم…خب، حالا یه تست کنیم ببینیم تا اینجا چطور پیشرفتیم:app/console cache:clear
app/console server:runاز این آدرس استفاده کنید تا بتونید بهتر ببینید:http://localhost:8000/app_dev.php/blog/app_dev.php در واقع محیط دیباگ رو فراهم میکنه. اگر واردش نکنید، سایت اصلی بدون گزینه‌های دیباگ و پولیش شده جلوتون قرار میگیره.تا اینجا عالی بود. پیشنهاد میکنم یکم با این صفحه کار کنید و چندتا پست نمونه بسازید، پاکشون کنید و تغییرشون بدید. چقدر راحت شد همه‌چیز.ولی ظاهرش اصلا قشنگ نیست… قدم بعدیمون، میریم سراغ یکم طراحی…یکم کار با قالب‌هاتمام قالب‌های مربوط به کراد، با توجه به اینکه قرار نیست ما این باندل رو جدا کنیم، تو فولدر app/Resources/views/post قرار گرفتن. از اسم فایل‌ها مشخصه که هر کدوم چه وظیفه‌ای به عهده دارن. پسوندشون هم .html.twig هست که درواقع یک فایل توییگه که باهاش به شکل فایل html برخورد میشه.فایل index.html.twigاگر به فایل src/BlogBundle/Controller/PostController.php نگاه کنید، که بعد از اجرای دستور doctrine:generate:crud ایجاد شده، متوجه میشید که تمام عملیات کراد اینجا انجام میشه.کنترلرها در واقع کلاس‌هایی هستن که وظیفشون مدیریت فعالیت‌های قسمت‌های مختلف باندل یا مسیرهای اوناست. اینو رو ببینید:/**
* Lists all post entities.
*
* @Route(&quot;/&quot;, name=&quot;blog_index&quot;)
* @Method(&quot;GET&quot;)
*/
public function indexAction()
{
    $em = $this-&gt;getDoctrine()-&gt;getManager();

    $posts = $em-&gt;getRepository(&#039;BlogBundle:Post&#039;)-&gt;findAll();

    return $this-&gt;render(&#039;post/index.html.twig&#039;, array(
        &#039;posts&#039; =&gt; $posts,
    ));
}چون تعریف کردیم که تظیمات رو با انوتیشن انجام میدیم، تمام تعاریف اکشن‌ها (یا همون تیکه‌های کوچیک که وظیفه مدیریت قسمت‌های مختلف باندل رو دارن وکنترلر اونارو یجا جمع کرده) بالاشون، انوتیت میشن.مثلا اینجا به @Route دقت کنید، آرگومان اولش / هست، یعنی مسیرباندل/مسیر کنترلر/مسیر اکشن که اینجا برای ما میشه /blog/. دقت کنید که خود باندل بلاگ، مسیری رو نداره، و ما زمان ساخت فرم گفتیم که پیشوند مسیر رو از /post به /blog تغییر بده. اگر دوست داشتید که مسیر باندل رو هم عوض کنید، فایل app/config/routing.yml رو باز کنید و prefix باندل رو از / به هرچی که دوست دارید، مثلا hello تغییر بدید. در نتیجه این تغییر، کاربر شما برای دریافت لیست پست‌ها باید به آدرس hello/blog/ مراجعه کنه.خب، برمیگردیم به خود کد و اون رو مرور میکنیم. $em درواقع انتیتی منیجر داکترین تعریف شده. وقتی ما این کلاس رو از Symfony\Bundle\FrameworkBundle\Controller\Controller اکستند کردیم، امکاناتی مثل getDoctrine() به $this اضافه شده.بعد اومده و لیست تمام رکورد‌های موجود توی جدول پست رو گرفته، و در نهایت فایل app/Resources/views/post/index.html.twig رو رندر کرده و پست‌ها رو پاس داده بهش.حالا بریم سراغ فایل app/Resources/views/post/index.html.twig. تو خط اولش متوجه میشیم که {% extends &#x27;base.html.twig&#x27;%} اجرا میشه، یعنی، این فایل ما یک بخشی از فایل اصلی base.html.twig هست که تو پوشه app/Resources/views/base.html.twig قرار گرفته.شما با تغییر دادن این فایل میتونید ظاهر سایت رو عوض کنید. مثلا من بالای base.html.twig میخوام اسم سایت رو اضافه کنم. فایلش رو باز میکنم و:حالا بالای صفحه یه هدر دارم و پایین هم یه فوتر. یه استایل ساده رو داخل فولدر web/style.css میذارم و اینا رو داخلش اضافه میکنم:body {
    font-family: sans;
}

.header {
    margin: 15px;
    background-color: #eee;
}

.footer {
    margin: 15px;
    border: 1px solid #ccc;
}و در نهایت به base.html.twig میگم که این فایل رو بیاره و تو صفحه‌ها نمایش بده:دستورات توییگ با { { } } (بدون فاصله) اجرا میشن. و asset(&#x27;...&#x27;) میره و هرچیزی که داخل فولدر web بود رو برای شما با اون اسم میاره. دیگه نیازی نیست نگران آدرس فایل‌ها باشید!حالا میخوام جدولی که توی فایل app/Resources/views/post/index.html.twig بود رو یکم قشنگتر کنم، یه فایل table.css توی web میسازم و اینارو داخل مینویسم:table, td, th {    
    border: 1px solid #ddd;
    text-align: left;
}

table {
    border-collapse: collapse;
    width: 100%;
}

th, td {
    padding: 15px;
}و بعد، میخوام هرموقع که کاربر صفحه ایندکس پست‌ها (indexAction) رو باز میکنه، این استایل نمایش داده بشه. برای اینکار، فایل post/index.html.twig رو باز میکنم و:کارمون تموم شد. یه تست میکنیم:app/console cache:clear
app/console server:runحالا صفحه پست‌ها رو باز کنید و ببینید چه اتفاقی افتاد…خب ما باهم تونستیم یه وب‌سایت خیلی ساده رو درست کنیم و تقریبا هیچ کدی نزنیم. سیمفونی هنوز مونده و خیلی خیلی جا برای یادگیری داره، اما بنظرم شروع خوبی داشتیم و قطعا خودتون میتونید از اینجا به بعد رو تنهایی پیش برید.پیشنهاد میکنم حتما سری به سایت سیمفونی، سایت آموزش داکترین و توییگ بزنید تا باهاشون بیشتر آشنا بشید.با آرزوی موفقیت روزافزون برای شما</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Fri, 13 Jul 2018 15:10:58 +0430</pubDate>
            </item>
                    <item>
                <title>از سیر تا پیاز ری‌اکت، نکست و ریداکس!</title>
                <link>https://virgool.io/pullrequest/%D8%A7%D8%B2-%D8%B3%DB%8C%D8%B1-%D8%AA%D8%A7-%D9%BE%DB%8C%D8%A7%D8%B2-%D8%B1%DB%8C%D8%A7%DA%A9%D8%AA-%D9%86%DA%A9%D8%B3%D8%AA-%D9%88-%D8%B1%DB%8C%D8%AF%D8%A7%DA%A9%D8%B3-vkxtmkwxk1ts</link>
                <description>عمیق‌تر در مورد جاوااسکریپت، ری‌اکت و نکست‌جی‌اس بدونیمنکست‌جی‌اس و ریداکس‌تانک، از مبتدی تا پیشرفتهمقدمهخیلی از دوستان من با موضوعات مختلفی خصوصا در زمینه جاوا‌اسکریپت دچار مشکل شدن. بعضی از مفاهیم رو نفهمیدن و یا نمیدونستن از کجا باید شروع کنن. برای همین تصمیم گرفتم که این مطلب رو بنویسم. قصد دارم اینجا برای سطوح مبتدی تا پیشرفته در مورد ری‌اکت و نکست‌جی‌اس و همچنین ریداکس توضیح بدم. و سعی میکنم این مطلب رو تا حد امکان گسترده کنم تا تمامی مواردی که برای یک برنامه‌نویس خوب شدن لازم هست رو پوشش بدم.اما اساسا چرا این مطلب رو نوشتم؟ خب، اول از همه اینکه بتونم هر آنچه که بلد هستم رو یک‌جا نگه دارم و بعدا هم ازش استفاده کنم. دوم اینکه همچین آموزشی رو تقریبا هیچ‌کجای وب، و خصوصا تو سایت‌های ایرانی پیدا نکردم.متنی که اینجا نوشته شده، حاصل چند سال تلاش من برای یادگیری، و تقریبا یک ماه برای خلاصه‌کردن تمام اون اطلاعات بود تا بتونم یک مرجع کامل رو بسازم، سعی کردم خط به خط کدها رو توضیح بدم و ریپازیتوری گیت رو باهاش سینک و همگام نگه‌دارم. از اینکه این مطالب به دست دیگران هم برسه و کمک به چند نفر بکنه واقعا خوشحال میشم، اما تنها خواهش من از خوانندگان و شما، اینه که اگر این مطلب رو جایی به اشتراک میذارید، منبع اون رو هم ذکر کنید.همچنین مطلب کامل رو در سایت خودم میتونید پیدا کنید و در مورد ری‌اکت و نکست‌جی‌اس بیشتر مطالعه کنید.سپاس.جاوا‌اسکریپت و اکما‌اسکریپت (ECMAScript)اولین چیزی که لازم هست بدونید، اینه که جاوا‌اسکریپت توسط شرکت نِت‌اِسکیِپ (شرکت قدیمی موزیلا فایرفاکس) ساخته و به سازمان اِکما داده شد تا اون رو استانداردسازی کنن. اِکما سازمانیه که وظیفش استانداردسازی اطلاعاته.اونچه که در نهایت از جاوا‌اسکریپت توسط سازمان اِکما ارائه شد، اِکما‌اِسکریپت بود. ساده‌تر بگم، اِکما‌اِسکریپت یک استاندارد هست، در حالی که جاوا‌اسکریپت محبوب‌ترین پیاده‌سازی از اون استاندارد به حساب میاد. جاوا‌اِسکریپت، اِکما‌اِسکریپت رو پیاده‌سازی میکنه و بر پایه اون ساخته میشه.حالا سوالی که مطرح میشه، اینه که “ES” چیه؟ای‌اِس، مخفف اِکما‌اِسکریپته (ECMAScript)، هرجایی که ای‌اِس رو در کنار یک عدد دیدید، مثل ای‌اس۶، یادتون باشه که داره به یک نسخه از اِکما‌اِسکریپت یا در واقع یک نسخه از استاندارد اشاره میشه.ای‌اِس (ES)===========ای‌اِس تا به اینجا ۸ نسخه مختلف رو ارائه کرده، ای‌اِس۱، ۲، ۳ و ۴ بین سال‌های ۱۹۹۷ تا ۱۹۹۹ ارائه شدن و دیگه ازشون پشتیبانی نمیشه. (ما هم کاری بهشون نداریم).ای‌اِس۵ تقریبا ۱۰ سال بعد از اس‌اس۴ یعنی اواخر سال ۲۰۰۹ (تاریخ دقیق رو نمیدونم) ارائه داده شد.ای‌اِس۶ در سال ۲۰۱۵ منتشر شد که برای راحتی کار، بهش ای‌اس۲۰۱۵ هم میگن. در واقع چون ای‌اس۶ در سال ۲۰۱۵ ارائه شده، بهش ای‌اِس۲۰۱۵ میگن!ای‌اِس۷/ای‌اس۲۰۱۶ که مطمئنا میتونید پیشبینی کنید در سال ۲۰۱۶ منتشر شد.ای‌اس۸/ای‌اس۲۰۱۷ هم، در سال ۲۰۱۷ منتشر شد.چرا ورژن‌های مختلف از ای‌اس منتشر شدن؟دلیلش اینه که هر وِرژِن، ویژگی‌های جدیدی رو ارائه کرده که با زمان خودش هم‌خوانی داشته باشه. فقط باید چند نکته رو به خاطر داشته‌باشید:پیشبینی میشه که هر سال یک نسخه جدید از اِکما‌اِسکریپت ارائه بشه،اولین نسخه‌های اِکما‌اِسکریپت با عدد نسخه‌بندی میشدن، مثل ای‌اِس۱، ای‌اِس۲ و…نسخه‌های جدید که از سال ۲۰۱۵ شروع شدن، به شکل ای‌اس[سال انتشار] نام‌گذاری میشن.اکما یک استاندارده، جاوا‌اسکریپت محبوب‌ترین پیاده‌سازی از اون استاندارد هست.چرا ای‌اس۶؟نسخه ۶‌ام از اِکما‌اِسکریپت، ویژگی‌های خیلی خوبی رو به زبان جاوا‌اسکریپت اضافه کرد، و همین، یکی از دلایلی شد که ری‌اَکت به طور پیش‌فرض ازش پشتیبانی میکنه. مثلا مفاهیمی مثل «کلاس‌ها» و «ماژول‌ها»، که برای زبان‌های شئ‌گرا اجباری هستند، بهش اضافه شدن. از جمله ویژگی‌های دیگش، اضافه شدن دستورات for، جِنِراتور‌های شبیه به زبان پایتون، توابع فِلِشی (Arrow Function)، کالِکشِن‌ها، پرامِس‌ها (Promise) و غیره بوده.متاسفانه هنوز مرورگرها پشتیبانی از ای‌اِس۶ رو کامل نکردن و ای‌اِس۶ به خودی خود تو مرورگرها پشتیبانی نمیشه. اینجاست که مفاهیم تِرَنس‌پایلِرها (transpiler) خودشون رو نشون میدن که بعد از توضیح توابع فِلِشی (برای راحتی کار میگم اَرو فانکشِن) بهشون میپردازم.Arrow Functionsیکی از ویژگی‌های خیلی خوبی که توی ای‌اِس۶ وجود داره، استفاده از اَرو فانکشن‌هاست. به اسمش دقت نکنید، مفهومش خیلی سادست. ارو فانکشن‌ها، در واقع همون توابع قدیمی جاوااسکریپت هستند (با ویژگی‌های جدید‌تر که اینجا بهشون کاری نداریم) که تو ای‌اس۶ به شکل دیگه‌ای تعریف میشن و موقع تِرَنس‌پایل (یکمی پایینتر توضیح میدم در این مورد) به شکل توابع جاوااسکریپت درمیان، مثلا:x =&gt; {
 return x * x;
}

(m, n) =&gt; {
 return m+n
}

data =&gt; {
 data.json()
 .then(result =&gt; {
 return result;
  })
}بعد از تِرَنس‌پایل تبدیل میشن به:(function (x) {
 return x * x;
});

(function (m, n) {
 return m + n;
});

(function (data) {
 data.json().then(function (result) {
 return result;
  });
});ترنس‌پایلر (transpiler)حتما تا به حال واژه‌های «کامپایلِر» و «مفسر» به گوشتون خورده. تِرَنس‌پایلِرها در واقع نوعی کامپایلر هستند با یک تفاوت اصلی:کامپایلرها معمولا زبان رو به یک نسخه قابل اجرا برای ماشین تبدیل می‌کنن، مثلا زبان سی، کدهای باینری یا همون صفر و یک میسازه، یا جاوا بایت‌کد رو تولید میکنه.این درحالیه که ترنس‌پایلرها، یک سورس‌کد رو به یک سورس‌کد دیگه تبدیل می‌کنن (یا مثلا به یک زبان دیگه که مستقیم برای ماشین قابل درک نیست و باید دوباره کامپایل، اینتِرپرِت یا همون تفسیر بشه). مثلا کافی‌اسکریپت (CoffeeScript) که از خودش جاوا‌اسکریپت تولید میکنه، یا بابِل (Babel) که ای‌اس۶ رو به ای‌اس۵ (قابل پشتیبانی برای مرورگرها) تبدیل می‌کنه.بابِل یا بِیبِل (Babel) یک ترنس‌پایلر برای ای‌اس۶ هست که اون رو به ای‌اس۵ تبدیل میکنه. ای‌اس۵ توسط مرورگرها خیلی خوب پشتیبانی میشه و در حقیقت، ای‌اس۵ همون جاوا‌اسکریپتیه که عموما باهاش آشنایی دارن.بابِل، بِیبِل…؟ (Babel)بابل یک تِرَنس‌پایلِر برای جاوا‌اسکریپته. بابل رو اکثرا بخاطر توانایی خوبش تو تبدیل ای‌اس۶ به ای‌اس۵ میشناسن.به عنوان مثال این کد که با ای‌اس۶ نوشته شده:let input = \[1, 2, 3\];
console.log(input.map(item =&gt; item + 1)); // \[2, 3, 4\]توسط بابل تبدیل میشه به کد ای‌اس۵:var input = \[1, 2, 3\];
console.log(input.map(function (item) {
 return item + 1;
})); // \[2, 3, 4\]که تقریبا همه‌جا قابل اجراست. بابل خیلی خوب از پُلی‌فیل‌های جاوا‌اسکریپت پشتیبانی میکنه و باعث میشه که کد جاوا‌اسکریپت ساخته شده برای مرورگرهای قدیمی هم قابل پشتیبانی باشه. به همین خاطر، بابل باعث میشه شما از تمام ویژگی‌های ای‌اس۶ استفاده کنید بدون اینکه پشتیبانی از نسخه‌های قدیمی مرورگرها رو از دست بدید (مفهوم پُلی‌فیل اینجا معلوم میشه).فرانت‌اند و مفاهیم اِس‌پی‌اِی (SPA)اطلاعاتی که ما در اینترنت میبینیم، مجموعه‌ای از کدهای HTML، JavaScript و CSS هستن. قدیم‌ها، زمانی که خیلی از برنامه‌نویس‌ها از PHP (هنوز هم استفاده میکنن) برای نوشتن صفحات وب استفاده می‌کردن و جِی‌اِس مثل امروز محبوب نبود، هر صفحه از سایت باید بصورت جداگانه نوشته می‌شد. و زمانی که کاربر روی یک لینک کلیک میکرد، کل صفحه از اول رِندِر (Render) می‌شد. این فرایند برای کاربر، خسته‌کننده و طاقت‌فرسا بود و حتی گاهی بخاطر زمان زیادی که باید برای بارگذاری صفحه صرف میکرد، از ادامه کارش پشیمون میشد.کم‌کم تکنیک‌هایی مثل اِی‌جَکس (AJAX) استفاده شدن، که مثلا وقتی صفحه در حال بارگذاری بود، شروع میکرد یک نماد کوچک لودینگ و بارگذاری (بهش معمولا میگن اِسپینِر یا spinner) رو نشون دادن و کاربر رو متوجه میکرد که اطلاعات در حال ارسال و دریافتن.این ایده، که اطلاعات تو یک صفحه بارگذاری بشن و کاربر مدام مجبور به عوض کردن صفحه‌ها نشه (مگر در مواقع لازم) باعث ایجاد تعریف جدیدی از وب‌اَپلیکِیشِن‌ها شد، اِس‌پی‌اِی (SPA) یا Single Page Application راهش رو به لغت‌نامه‌ی برنامه‌نویس‌ها باز کرد!SPA هدفش ایجاد یک تجربه کاربری بهتر برای کاربرهاست. در حقیقت، SPA کار رو برای برنامه‌نویس سخت‌تر و برای کاربر راحتتر کرد. تو یک اپلیکیشن SPA ایده‌آل، کاربر شما متوجه عوض شدن صفحه‌ها نمیشه و احساس میکنه که همه‌چیز در حال رخ‌دادن تو یک صفحست.اما داستان سمت برنامه‌نویس کمی فرق می‌کنه. کاربر زمانی میتونه اطلاعات رو تو مرورگرش ببینه، که کد‌های HTML ساخته شده باشن، و این یعنی برنامه‌نویس باید با هر درخواست کاربر، یا کلا صفحه رو از اول بارگذاری کنه (که دیگه SPA نیست) یا اینکه اون قسمتی از سایت رو که مرتبط با کاربر هست یا نیاز به تغییر داره رو مجددا با داده‌های جدید که از سمت سرور اومدن بارگذاری کنه.اینجاست که سایت شما، تا حدود زیادی از سمت سرور خودش جدا میشه و مفهوم جدیدی به عنوان فرانت‌اِند (Front End) رو تعریف می‌کنه. فرانت‌اند و بَک‌اِند، در زمان‌های دور وجود نداشتن یا خیلی به هم نزدیک بودن. شما یک سایت رو کامل می‌نوشتید و مثلا تو یک صفحه PHP، همزمان از HTML و JavaScript استفاده می‌کردید. هر زمان که کاربر درخواست صفحه‌ی جدیدی رو میداد، شما یک اسکریپت جدید رو بارگذاری و صفحه‌های مربوطه رو از نو بازنویسی می‌کردید.زمانی که تعاریف فرانت‌اند و بَک‌اند ایجاد شدند، طراحی سایت شکل جدیدی به خودش گرفت. فرانت‌اند یجورایی بیشتر نماد طراحی سایت شد و بَک‌اند بیشتر نماد منطق کاری (Business Logic). کدها سمت بک‌اند نوشته می‌شن و اطلاعات رو موقع نیاز به فرانت‌اند ارسال می‌کنن. از اینجا به بعد، برنامه‌نویس فرانت نیازی نداره که نگران SQL و دستورات مربوط به ارتباط با پایگاه داده و دریافت محصولات از اون باشه، یا حتی نگران فرایند عضویت و ورود به سایت. فرانت‌اند خودش رو بیشتر با بهبود تجربه کاربری درگیر کرد. لازم هست که بگم، این یک مفهوم کلی و جداسازی کلی بک‌اند و فرانت‌اند هست. اینکه وظیفه‌ی برنامه‌نویس چی باشه، نسبت به هر پروژه قابل تغییر هست و امرو، خیلی از برنامه‌نویس‌ها به هرد شاخه بَک و فرانت تسلط دارن.اینجا بود که مارس ۲۰۱۳، فیسبوک اولین نسخه از کتاب‌خونه ری‌اَکت رو ارائه داد…ری‌اکت (React)ری‌اَکت یا ری‌اَکت‌جِی‌اِس، یک کتابخونست برای ساختن روابط کاربری. ری‌اکت به برنامه‌نویس این اجازه رو میده، که بتونه وب‌اپلیکیشن‌های بزرگی رو بسازه که از اطلاعات مختلفی استفاده می‌کنن و میتونن تو یک صفحه تغییر کنن، بدون اینکه صفحه رو مجدد لود کنن (مفهوم SPA). هدف اصلی سازندگان ری‌اکت، سرعت، سادگی و مقیاس‌پذیری بوده.ری‌اکت صرفا تلاش میکنه تا رابط کاربری رو از راه Virtual-DOM تغییر بده. اینکه این ساز.کار به چه صورتی هست رو فعلا تشریح نمیکنم اما، اگر با معماری MVC آشنا باشید، ری‌اکت اون قسمت “V” رو به خودش اختصاص میده و میتونه با بقیه کتابخونه‌های جی‌اس خودش رو وفق بده.یکی دیگه از اَشکال ری‌اکت، ری‌اَکت‌نِیتیو هست که کمک میکنه، نرم‌افزارهای (اکثرا موبایل) نِیتیو یا سازگار با سیستم‌عامل توسط ری‌اکت ساخته بشن. ضمنا ری‌اکت از جی‌اس‌اکس (JSX) برای نمایش و ساخت المان‌ها استفاده میکنه که توضیح میدم در این مورد.جی‌اس‌اکس (JSX)جِی‌اِس‌اِکس، یک زبان مشابه با HTML یا XML که کمک میکنه، تیکه‌های سایت (Component) جدای از هم ساخته بشن و به شکل یک شئ جاوا‌اسکریپت در بیان.ساده‌تر بگم، با JSX میشه ساختارهای مشابه به HTML رو ساخت. مثال:var nav = (
    &lt;ul id=&quot;nav&quot;&gt;
      &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Home&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#&quot;&gt;About&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Clients&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Contact Us&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
);اینجا، nav به عنوان یک کامپونِنت (Component) شناخته میشه. و شما میتونید جاهای مختلف برنامه، ازش استفاده کنید (یکبار بنویسید و چندبار استفاده کنید).این استفاده از JSX یکی دیگه از ویژگی‌های ری‌اکت به حساب میاد! اینکه شما برنامتون رو به تیکه‌های کوچکتری تقسیم می‌کنید و میتونید در جاهای مختلفی ازش استفاده کنید.کمی بیشتر در مورد ری‌اکتدنیای ری‌اکت جالبه. فرض کنید که یک کامپوننت رو ساختیم، مثلا یه لیست از محصولات. بعد کاربر روی یکی از محصولات کلیک میکنه، صفحه محصول باز میشه و کاربر محصول رو میبینه. کاری که ری‌اکت انجام داده چیه؟ ری‌اکت متوجه میشه که کدوم قسمت‌های سایت باید تغییر کنن و فقط اونها رو تغییر میده! پس اول شناسایی میکنه که چه چیزی تغییر کرده، و بعد تغییرات رو اعمال میکنه. ری‌اکت، به جای اینکه کل صفحه رو از اول بازسازی کنه، فقط قسمت‌هایی که تغییر کردند یا به نوعی وضعیتشون تغییر کرده رو با داده‌های جدید پر می‌کنه و اونها رو از نو میسازه و خیلی هم سریع این کار رو انجام میده!نصب و شروع کار با ری‌اکتتصمیم ندارم اینجا به طور عمیق وارد ری‌اکت بشم و کد منبع ری‌اکت رو تشریح کنم، هدفم اینه که فضای کلی برای ورود به نکست‌جی‌اس رو ایجاد و شما رو با ساختار کلی و نحوه کار با ری‌اکت آشنا کنم. پس پیش میریم برای نصب ری‌اکت‌جی‌اس و یک آشنایی کلی با این کتابخونه.نصاب ری‌اکتنصاب ری‌اکت، که توسط فیسبوک ساخته شده، تو مخازن npm موجوده و میتونید اون رو به صورت عمومی توی سیستم‌عاملتو بریزید:$ npm install -g create-react-app

\# ساخت نرم‌افزار
$ create-react-app my-app-name

\# نصب وابسته‌ها (Dependencies)
$ cd my-app-name
$ npm installمطمئن باشید که حتما npm رو روی کامپیوترتون نصب کردید. یکی از مهم‌ترین ویژگی‌های create-react-app اینه که تمام ابزارهای لازم رو از قبل برای شما فراهم کرده. مثلا از قبل Babel برای شما نصب شده و نیازی نیست که خودتون رو درگیر نصب و راه‌اندازیش بکنید. حالا میریم سراغ یک توضیح در مورد ساختار این کتابخونه.ساختار پوشه‌هااگر داخل پوشه public رو ببینید، متوجه حضور فایل index.html میشید. این فایل در حقیقت نقطه شروع برنامست و حتما باید وجود داشته باشه، این یکی از بایدهای برنامه‌های ساخته شده با create-react-appهست. یه نگاهی به داخل این فایل میندازیم:&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot;&gt;
    &lt;meta name=&quot;theme-color&quot; content=&quot;#000000&quot;&gt;
 &lt;!--
      manifest.json provides metadata used when your web app is added to the
      homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
    --&gt;
    &lt;link rel=&quot;manifest&quot; href=&quot;%PUBLIC_URL%/manifest.json&quot;&gt;
    &lt;link rel=&quot;shortcut icon&quot; href=&quot;%PUBLIC_URL%/favicon.ico&quot;&gt;
 &lt;!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the \`public\` folder during the build.
      Only files inside the \`public\` folder can be referenced from the HTML.

      Unlike &quot;/favicon.ico&quot; or &quot;favicon.ico&quot;, &quot;%PUBLIC_URL%/favicon.ico&quot; will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running \`npm run build\`.
    --&gt;
    &lt;title&gt;React App&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;noscript&gt;
      You need to enable JavaScript to run this app.
    &lt;/noscript&gt;
    &lt;div id=&quot;root&quot;&gt;&lt;/div&gt;
 &lt;!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the &lt;body&gt; tag.

      To begin the development, run \`npm start\` or \`yarn start\`.
      To create a production bundle, use \`npm run build\` or \`yarn build\`.
    --&gt;
  &lt;/body&gt;
&lt;/html&gt;همینطور که میبینید، این فایل چیز خاصی رو داخل خودش نداره. به جز خط ۲۸ام. که اِلِمانی تعریف شده با آی‌دیroot، این رو تا اینجا توی ذهنتون داشته باشید. اتفاقی که از اینجا به بعد رخ میده، توی فایل src/index.js قرار داره. بذارید یه نگاهی هم به این فایل بندازیم:import React from &#039;react&#039;;
import ReactDOM from &#039;react-dom&#039;;
import &#039;./index.css&#039;;
import App from &#039;./App&#039;;
import registerServiceWorker from &#039;./registerServiceWorker&#039;;

ReactDOM.render(&lt;App /&gt;, document.getElementById(&#039;root&#039;));
registerServiceWorker();این فایل هم یکی از فایل‌هایی هست که حتما باید وجود داشته باشه. دلیلش اینه که تو تتظیمات create-react-app این دو فایل به عنوان نقاط شروع برنامه تعریف شدند. خود create-react-app این دو فایل رو به هم متصل میکنه و زمانی رو که شما لازم هست خودتون بذارید تا تنظیمات رو انجام بدید، براتون ذخیره می‌کنه. میریم سراغ بررسی این فایل:اول از همه، این کد با استاندارد ای‌اس۶ نوشته شده. اگر قرار بود از استاندارد ای‌اس۵ (یا به اصطلاح Common JS) پیروی کنیم، باید مینوشتیم: var React = require(&quot;react&quot;); تا کلاس ری‌اکت رو به پروژه اضافه کنیم. بعدا به این خواهیم پرداخت که این خط چه کارهایی انجام میده. فعلا بریم سراغ خط بعد.تو خط دوم، شئیی به نام ReactDOM فراخوانی شده. برای اطلاعاتون، قبل از نسخه ۰.۱۴ ری‌اکت، کتابخونه‌های react و react-dom یکی بودن. تنها وظیفه‌ای که ReactDOM به عهده داره، اینه که با اِی‌پی‌آی‌های render یا ReactDOM.render یک اِلِمان جِی‌اِس‌اِکس رو، داخل یک اِلِمان دیگه (اینجا document.getElementById(&#x27;root&#x27;)) نمایش بده.خط سوم، خیلی ساده اِستایل‌های موجود در فایل index.css رو، برای تمام اِلِمان‌هایی که اینجا قرار هست رِندِر بشن، اعمال میکنه.خط چهارم یک کامپوننت رو، اینجا به اسم app، از یک کلاس ری‌اکت فراخوانی کرد و بعد تو خط هفتم، به ReactDOM گفت که این کامپوننت رو داخل اِلِمان root رِندِر کنه. اما بریم سراغ کلاس ری‌اکت و ببینیم اصلا حرفش چی هست.import React, { Component } from &#039;react&#039;;
import logo from &#039;./logo.svg&#039;;
import &#039;./App.css&#039;;

class App extends Component {
 render() {
 return (
      &lt;div className=&quot;App&quot;&gt;
        &lt;header className=&quot;App-header&quot;&gt;
          &lt;img src={logo} className=&quot;App-logo&quot; alt=&quot;logo&quot; /&gt;
          &lt;h1 className=&quot;App-title&quot;&gt;Welcome to React&lt;/h1&gt;
        &lt;/header&gt;
        &lt;p className=&quot;App-intro&quot;&gt;
          To get started, edit &lt;code&gt;src/App.js&lt;/code&gt; and save to reload.
        &lt;/p&gt;
      &lt;/div&gt;
 );
  }
}

export default App;خب، طبق معمول خط اول، کلاس‌های ری‌اکت (React) و کامپوننت (Component) رو از کتابخونه ری‌اکت فراخوانی کرده. اما تفاوت براکت‌ها {} برای کامپوننت و ری‌اکت که براکت نداره چیه؟ این یکی از ویژگی‌های ای‌اس۶ هست که به این صورته:فرض کنید کلاسی رو به شکل زیر تعریف کردیم:class YeClassJadid1 {/*...*/}

export class YeClassJadid2 {/*...*/}

export default class YeClassJadid3 {/*...*/}

export default class YeClassJadid4 extends YeClassDige {/*...*/}اشیائی که تعریف شدن همشون ویژگی کلاس بودن رو دارن، اما تفاوتشون به این صورته که، کلاس اول (YeClassJadid1)، فقط تو همون فایلی که تعریف شده، یا اسکوپی (Scope) که تعریف شده قابل خونده شدنه و جاهای دیگه قابل استفاده نیست. کلاس دوم (YeClassJadid2) رو شما میتونید جاهای دیگه، با استفاده از روش import { YeClassJadid2 } from &quot;path/to/the/file&quot; فراخوانی کنید. دلیلش هم اینه که کلاس دوم، به طور پیش‌فرض کلاس اصلی این ماژول یا فایل نیست. اما، کلاس سوم YeClassJadid3 به طور پیش‌فرض، کلاس اصلی تعریف شده (default) و زمانی که بخواد فراخوانی بشه، میتونه به صورت import YeClassJadid3 from &quot;path/to/the/file&quot; یا حتی import YeEsmeDige from &quot;path/to/the/file&quot; فراخوانی بشه. و در نهایت هم، کلاس چهارم YeClassJadid4 مثل کلاس‌های قبلی، اما با ارث‌بری از کلاس YeClassDige خارج یا اِکسپورت میشه.نکته‌ای که گفتنش حائز اهمیته، اینه که هر ماژول، یا هر فایل، فقط یک کلاس رو میتونه به صورت default خارج کنه! تو مثال بالا، یکی از کلاس‌های YeClassJadid3 یا YeClassJadid4 میتونن خاصیت default رو داشته باشن!باز هم میگم، هدفم این نیست که عمیق وارد ری‌اکت بشم و فقط میخوام شما رو با این محیط آشنا کنم. برنامه اینه که شما وارد نِکست‌جِی‌اِس بشید و من اونجا بیشتر درمورد خود ری‌اکت می‌نویسم. تا اینجا هم خوب پیش اومدیم، بریم سراغ کامپوننت‌ها و یه کامپوننت بسازیم.ساخت کامپوننتبرای اینکه بهتر متوجه بشید کامپوننت‌ها چی هستند، صفحات وب رو به تیکه‌های کوچیک تقسیم کنید. مثلا نوار بالای صفحه یه کامپوننت جدا، لیست محصولات یه کامپوننت جدا و همینطور ادامه بدید…اول، کل صفحه یک کامپوننت هست، بعد هر تیکه‌ای از صفحه تقسیم به کامپوننت‌های کوچک‌تر میشه و پیش میره. این موضوع رو با ساخت یک کامپوننت راحتت درک میکنید. برای شروع، داخل پوشه src یک پوشه دیگه به اسم components یا هر اسم دیگه‌ای که دوست دارید ایجاد کنید. اینکه پوشه‌ها چطور باشن، دست خودتونه، اما یادتون باشه که یک‌سری استاندارد یا کانوِنشِن (Convention) برای اینکار هست که مدیریت کد رو راحتتر میکنه. در نهایت داخل این پوشه، یک فایل به اسم MyComponent.js بسازید و داخلش این کد رو قرار بدید:import React from &quot;react&quot;;

export default class ThisIsAComponent extends React.Component {
    render() {
         return (
            &lt;ul&gt;
                &lt;li&gt;Item 1&lt;/li&gt;
                &lt;li&gt;Item 2&lt;/li&gt;
                &lt;li&gt;Item 3&lt;/li&gt;
                &lt;li&gt;Item 4&lt;/li&gt;
                &lt;li&gt;Item 5&lt;/li&gt;
            &lt;/ul&gt;
         );
    }
}کامپوننتی که ساختیم خیلی سادست، یه لیست با ۵تا آیتم. که باید، حتما داخل تابع render قرار بگیرن، و این تابع هم، فقط باید یک اِلِمان رو، یا چند اِلِمانی که داخل یک المان والد جمع شدند رو برگردونه. حالا باید این کامپوننت رو داخل App.js فراخوانی کنیم. کار خیلی ساده‌ایه. App.js رو باز کنید و اون رو به شکل زیر تغییر بدید:import React, { Component } from &#039;react&#039;;
import logo from &#039;./logo.svg&#039;;
import &#039;./App.css&#039;;
import ThisIsAComponent from &quot;./components/MyComponent&quot;

class App extends Component {
 render() {
 return (
      &lt;div className=&quot;App&quot;&gt;
        &lt;header className=&quot;App-header&quot;&gt;
          &lt;img src={logo} className=&quot;App-logo&quot; alt=&quot;logo&quot; /&gt;
          &lt;h1 className=&quot;App-title&quot;&gt;Welcome to React&lt;/h1&gt;
        &lt;/header&gt;
        &lt;p className=&quot;App-intro&quot;&gt;
          To get started, edit &lt;code&gt;src/App.js&lt;/code&gt; and save to reload.
        &lt;/p&gt;
 
        &lt;ThisIsAComponent /&gt;
      &lt;/div&gt;
 );
  }
}

export default App;خب، کامپوننت رو ساختیم و اون رو به کامپوننت اصلی اضافه کردیم. حالا دستور npm start رو اجرا کنید و بعد داخل مرورگر به آدرس localhost:3000 برید و نتیجه رو ببینید. بعد از اینکه تموم شد، میتونید سرور رو ببندید و برید سراغ مرحله بعد.گریزی به stateفرض کنید که قرار بود دکمه‌ای وجود داشته باشه، تا با کلیک کردن روش، کامپوننت ما یا حتی یک بخشی از کامپوننت نمایش داده بشه و یا مخفی بشه، یکی از این دو حالت ساده! اینجا لازم هست که کمی در مورد مفهوم استِیت (state) توضیح بدم. کامپوننت‌های شما، همینطور که تا اینجا دیدید، کار خاصی رو به خودی خودشون انجام نمیدن، چون در حقیقت اِلِمانهای HTML هستند، یا حتی شاید لازم باشه در طول زمان تغییراتی رو پیدا کنن. ملموس‌ترین نوع تغییر، زمانی رخ میده که شما اطلاعاتی رو از جایی (از یک سرور) دریافت میکنید و می‌خواید به کاربر نشون بدید، اما تو مدت زمانی که اطلاعات در حال دریافت هستند، علاقه دارید تا یک اسپینر (spinner) رو نمایش بدید، تا به کاربر بگید که اطلاعات در حال بارگزاری هستن. یه سناریوی دیگه اینکه، با کلیک روی یک چِک‌باکس (checkbox) یک فیلد مخفی شده رو نمایش بدید و مثال‌های دیگه. اینجاست که استیت به کمک شما میاد.استیت در حقیقت محل ذخیره‌ي آخرین تغییرات و حالات کامپوننته. مثلا شما بهش میگید که کامپوننت من در حالت عادی، نمایش داده میشه، اما من میخوام، زمانی که کاربر روی یک دکمه کلیک میکنه، کامپوننتم رو مخفی کنم. اینجا، نمایش داده شدن یا مخفی شدن، جز حالات یا استیت کامپوننت به حساب میاد. ری‌اکت، زمانی که استیت تغییر میکنه، کامپوننت رو مجدد بارگزاری یا رِندِر میکنه.برای اینکه با استیت هم کار کنیم و بهتر درکش کنیم، به تریتیب زیر، به کامپوننت ThisIsAComponent استیت میدیم،حالت دیفالت یا اولیه رو برای کامپوننت تعریف میکنیمتوسط یک ایونت (Event) حالت یا همون استیت رو تغییر میدیم.کامپوننت رو به شکل زیر بازنویسی میکنیم:import React from &quot;react&quot;;

export default class ThisIsAComponent extends React.Component {
 constructor() {
 super()

 this.state = {
            isHidden: false
        }
    }

 toggleState() {
 this.setState({
            isHidden: !this.state.isHidden
        })
    }

 render() {
 return (
            &lt;div&gt;
                &lt;button onClick={this.toggleState.bind(this)}&gt;Change&lt;/button&gt;
                &lt;ul hidden={this.state.isHidden}&gt;
                    &lt;li&gt;Item 1&lt;/li&gt;
                    &lt;li&gt;Item 2&lt;/li&gt;
                    &lt;li&gt;Item 3&lt;/li&gt;
                    &lt;li&gt;Item 4&lt;/li&gt;
                    &lt;li&gt;Item 5&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
 );
    }
}کارهایی که انجام شده، به همراه توضیحاتشون به ترتیب زیر هستن:constructor به کامپوننت اضافه شده. این تابع که در حقیقت از تعاریف کلاس در جاوا‌اسکریپتبرگرفته شده، کارهای متفاوتی رو میتونه انجام بده. اما یادتون باشه، هر موقع که میدونستید کامپوننتتون قرار هست حالات مختلفی رو برای نمایش داشته باشه، حالت اولیش (Initial State) رو اینجا تعریف کنید. مهمترین نکته اینه که به محض تعریف کردن constructor، تابع super() فراخوانی بشه. اگر فراموش کنید که super() رو بلافاصله فراخوانی کنید، this که در حقیقت همون کامپوننت شماست و اطلاعات کامپوننت رو توی خودش داره، خالی خواهد موند و در نتیجه امکان استفاده از اِستِیت و بقیه ویژگی کامپوننت‌ها رو نخواهید داشت.قدم بعدی، داخل construct و زیر super()، استیت اولیه یا همون Default رو تعریف کردم. شکل تعریفش هم یه شئ ساده بوده که داخلش فقط از isHidden: false استفاده کردم تا بگم، در حالت عادی نمایش داده نمیشه (اینکه چطور و چه چیزی از این حالت استفاده میکنه و تغییر میکنه رو پایین‌تر توضیح میدم)یک تابعی رو تعریف کردم با اسم دلخواه toggleState که قرار هست موقع کلیک کردن دکمه، فراخوانی بشه. کاری هم که انجام میده، خیلی ساده، استیت رو تغییر میده. کد نوشته شده شاید شما رو یکم سردرگم کنه. تعریف کد به این شکله: isHidden: !this.state.isHidden و یعنی، مقدار جدید isHidden برابر خواهد بود با هر آنچه که this.state.isHidden بوده، اما چون یک ! هم اولش آوردم، یعنی اون مقدار رو بر عکسش کن. پس اگر this.state.isHidden برابر با false بود، مقدار جدیدش برابر با true میشه و برعکس.چون یک دکمه هم به کامپوننت اضافه کردم، باید کل اِلِمان‌ها رو داخل یک اِلِمان اصلی و والد جا بدم. برای همین هم، تمام المان‌ها رو داخل یک div گذاشتم.زمانی که کاربر روی دکمه کلیک میکنه، رویداد (Event) onClick اتفاق میوفته. اینجا بهش گفتم، زمانی که این رویداد اتفاق افتاد، تابع toggleState رو صدا بزنه. ضمنا از bind هم استفاده کردم، چون دکمه‌ها در حالت عادی، رویدادها رو انجام نمیدن و بایند (Bind) موظف هست تا حالت اصلی شئی که بهش پاس داده میشه رو حفظ و برای تابع مربوطه ارسالش کنه. در این مورد بعدا بیشتر توضیح میدم.و در نهایت، به المان ul گفتم، تا مخفی بودن یا نبودنش رو از this.state.isHidden بگیره. حالا، هر موقع که isHidden تغییر کنه، المان ul مجددا رِندِر میشه.برنامه رو تست کنید و ببینید که کارکردش چطوره. کارتون که تموم شد، میریم تا یکم دیگه با تئوری دست و پنجه نرم کنیم.درک مفاهیم ری‌اکتمهم‌ترین تفاوت کتاب‌خونه ری‌اکت با فرِیم‌وُرک‌هایی مثل انگولار، اینه که ری‌اکت فقط برای فرانت‌اند ساخته شده. در مورد ری‌اکت، چیزهای خیلی زیادی برای گفتن وجود داره. اما دوتا از ویژگی‌های اصلی ری‌اکت، داشتن مفاهیمی مثل Properties یا به طور خلاصه Prop و همچنین State هست که قبل‌تر کمی با مفهوم State آشنا شدیم. اینجا تصمیم دارم در مورد این دو و همچنین چرخه زندگی کامپوننت‌ها بیشتر توضیح بدم.Propsپراپ‌ها در واقع راهی برای ارتباط بین کامپوننت‌ها و جز ویژگی‌های اونها هستند (هرجا که شما کلاس React.Component رو استفاده یا همون extend کنید، میتونید ازشون بهره‌ ببرید). مهم‌ترین ویژگی پراپ‌ها، اینه که از سمت کامپوننت والد به فرزند منتقل میشن و اصطلاحا uni-directional (یک‌طرفه) هستن. زمانی هم وجود داره که شما مثل استِیت، پراپ‌های اولیه رو تعریف میکنید تا کامپوننت شما با اطلاعات اولیه (و نه حالات اولیه)، شروع به کار کنه. پراپ‌ها به شما کمک میکنن تا اطلاعات رو بین کامپوننت‌ها جابجا کنید، و زمانی که کاربر بخواد مستقیما روی خود کامپوننت تغییری اعمال کنه، باید از استیت استفاده بشه. بذارید با یک مثال ساده از پراپ استفاده کنیم:فرض کنید که توی کامپوننت ThisIsAComponent از یک تگ هدر h1 استفاده میکردیم و قرار بود مقدار داخلش رو توسط کامپوننت والد تغییر بدیم. کد جدیدمون به این شکل میشد (فقط تابع رِندِر رو گذاشتم و مابقی کد دست‌نخورده باقی مونده):render() {
 return (
            &lt;div&gt;
                &lt;h1&gt;{this.props.title}&lt;/h1&gt;
                &lt;button onClick={this.toggleState.bind(this)}&gt;Change&lt;/button&gt;
                &lt;ul hidden={this.state.isHidden}&gt;
                    &lt;li&gt;Item 1&lt;/li&gt;
                    &lt;li&gt;Item 2&lt;/li&gt;
                    &lt;li&gt;Item 3&lt;/li&gt;
                    &lt;li&gt;Item 4&lt;/li&gt;
                    &lt;li&gt;Item 5&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
 );
    }حالا باید مقداری رو برای title از کامپوننت والد، یعنی App در نظر بگیرم. کار آسونیه و به شکل زیر تغییری رو تو App.js ایجاد میکنم:...
&lt;ThisIsAComponent title={&quot;This is a new title&quot;}/&gt;
...Stateپراپ‌ها نباید تغییر کنن (به اصطلاح باید Immutable باشن)، برای همین از استیت استفاده میشه. در حالت عادی، کامپوننت‌ها استیت ندارن و از این جهت اصطلاحا بهشون Stateless گفته میشه. کامپوننت‌هایی که استیت پیدا میکنن، بهشون Stateful میگن.کاربرد استیت برای اینه که کامپوننت بتونه اطلاعاتی که در هر بازسازی دریافت میکنه رو حفظ کنه. زمانی که شما از this.setState() استفاده میکنید، وضعیت کامپوننت بروزرسانی و مجددا بازسازی میشه. تمام این فرایند بازسازی توسط ری‌اکت اتفاق می‌افته و خیلی هم سریعه.پراپ و استیت خیلی شبیه به هم هستند و تقریبا کار مشابهی رو انجام میدن، اما برای کارهای متفاوتی ازشون استفاده میشه. این امکام وجود داره تا خیلی از کامپوننت‌های شما Stateless باشن.چرخه زندگی کامپوننت‌ها (Component Lifecycle)کامپوننت‌ها به شما کمک میکنن تا یو‌آی (UI) رو به تیکه‌های کوچکتر تقسیم کنید. در حالت کلی، شما کامپوننت‌ها رو به شکل کلاس‌های جاوااسکریپت تعریف میکنید:class Greeting extends React.Component {
 render() {
 return &lt;h1&gt;Hello, {this.props.name}&lt;/h1&gt;;
  }
}اما کامپوننت‌ها صرفا جهت نمایش ساخته نمیشن و کارهای بیشتری میشه باهاشون انجام داد. اصطلاحا هر کامپوننتی برای خودش یک چرخه‌زندگی بخصوص یا Lifecycle داره که چندتا از پر کاربردترین‌ها رو توضیح میدم:constructor() که دقیقا قبل از بارگذاری کامپوننت توسط ری‌اکت خونده میشه. بهترین استفادش، تعریف state اولیه کامپوننت هست. اگر کامپوننت stateless باشه، نیازی به تعریف این تابع نیست.componentWillMount() دقیقا قبل از بارگذاری خونده میشه. و قبل از تابع render() اتفاق میوفته. به همین خاطر تعریف استیت تو این تابع پیشنهاد نمیشه. این تابع سمت سرور کارهاش رو انجام میده و اصطلاحا server-side هست. (در این مورد تو بخش Isomorphism توضیح میدم)componentDidMount() بعد از اینکه کامپوننت بارگذاری شد، خونده میشه. این تابع بهترین جا برای ارسال درخواست‌ها به سرور شماست و اگر استیت رو تو این تابع با استفاده از تابع this.setState() تغییر بدید، باعث میشید که باز دوباره تابع render() فراخوانی بشهcomponentWillReceiveProps(nextProps) زمانی فراخوانی میشه، که شما از طریق کامپوننت والد، پراپ‌های کامپوننت فرزند رو تغییر بدید و بخواید استیت جدید رو بر اساس پراپ‌های جدید تنظیم کنید. برای اینکار میتونید آرگومان‌های nextProps و this.props رو با هم مقایسه کرده و تغییرات رو ایجاد کنید. (مقایسه رو حتما انجام بدید!)componentWillUpdate(nextProps, nextState) قبل از بارگذاری مجدد رخ میده، اگر پراپ‌ها و استیت‌های کامپوننت تغییری کرده باشن.componentDidUpdate(prevProps, prevState) بلافاصله بعد از بارگذاری مجدد اتفاق میوفته و به شما این امکان رو میده تا المان‌ها رو دستکاری کنید.componentDidCatch(error, info) برای مدیریت اِرورها و خطاها تو UI استفاده میشه.مطالعه بیشتر…جمع‌بندیپراپها استفاده میشن تا اطلاعات از کامپوننت والد به کامپوننت فرزند یا حتی داخل کامپوننت فرزند منتقل بشن. پراپ‌ها تغییرناپذیر یا به اصطلاح Immutable هستند و نباید در هر رندر تغییر کنند.استیت برای این استفاده میشه تا اطلاعات رو تغییر بدیم، یا اطلاعات تغییر یافته رو نمایش بدیم و اصطلاحا تغییر پذیر یا Mutable هستند. مثلا کاربر چیزی رو در سایت سرچ میکنه و بلافاصله زیرش تعدادی از نزدیک‌ترین نتایج جست‌وجو نمایش داده میشه.مفهوم Isomorphic یا Universalزمانهای قدیم، قبل از موقعی که NodeJS بین برنامه‌نویس‌ها محبوب بشه، جاوااسکریپت زبانی بود که باهاش تغییراتی رو تو صفحه‌های وب ایجاد میکردن تا صفحه‌ها از حالت مرده و استاتیک خارج بشن. تا اون موقع زبان جاوااسکریپت، زبانی بود که تو مرورگر کاربر اجرا میشد و به اصطلاح Client Side یا سمت کاربر بود. بعد از ظهور NodeJS جاوااسکریپت این قابلیت رو پیدا کرد که تو محیط سمت سرور هم اجرا بشه و بعد از اون جاوااسکریپت به یک زبان Server Side هم تبدیل شد.ایزومورفیزم (Isomorphism) از ریاضیات گرفته شده و «هم‌سان» معنی میشه. چون واژه ایزومورفیک برای برنامه‌نویس‌ها کمی مشکل‌ساز میتونه باشه، به جاش از واژه یونیورسال (Universal) هم استفاده میکنن.ایزوموفیک در شاخه وب، به معنی ساخته شدن صفحه سمت سرور یا سمت کاربر هست و در حالت کلی به NodeJS و خود JavaScript اشاره میکنه. برای اینکه تعریف رو ساده‌تر کنم، اینطور در نظر بگیرید که، کدی که سمت سرور ساخته شده، به صورت HTML به کاربر ارسال میشه و کاربر میتونه تو کد صفحهش اون رو ببینه. اما کدی که سمت کاربر ساخته میشه، تو کدهای صفحه قابل مشاهده نیست. اینجا لازم هست که به این نکته اشاره کنم، که منظور از سرور، الزاما بک‌اند نیست، و اونچه که مد نظر هست، ابزاریه که وظیفه تبادل ارتباطات رو به عهده داره.دلایل مختلفی وجود دارن که برنامه‌نویس‌ها به اپ‌های ایزومورف علاقه‌مندند:بهبود سئو،پرفورمنس بهتر،و نگهداری راحت‌تر.یکی از مضوعاتی که خیلی در این مورد مهم هست، اینه که کد‌های ایزومورفیک که سمت کاربر ساخته شدن، توسط موتورهای جست‌وجو به خوبی خونده نمیشن، برای همین هم اپ‌های SPA معمولا با این ساختار دچار مشکل میشن و لازم هست تا کدشون سمت سرور ساخته بشه. (سرور رو الزاما با کامپیوتر سرور اشتباه نگیرید!)Promise و درک ناهم‌گام‌سازی (Asynchronous)بیاید با هم یه دنیای جالبی رو تجسم کنیم، تو این دنیای ما، هنوز گوگل وجود نداره و شما رئیس یک شرکت «پاسخ به سوالات» هستید. نحوه کار به این شکله که کاربر سوال خودش رو بسته‌بندی میکنه (Data Package) و اون رو به یک پست‌چی میده، پست‌چی این بسته رو میاره برای شرکت شما (Request) و شما بسته رو باز میکنید، به سوال جواب میدید و اون رو به پست‌چی میدید و ایشون هم برای کاربر جواب رو میبره (Response). پروسه تا اینجا واضحه فقط چند شرط وجود داره:از اونجایی که شرکت ما خیلی خاصه :دی،کاربر زمانی که بسته رو به پست‌چی میده، باید دم در خونه صبر کنه تا پست‌چی برگرده (و از کار و زندگیش هم می‌افته)پستچی تا زمانی که شما پاسخ رو بسته‌بندی نکردید و بهش تحویل ندادید پیش شما میمونه.این روش ارتباط، روش هم‌گام یا اصطلاحا Synchronous نام داره و همون روش قدیمیه کار با اینترنته، کد PHP مینوشتیم و با هربار کلیک رو دکمه، کاربر باید منتظر صفحه جدید میموند و نمیتونست کارهای دیگه توی سایت رو انجام بده.حالا شرکتمون رو کمی پیشرفته‌تر میکنیم، فرایند همون شکل قبلی رو داره اما:زمانی که کاربر درخواستش رو بسته‌بندی کرد و به پست‌چی داد، برمی‌گرده خونش و کارهاش رو انجام میدهشما فقط یک پست‌چی ندارید و پست‌چی‌ها میتونن از کاربر درخواست‌های مختلفی رو بگیرن و برای شما بیارناین نوع ارتباط، ارتباط نا‌هم‌گام یا Asynchronous نام داره و خیلی تو وب‌اپ‌های SPA پر کاربرده و AJAX یکی از معروف‌ترین تکنیک‌ها برای برقراری این نوع ارتباطهاست. تو نسخه‌های جدید جی‌اس، برای اینکه کاربر رو منتظر نذاریم بعد از اینکه درخواستش رو ارسال کرد، بهش قول میدیم که در آینده جوابی رو برای درخواستش ارسال میکنیم، و کاربر میتونه به کارش ادامه بده و ماهم پردازشمون رو انجام میدیم. اینجاست که پرامِس (پرامیس؟) یا همون Promiseها خودشون رو نشون میدن.قبل از معرفی شدن پرامس‌ها، تو جاوااسکریپت از Callbackها استفاده میشد، کال‌بک‌ها توابعی بودن که مثلا به عنوان آرگومان یک تابع دیگه تعریف میشدن، تا هنگام بُروز یک رویداد خاص (Event) کار خاصی رو هم انجام بدن. مشکل اینجا بود که ایده‌ی کال‌بک‌ها، هرچقدر هم که قشنگ بوده، تو پردازش‌های پیچیده مدیریت کد رو خیلی سخت میکرده و به اصطلاح، برنامه‌نویس رو وارد جهنم کالبَک‌ها یا همون Callback-Hell میکرده. برای همین پرامس‌ها ساخته شدند تا جایگزینی برای کال‌بک‌ها باشن.پرامس‌ها یا جوابی رو برمیگردونن یا اینکه دلیلی رو برای عدم انجام موفقیت‌آمیز اون فرایند ارائه میدن. از اینجا میشه گفت که پرامس‌ها ساختار مشابهی مثل try/catch دارن و از همه مهمتر، سه وضعیت کلی رو شامل میشن:Pending: که یعنی در حال انجام کاری هستند،fulfilled: که یعنی کارشون رو به خوبی انجام دادن وrejected: که یعنی از پس کاری که بهشون داده شده بر نیومدن.یه مثال ساده برای اینکه با نمونه‌ای از یک پرامس آشنا بشید به این شکله:fetch(url)
 .then(process)
 .then(save)
 .catch(handleErrors)اینجا، تابع process صبر میکنه تا کار تابع fetch تموم بشه، بعد تابع save منتظر process میمونه و اگر هرکدوم از این توابع جایی به مشکل خوردند، تابه handleErrors وظیفش رو انجام میده.اگر هرکدوم از این توابع، پرامس باشن، میتونن ساختار مشابهی رو برای خودشون بگیرن، در واقع این قابلیت رو به شما میدن تا بتونید پرامس‌ها رو تودرتو کنید.استفاده از fetchحالا که متوجه مفهوم ایزومورفیک و همچنین درخواست‌های نا‌همگام شدید، بریم تا با یه مثال تو پروژمون به درک بیشتری ازشون برسیم.قدم اول، نصب کتابخونه isomorphic-fetch از مخازن npm هست. fetch یکی از کتابخونه‌های مورد علاقه‌ی من که در کنارش کتابخونه axios وجود داره. تفاوت عمده این دو کتابخونه، تو پردازش اطلاعات هست و اکسیوس برای ای‌اس۶ آمادگی بیشتری داره، منتهی من طبق عادت پیش میرم و از فِچ (fetch) استفاده میکنم.$ npm install --save isomorphic-fetchکتابخونه رو نصب کنید، اینکه واژه ایزومورفیک اولش استفاده شده، نشون میده که این کتابخونه رو، هم میشه سمت سرور و هم سمت کاربر استفاده کرد. حالا، کامپوننت ThisIsAComponent رو یکمی تغییر میدیم. در نهایت کدمون باید به شکل زیر بشه:import React from &quot;react&quot;;
import fetch from &quot;isomorphic-fetch&quot;;

export default class ThisIsAComponent extends React.Component {
 constructor() {
 super()

 this.state = {
            done: true,
            items: \[\]
        }
    }

 fetchData() {
 this.setState({
            done: false
        });

 fetch(&#039;http://jsonplaceholder.typicode.com/posts&#039;)
 .then(data =&gt; {
 data.json()
 .then(res =&gt; {
 this.setState({
                    done: true,
                    items: res
                })
            })
        })
 .catch(error =&gt; {
 console.log(error)
        })
    }

 render() {
 return (
            &lt;div&gt;
                &lt;h1&gt;{this.props.title}&lt;/h1&gt;
                &lt;button onClick={this.fetchData.bind(this)}&gt;Get Data&lt;/button&gt;
                &lt;p hidden={this.state.done}&gt;Loading&lt;/p&gt;
                &lt;div&gt;
 {
 this.state.items.map(item =&gt; {
 return (
                                &lt;p&gt;{item.title}&lt;/p&gt;
 )
                        })
 }
                &lt;/div&gt;
            &lt;/div&gt;
 );
    }
}خط به خط بریم جلو ببینیم چه اتفاقی افتاده:اول، از کتابخونه isomorphic-fetch شئ fetch رو فراخوانی کردم.تو تابع constructor، استیت اولیه رو تغییر دادم و به جای isHidden که اول داشتیم، done رو، که وظیفه نگهداری از وضعیت بارگذاری آیتم‌ها رو به عهده داره و items که نگهدارنده آیتم‌های دریافت شده از سرور هستند رو ساختم.تابع toggleState رو پاک کردم و به جاش از fetchData استفاده کردم. اسمش رو هم خودم انتخاب کردم. داخل این تابع اتفاقات جالبی میوفته.زمانی که این تابع خونده میشه (یا در واقع رو دکمه‌ای کلیک میشه که باید این تابع رو اجرا کنه) وضعیت done به false تغییر پیدا میکنه. چون در حقیقت آیتمی دریافت و کار ما هم تموم نشده.قدم بعدی، از fetch استفاده کردم تا از یک آدرس پیش‌فرض، یک‌سری اطلاعات الکی رو دریافت کنم. نکته مهم اینه که fetch یک پرامس هست و وضعیتش رو میشه کنترل کرد. برای همین، تو خط پایینش گفتم، هر موقع که دریافت اطلاعات تموم شد، از اطلاعات دریافت شده که اسمشون رو data گذاشتم استفاده کن و…یکی از مهم‌ترین تفاوت‌های fetch و axios تو این مرحلست، پاسخی که fetch به شما برمیگردونه، یک پاسخ خام هست و باید تبدیل به دیتای قابل خوندن بشه. fetch این کار رو با برگردوندن یک پرامس انجام میده (برای نوشتن توابع از Arrow Functionها استفاده کردم). پس گفتم، زمانی که جواب رو از سرور گرفتی، اون رو به json تبدیل کن (که خود تابع json یک پرامس برمیگردونه) و بعد از اینکه عمل تبدیل به json درست انجام شد، از حاصلش استفاده کن تا دوباره استیت رو تغییر بدی.done رو هم برابر با true کردم تا نشون بدم عمل دریافت اطلاعات کامل شده. در نهایت نتیجه حاصل از دریافت اطلاعات، یا همون آیتم‌های مورد نظرم رو، که حالا تبدیل به json شدند، داخل items استیت ذخیره کردم.اینکار باعث میشه که ری‌اکت، یکبار دیگه کامپوننت‌هایی که از این استیت استفاده میکنن رو بارگذاری کنه. در نهایت هم بررسی میکنه که آیا اشکالی وجود داشته تو کل این فرایند یا نه.آخر سر، تو تابع render دکمه Get Data رو به تابع fetchData وصل کردم. یک تگ p هم اضافه کردم که بهش گفتم، وضعیت hidden بودنش رو از done موجود تو استیت بگیره. (هر موقع که بارگذاری تموم شده بود، این المان محو میشه و هرموقع بارگذاری در حال انجام بود، این المان نمایش داده میشه)داخل المان div که به جای ul نشسته، با استفاده از تابع map() که شکل جدیدی از forEachهست، آیتم‌ها رو نمایش دادم. (پایین‌تر درمورد map توضیحات بیشتری میدم)ادامه مطلب در سایت خودم…</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Tue, 22 May 2018 15:47:59 +0430</pubDate>
            </item>
                    <item>
                <title>نکست‌جی‌اس و ریداکس‌تانک، از مبتدی تا پیشرفته</title>
                <link>https://virgool.io/iran-react-community/%D9%86%DA%A9%D8%B3%D8%AA%D8%AC%DB%8C%D8%A7%D8%B3-%D9%88-%D8%B1%DB%8C%D8%AF%D8%A7%DA%A9%D8%B3%D8%AA%D8%A7%D9%86%DA%A9-%D8%A7%D8%B2-%D9%85%D8%A8%D8%AA%D8%AF%DB%8C-%D8%AA%D8%A7-%D9%BE%DB%8C%D8%B4%D8%B1%D9%81%D8%AA%D9%87-uzcgpsjoceof</link>
                <description>مقدمه خیلی از دوستان من با موضوعات مختلفی خصوصا در زمینه جاوا‌اسکریپت دچار مشکل شدن. بعضی از مفاهیم رو نفهمیدن و یا نمیدونستن از کجا باید شروع کنن. برای همین تصمیم گرفتم که این مطلب رو بنویسم. قصد دارم اینجا برای سطوح مبتدی تا پیشرفته در مورد ری‌اکت و نکست‌جی‌اس و همچنین ریداکس توضیح بدم. و سعی میکنم این مطلب رو تا حد امکان گسترده کنم تا تمامی مواردی که برای یک برنامه‌نویس خوب شدن لازم هست رو پوشش بدم.اما اساسا چرا این مطلب رو نوشتم؟ خب، اول از همه اینکه بتونم هر آنچه که بلد هستم رو یک‌جا نگه دارم و بعدا هم ازش استفاده کنم. دوم اینکه همچین آموزشی رو تقریبا هیچ‌کجای وب، و خصوصا تو سایت‌های ایرانی پیدا نکردم.متنی که اینجا نوشته شده، حاصل چند سال تلاش من برای یادگیری، و تقریبا یک ماه برای خلاصه‌کردن تمام اون اطلاعات بود تا بتونم یک مرجع کامل رو بسازم، سعی کردم خط به خط کدها رو توضیح بدم و ریپازیتوری گیت رو باهاش سینک و همگام نگه‌دارم. از اینکه این مطالب به دست دیگران هم برسه و کمک به چند نفر بکنه واقعا خوشحال میشم، اما تنها خواهش من از خوانندگان و شما، اینه که اگر این مطلب رو جایی به اشتراک میذارید، منبع اون رو هم ذکر کنید.همچنین مطلب کامل رو در سایت خودم میتونید پیدا کنید و در مورد ری‌اکت و نکست‌جی‌اس بیشتر مطالعه کنید.سپاس.جاوا‌اسکریپت و اکما‌اسکریپت (ECMAScript)اولین چیزی که لازم هست بدونید، اینه که جاوا‌اسکریپت توسط شرکت نِت‌اِسکیِپ (شرکت قدیمی موزیلا فایرفاکس) ساخته و به سازمان اِکما داده شد تا اون رو استانداردسازی کنن. اِکما سازمانیه که وظیفش استانداردسازی اطلاعاته.اونچه که در نهایت از جاوا‌اسکریپت توسط سازمان اِکما ارائه شد، اِکما‌اِسکریپت بود. ساده‌تر بگم، اِکما‌اِسکریپت یک استاندارد هست، در حالی که جاوا‌اسکریپت محبوب‌ترین پیاده‌سازی از اون استاندارد به حساب میاد. جاوا‌اِسکریپت، اِکما‌اِسکریپت رو پیاده‌سازی میکنه و بر پایه اون ساخته میشه.حالا سوالی که مطرح میشه، اینه که &quot;ES&quot; چیه؟ای‌اِس، مخفف اِکما‌اِسکریپته (ECMAScript)، هرجایی که ای‌اِس رو در کنار یک عدد دیدید، مثل ای‌اس۶، یادتون باشه که داره به یک نسخه از اِکما‌اِسکریپت یا در واقع یک نسخه از استاندارد اشاره میشه.ای‌اِس (ES)ای‌اِس تا به اینجا ۸ نسخه مختلف رو ارائه کرده، ای‌اِس۱، ۲، ۳ و ۴ بین سال‌های ۱۹۹۷ تا ۱۹۹۹ ارائه شدن و دیگه ازشون پشتیبانی نمیشه. (ما هم کاری بهشون نداریم).ای‌اِس۵ تقریبا ۱۰ سال بعد از اس‌اس۴ یعنی اواخر سال ۲۰۰۹ (تاریخ دقیق رو نمیدونم) ارائه داده شد.ای‌اِس۶ در سال ۲۰۱۵ منتشر شد که برای راحتی کار، بهش ای‌اس۲۰۱۵ هم میگن. در واقع چون ای‌اس۶ در سال ۲۰۱۵ ارائه شده، بهش ای‌اِس۲۰۱۵ میگن!ای‌اِس۷/ای‌اس۲۰۱۶ که مطمئنا میتونید پیشبینی کنید در سال ۲۰۱۶ منتشر شد.ای‌اس۸/ای‌اس۲۰۱۷ هم، در سال ۲۰۱۷ منتشر شد.چرا ورژن‌های مختلف از ای‌اس منتشر شدن؟دلیلش اینه که هر وِرژِن، ویژگی‌های جدیدی رو ارائه کرده که با زمان خودش هم‌خوانی داشته باشه. فقط باید چند نکته رو به خاطر داشته‌باشید:پیشبینی میشه که هر سال یک نسخه جدید از اِکما‌اِسکریپت ارائه بشه،اولین نسخه‌های اِکما‌اِسکریپت با عدد نسخه‌بندی میشدن، مثل ای‌اِس۱، ای‌اِس۲ و...نسخه‌های جدید که از سال ۲۰۱۵ شروع شدن، به شکل ای‌اس[سال انتشار] نام‌گذاری میشن.اکما یک استاندارده، جاوا‌اسکریپت محبوب‌ترین پیاده‌سازی از اون استاندارد هست.چرا ای‌اس۶؟نسخه ۶‌ام از اِکما‌اِسکریپت، ویژگی‌های خیلی خوبی رو به زبان جاوا‌اسکریپت اضافه کرد، و همین، یکی از دلایلی شد که ری‌اَکت به طور پیش‌فرض ازش پشتیبانی میکنه. مثلا مفاهیمی مثل «کلاس‌ها» و «ماژول‌ها»، که برای زبان‌های شئ‌گرا اجباری هستند، بهش اضافه شدن. از جمله ویژگی‌های دیگش، اضافه شدن دستورات for، جِنِراتور‌های شبیه به زبان پایتون، توابع فِلِشی (Arrow Function)، کالِکشِن‌ها، پرامِس‌ها (Promise) و غیره بوده.متاسفانه هنوز مرورگرها پشتیبانی از ای‌اِس۶ رو کامل نکردن و ای‌اِس۶ به خودی خود تو مرورگرها پشتیبانی نمیشه. اینجاست که مفاهیم تِرَنس‌پایلِرها (transpiler) خودشون رو نشون میدن که بعد از توضیح توابع فِلِشی (برای راحتی کار میگم اَرو فانکشِن) بهشون میپردازم.Arrow Functionsیکی از ویژگی‌های خیلی خوبی که توی ای‌اِس۶ وجود داره، استفاده از اَرو فانکشن‌هاست. به اسمش دقت نکنید، مفهومش خیلی سادست. ارو فانکشن‌ها، در واقع همون توابع قدیمی جاوااسکریپت هستند (با ویژگی‌های جدید‌تر که اینجا بهشون کاری نداریم) که تو ای‌اس۶ به شکل دیگه‌ای تعریف میشن و موقع تِرَنس‌پایل (یکمی پایینتر توضیح میدم در این مورد) به شکل توابع جاوااسکریپت درمیان، مثلا:x =&gt; {
  return x * x;
}

(m, n) =&gt; {
  return m+n
}

data =&gt; {
  data.json()
  .then(result =&gt; {
    return result;
  })
}بعد از تِرَنس‌پایل تبدیل میشن به:(function (x) {
  return x * x;
});

(function (m, n) {
  return m + n;
});

(function (data) {
  data.json().then(function (result) {
    return result;
  });
});ترنس‌پایلر (transpiler)حتما تا به حال واژه‌های «کامپایلِر» و «مفسر» به گوشتون خورده. تِرَنس‌پایلِرها در واقع نوعی کامپایلر هستند با یک تفاوت اصلی:کامپایلرها معمولا زبان رو به یک نسخه قابل اجرا برای ماشین تبدیل می‌کنن، مثلا زبان سی، کدهای باینری یا همون صفر و یک میسازه، یا جاوا بایت‌کد رو تولید میکنه.این درحالیه که ترنس‌پایلرها، یک سورس‌کد رو به یک سورس‌کد دیگه تبدیل می‌کنن (یا مثلا به یک زبان دیگه که مستقیم برای ماشین قابل درک نیست و باید دوباره کامپایل، اینتِرپرِت یا همون تفسیر بشه). مثلا کافی‌اسکریپت (CoffeeScript) که از خودش جاوا‌اسکریپت تولید میکنه، یا بابِل (Babel) که ای‌اس۶ رو به ای‌اس۵ (قابل پشتیبانی برای مرورگرها) تبدیل می‌کنه.بابِل یا بِیبِل (Babel) یک ترنس‌پایلر برای ای‌اس۶ هست که اون رو به ای‌اس۵ تبدیل میکنه. ای‌اس۵ توسط مرورگرها خیلی خوب پشتیبانی میشه و در حقیقت، ای‌اس۵ همون جاوا‌اسکریپتیه که عموما باهاش آشنایی دارن.بابِل، بِیبِل...؟ (Babel)بابل یک تِرَنس‌پایلِر برای جاوا‌اسکریپته. بابل رو اکثرا بخاطر توانایی خوبش تو تبدیل ای‌اس۶ به ای‌اس۵ میشناسن.به عنوان مثال این کد که با ای‌اس۶ نوشته شده:let input = [1, 2, 3];
console.log(input.map(item =&gt; item + 1)); // [2, 3, 4]توسط بابل تبدیل میشه به کد ای‌اس۵:var input = [1, 2, 3];
console.log(input.map(function (item) {
  return item + 1;
})); // [2, 3, 4]که تقریبا همه‌جا قابل اجراست. بابل خیلی خوب از پُلی‌فیل‌های جاوا‌اسکریپت پشتیبانی میکنه و باعث میشه که کد جاوا‌اسکریپت ساخته شده برای مرورگرهای قدیمی هم قابل پشتیبانی باشه. به همین خاطر، بابل باعث میشه شما از تمام ویژگی‌های ای‌اس۶ استفاده کنید بدون اینکه پشتیبانی از نسخه‌های قدیمی مرورگرها رو از دست بدید (مفهوم پُلی‌فیل اینجا معلوم میشه).فرانت‌اند و مفاهیم اِس‌پی‌اِی (SPA)اطلاعاتی که ما در اینترنت میبینیم، مجموعه‌ای از کدهای HTML، JavaScript و CSS هستن. قدیم‌ها، زمانی که خیلی از برنامه‌نویس‌ها از PHP (هنوز هم استفاده میکنن) برای نوشتن صفحات وب استفاده می‌کردن و جِی‌اِس مثل امروز محبوب نبود، هر صفحه از سایت باید بصورت جداگانه نوشته می‌شد. و زمانی که کاربر روی یک لینک کلیک میکرد، کل صفحه از اول رِندِر (Render) می‌شد. این فرایند برای کاربر، خسته‌کننده و طاقت‌فرسا بود و حتی گاهی بخاطر زمان زیادی که باید برای بارگذاری صفحه صرف میکرد، از ادامه کارش پشیمون میشد.کم‌کم تکنیک‌هایی مثل اِی‌جَکس (AJAX) استفاده شدن، که مثلا وقتی صفحه در حال بارگذاری بود، شروع میکرد یک نماد کوچک لودینگ و بارگذاری (بهش معمولا میگن اِسپینِر یا spinner) رو نشون دادن و کاربر رو متوجه میکرد که اطلاعات در حال ارسال و دریافتن.این ایده، که اطلاعات تو یک صفحه بارگذاری بشن و کاربر مدام مجبور به عوض کردن صفحه‌ها نشه (مگر در مواقع لازم) باعث ایجاد تعریف جدیدی از وب‌اَپلیکِیشِن‌ها شد، اِس‌پی‌اِی (SPA) یا Single Page Application راهش رو به لغت‌نامه‌ی برنامه‌نویس‌ها باز کرد!SPA هدفش ایجاد یک تجربه کاربری بهتر برای کاربرهاست. در حقیقت، SPA کار رو برای برنامه‌نویس سخت‌تر و برای کاربر راحتتر کرد. تو یک اپلیکیشن SPA ایده‌آل، کاربر شما متوجه عوض شدن صفحه‌ها نمیشه و احساس میکنه که همه‌چیز در حال رخ‌دادن تو یک صفحست.اما داستان سمت برنامه‌نویس کمی فرق می‌کنه. کاربر زمانی میتونه اطلاعات رو تو مرورگرش ببینه، که کد‌های HTML ساخته شده باشن، و این یعنی برنامه‌نویس باید با هر درخواست کاربر، یا کلا صفحه رو از اول بارگذاری کنه (که دیگه SPA نیست) یا اینکه اون قسمتی از سایت رو که مرتبط با کاربر هست یا نیاز به تغییر داره رو مجددا با داده‌های جدید که از سمت سرور اومدن بارگذاری کنه.اینجاست که سایت شما، تا حدود زیادی از سمت سرور خودش جدا میشه و مفهوم جدیدی به عنوان فرانت‌اِند (Front End) رو تعریف می‌کنه. فرانت‌اند و بَک‌اِند، در زمان‌های دور وجود نداشتن یا خیلی به هم نزدیک بودن. شما یک سایت رو کامل می‌نوشتید و مثلا تو یک صفحه PHP، همزمان از HTML و JavaScript استفاده می‌کردید. هر زمان که کاربر درخواست صفحه‌ی جدیدی رو میداد، شما یک اسکریپت جدید رو بارگذاری و صفحه‌های مربوطه رو از نو بازنویسی می‌کردید.زمانی که تعاریف فرانت‌اند و بَک‌اند ایجاد شدند، طراحی سایت شکل جدیدی به خودش گرفت. فرانت‌اند یجورایی بیشتر نماد طراحی سایت شد و بَک‌اند بیشتر نماد منطق کاری (Business Logic). کدها سمت بک‌اند نوشته می‌شن و اطلاعات رو موقع نیاز به فرانت‌اند ارسال می‌کنن. از اینجا به بعد، برنامه‌نویس فرانت نیازی نداره که نگران SQL و دستورات مربوط به ارتباط با پایگاه داده و دریافت محصولات از اون باشه، یا حتی نگران فرایند عضویت و ورود به سایت. فرانت‌اند خودش رو بیشتر با بهبود تجربه کاربری درگیر کرد. لازم هست که بگم، این یک مفهوم کلی و جداسازی کلی بک‌اند و فرانت‌اند هست. اینکه وظیفه‌ی برنامه‌نویس چی باشه، نسبت به هر پروژه قابل تغییر هست و امرو، خیلی از برنامه‌نویس‌ها به هرد شاخه بَک و فرانت تسلط دارن.اینجا بود که مارس ۲۰۱۳، فیسبوک اولین نسخه از کتاب‌خونه ری‌اَکت رو ارائه داد...ری‌اکت (React)ری‌اَکت یا ری‌اَکت‌جِی‌اِس، یک کتابخونست برای ساختن روابط کاربری. ری‌اکت به برنامه‌نویس این اجازه رو میده، که بتونه وب‌اپلیکیشن‌های بزرگی رو بسازه که از اطلاعات مختلفی استفاده می‌کنن و میتونن تو یک صفحه تغییر کنن، بدون اینکه صفحه رو مجدد لود کنن (مفهوم SPA). هدف اصلی سازندگان ری‌اکت، سرعت، سادگی و مقیاس‌پذیری بوده.ری‌اکت صرفا تلاش میکنه تا رابط کاربری رو از راه Virtual-DOM تغییر بده. اینکه این ساز.کار به چه صورتی هست رو فعلا تشریح نمیکنم اما، اگر با معماری MVC آشنا باشید، ری‌اکت اون قسمت &quot;V&quot; رو به خودش اختصاص میده و میتونه با بقیه کتابخونه‌های جی‌اس خودش رو وفق بده.یکی دیگه از اَشکال ری‌اکت، ری‌اَکت‌نِیتیو هست که کمک میکنه، نرم‌افزارهای (اکثرا موبایل) نِیتیو یا سازگار با سیستم‌عامل توسط ری‌اکت ساخته بشن. ضمنا ری‌اکت از جی‌اس‌اکس (JSX) برای نمایش و ساخت المان‌ها استفاده میکنه که توضیح میدم در این مورد.جی‌اس‌اکس (JSX)جِی‌اِس‌اِکس، یک زبان مشابه با HTML یا XML که کمک میکنه، تیکه‌های سایت (Component) جدای از هم ساخته بشن و به شکل یک شئ جاوا‌اسکریپت در بیان.ساده‌تر بگم، با JSX میشه ساختارهای مشابه به HTML رو ساخت. مثال:var nav = (
    &lt;ul id=&quot;nav&quot;&gt;
      &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Home&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#&quot;&gt;About&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Clients&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Contact Us&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
);اینجا، nav به عنوان یک کامپونِنت (Component) شناخته میشه. و شما میتونید جاهای مختلف برنامه، ازش استفاده کنید (یکبار بنویسید و چندبار استفاده کنید).این استفاده از JSX یکی دیگه از ویژگی‌های ری‌اکت به حساب میاد! اینکه شما برنامتون رو به تیکه‌های کوچکتری تقسیم می‌کنید و میتونید در جاهای مختلفی ازش استفاده کنید.کمی بیشتر در مورد ری‌اکتدنیای ری‌اکت جالبه. فرض کنید که یک کامپوننت رو ساختیم، مثلا یه لیست از محصولات. بعد کاربر روی یکی از محصولات کلیک میکنه، صفحه محصول باز میشه و کاربر محصول رو میبینه. کاری که ری‌اکت انجام داده چیه؟ ری‌اکت متوجه میشه که کدوم قسمت‌های سایت باید تغییر کنن و فقط اونها رو تغییر میده! پس اول شناسایی میکنه که چه چیزی تغییر کرده، و بعد تغییرات رو اعمال میکنه. ری‌اکت، به جای اینکه کل صفحه رو از اول بازسازی کنه، فقط قسمت‌هایی که تغییر کردند یا به نوعی وضعیتشون تغییر کرده رو با داده‌های جدید پر می‌کنه و اونها رو از نو میسازه و خیلی هم سریع این کار رو انجام میده!نصب و شروع کار با ری‌اکتتصمیم ندارم اینجا به طور عمیق وارد ری‌اکت بشم و کد منبع ری‌اکت رو تشریح کنم، هدفم اینه که فضای کلی برای ورود به نکست‌جی‌اس رو ایجاد و شما رو با ساختار کلی و نحوه کار با ری‌اکت آشنا کنم. پس پیش میریم برای نصب ری‌اکت‌جی‌اس و یک آشنایی کلی با این کتابخونه.نصاب ری‌اکتنصاب ری‌اکت، که توسط فیسبوک ساخته شده، تو مخازن npm موجوده و میتونید اون رو به صورت عمومی توی سیستم‌عاملتو بریزید:$ npm install -g create-react-app

# ساخت نرم‌افزار
$ create-react-app my-app-name

# نصب وابسته‌ها (Dependencies)
$ cd my-app-name
$ npm installمطمئن باشید که حتما  npm رو روی کامپیوترتون نصب کردید. یکی از مهم‌ترین ویژگی‌های  create-react-app اینه که تمام ابزارهای لازم رو از قبل برای شما فراهم کرده. مثلا از قبل Babel برای شما نصب شده و نیازی نیست که خودتون رو درگیر نصب و راه‌اندازیش بکنید. حالا میریم سراغ یک توضیح در مورد ساختار این کتابخونه.ساختار پوشه‌هااگر داخل پوشه  public رو ببینید، متوجه حضور فایل index.html میشید. این فایل در حقیقت نقطه شروع برنامست و حتما باید وجود داشته باشه، این یکی از بایدهای برنامه‌های ساخته شده با  create-react-app هست. یه نگاهی به داخل این فایل میندازیم:&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot;&gt;
    &lt;meta name=&quot;theme-color&quot; content=&quot;#000000&quot;&gt;
    &lt;!--
      manifest.json provides metadata used when your web app is added to the
      homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
    --&gt;
    &lt;link rel=&quot;manifest&quot; href=&quot;%PUBLIC_URL%/manifest.json&quot;&gt;
    &lt;link rel=&quot;shortcut icon&quot; href=&quot;%PUBLIC_URL%/favicon.ico&quot;&gt;
    &lt;!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike &quot;/favicon.ico&quot; or &quot;favicon.ico&quot;, &quot;%PUBLIC_URL%/favicon.ico&quot; will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    --&gt;
    &lt;title&gt;React App&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;noscript&gt;
      You need to enable JavaScript to run this app.
    &lt;/noscript&gt;
    &lt;div id=&quot;root&quot;&gt;&lt;/div&gt;
    &lt;!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the &lt;body&gt; tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    --&gt;
  &lt;/body&gt;
&lt;/html&gt;همینطور که میبینید، این فایل چیز خاصی رو داخل خودش نداره. به جز خط ۲۸ام. که اِلِمانی تعریف شده با آی‌دی  root، این رو تا اینجا توی ذهنتون داشته باشید. اتفاقی که از اینجا به بعد رخ میده، توی فایل  src/index.js قرار داره. بذارید یه نگاهی هم به این فایل بندازیم:import React from &#039;react&#039;;
import ReactDOM from &#039;react-dom&#039;;
import &#039;./index.css&#039;;
import App from &#039;./App&#039;;
import registerServiceWorker from &#039;./registerServiceWorker&#039;;

ReactDOM.render(&lt;App /&gt;, document.getElementById(&#039;root&#039;));
registerServiceWorker();این فایل هم یکی از فایل‌هایی هست که حتما باید وجود داشته باشه. دلیلش اینه که تو تتظیمات  create-react-app این دو فایل به عنوان نقاط شروع برنامه تعریف شدند. خود create-react-app این دو فایل رو به هم متصل میکنه و زمانی رو که شما لازم هست خودتون بذارید تا تنظیمات رو انجام بدید، براتون ذخیره می‌کنه. میریم سراغ بررسی این فایل:اول از همه، این کد با استاندارد ای‌اس۶ نوشته شده. اگر قرار بود از استاندارد ای‌اس۵ (یا به اصطلاح Common JS) پیروی کنیم، باید مینوشتیم:  var React = require(&quot;react&quot;); تا کلاس ری‌اکت رو به پروژه اضافه کنیم. بعدا به این خواهیم پرداخت که این خط چه کارهایی انجام میده. فعلا بریم سراغ خط بعد.تو خط دوم، شئیی به نام  ReactDOM فراخوانی شده. برای اطلاعاتون، قبل از نسخه ۰.۱۴ ری‌اکت، کتابخونه‌های  react و react-dom یکی بودن. تنها وظیفه‌ای که ReactDOM به عهده داره، اینه که با اِی‌پی‌آی‌های render یا ReactDOM.render یک اِلِمان جِی‌اِس‌اِکس رو، داخل یک اِلِمان دیگه (اینجا document.getElementById(&#x27;root&#x27;)) نمایش بده.خط سوم، خیلی ساده اِستایل‌های موجود در فایل index.css رو، برای تمام اِلِمان‌هایی که اینجا قرار هست رِندِر بشن، اعمال میکنه.خط چهارم یک کامپوننت رو، اینجا به اسم app، از یک کلاس ری‌اکت فراخوانی کرد و بعد تو خط هفتم، به ReactDOM گفت که این کامپوننت رو داخل اِلِمان root رِندِر کنه. اما بریم سراغ کلاس ری‌اکت و ببینیم اصلا حرفش چی هست.import React, { Component } from &#039;react&#039;;
import logo from &#039;./logo.svg&#039;;
import &#039;./App.css&#039;;

class App extends Component {
  render() {
    return (
      &lt;div className=&quot;App&quot;&gt;
        &lt;header className=&quot;App-header&quot;&gt;
          &lt;img src={logo} className=&quot;App-logo&quot; alt=&quot;logo&quot; /&gt;
          &lt;h1 className=&quot;App-title&quot;&gt;Welcome to React&lt;/h1&gt;
        &lt;/header&gt;
        &lt;p className=&quot;App-intro&quot;&gt;
          To get started, edit &lt;code&gt;src/App.js&lt;/code&gt; and save to reload.
        &lt;/p&gt;
      &lt;/div&gt;
    );
  }
}

export default App;خب، طبق معمول خط اول، کلاس‌های ری‌اکت (React) و کامپوننت (Component) رو از کتابخونه ری‌اکت فراخوانی کرده. اما تفاوت براکت‌ها {} برای کامپوننت و ری‌اکت که براکت نداره چیه؟ این یکی از ویژگی‌های ای‌اس۶ هست که به این صورته:فرض کنید کلاسی رو به شکل زیر تعریف کردیم:class YeClassJadid1 {/*...*/}

export class YeClassJadid2 {/*...*/}

export default class YeClassJadid3 {/*...*/}

export default class YeClassJadid4 extends YeClassDige {/*...*/}اشیائی که تعریف شدن همشون ویژگی کلاس بودن رو دارن، اما تفاوتشون به این صورته که، کلاس اول (YeClassJadid1)، فقط تو همون فایلی که تعریف شده، یا اسکوپی (Scope) که تعریف شده قابل خونده شدنه و جاهای دیگه قابل استفاده نیست. کلاس دوم (YeClassJadid2) رو شما میتونید جاهای دیگه، با استفاده از روش import { YeClassJadid2 } from &quot;path/to/the/file&quot; فراخوانی کنید. دلیلش هم اینه که کلاس دوم، به طور پیش‌فرض کلاس اصلی این ماژول یا فایل نیست. اما، کلاس سوم YeClassJadid3 به طور پیش‌فرض، کلاس اصلی تعریف شده (default) و زمانی که بخواد فراخوانی بشه، میتونه به صورت import YeClassJadid3 from &quot;path/to/the/file&quot; یا حتی import YeEsmeDige from &quot;path/to/the/file&quot; فراخوانی بشه. و در نهایت هم، کلاس چهارم YeClassJadid4 مثل کلاس‌های قبلی، اما با ارث‌بری از کلاس YeClassDige خارج یا اِکسپورت میشه.نکته‌ای که گفتنش حائز اهمیته، اینه که هر ماژول، یا هر فایل، فقط یک کلاس رو میتونه به صورت  default خارج کنه! تو مثال بالا، یکی از کلاس‌های YeClassJadid3 یا YeClassJadid4 میتونن خاصیت default رو داشته باشن!باز هم میگم، هدفم این نیست که عمیق وارد ری‌اکت بشم و فقط میخوام شما رو با این محیط آشنا کنم. برنامه اینه که شما وارد نِکست‌جِی‌اِس بشید و من اونجا بیشتر درمورد خود ری‌اکت می‌نویسم. تا اینجا هم خوب پیش اومدیم، بریم سراغ کامپوننت‌ها و یه کامپوننت بسازیم.ساخت کامپوننتبرای اینکه بهتر متوجه بشید کامپوننت‌ها چی هستند، صفحات وب رو به تیکه‌های کوچیک تقسیم کنید. مثلا نوار بالای صفحه یه کامپوننت جدا، لیست محصولات یه کامپوننت جدا و همینطور ادامه بدید...?اول، کل صفحه یک کامپوننت هست، بعد هر تیکه‌ای از صفحه تقسیم به کامپوننت‌های کوچک‌تر میشه و پیش میره. این موضوع رو با ساخت یک کامپوننت راحتت درک میکنید. برای شروع، داخل پوشه  src یک پوشه دیگه به اسم components یا هر اسم دیگه‌ای که دوست دارید ایجاد کنید. اینکه پوشه‌ها چطور باشن، دست خودتونه، اما یادتون باشه که یک‌سری استاندارد یا کانوِنشِن (Convention) برای اینکار هست که مدیریت کد رو راحتتر میکنه. در نهایت داخل این پوشه، یک فایل به اسم MyComponent.js بسازید و داخلش این کد رو قرار بدید:import React from &quot;react&quot;;

export default class ThisIsAComponent extends React.Component {
    render() {
        return (
            &lt;ul&gt;
                &lt;li&gt;Item 1&lt;/li&gt;
                &lt;li&gt;Item 2&lt;/li&gt;
                &lt;li&gt;Item 3&lt;/li&gt;
                &lt;li&gt;Item 4&lt;/li&gt;
                &lt;li&gt;Item 5&lt;/li&gt;
            &lt;/ul&gt;
        );
    }
}کامپوننتی که ساختیم خیلی سادست، یه لیست با ۵تا آیتم. که باید، حتما داخل تابع render قرار بگیرن، و این تابع هم، فقط باید یک اِلِمان رو، یا چند اِلِمانی که داخل یک المان والد جمع شدند رو برگردونه. حالا باید این کامپوننت رو داخل  App.js فراخوانی کنیم. کار خیلی ساده‌ایه. App.js رو باز کنید و اون رو به شکل زیر تغییر بدید:import React, { Component } from &#039;react&#039;;
import logo from &#039;./logo.svg&#039;;
import &#039;./App.css&#039;;
import ThisIsAComponent from &quot;./components/MyComponent&quot;

class App extends Component {
  render() {
    return (
      &lt;div className=&quot;App&quot;&gt;
        &lt;header className=&quot;App-header&quot;&gt;
          &lt;img src={logo} className=&quot;App-logo&quot; alt=&quot;logo&quot; /&gt;
          &lt;h1 className=&quot;App-title&quot;&gt;Welcome to React&lt;/h1&gt;
        &lt;/header&gt;
        &lt;p className=&quot;App-intro&quot;&gt;
          To get started, edit &lt;code&gt;src/App.js&lt;/code&gt; and save to reload.
        &lt;/p&gt;
        
        &lt;ThisIsAComponent/&gt;
      &lt;/div&gt;
    );
  }
}

export default App;خب، کامپوننت رو ساختیم و اون رو به کامپوننت اصلی اضافه کردیم. حالا دستور  npm start رو اجرا کنید و بعد داخل مرورگر به آدرس localhost:3000 برید و نتیجه رو ببینید. بعد از اینکه تموم شد، میتونید سرور رو ببندید و برید سراغ مرحله بعد.گریزی به stateفرض کنید که قرار بود دکمه‌ای وجود داشته باشه، تا با کلیک کردن روش، کامپوننت ما یا حتی یک بخشی از کامپوننت نمایش داده بشه و یا مخفی بشه، یکی از این دو حالت ساده! اینجا لازم هست که کمی در مورد مفهوم استِیت (state) توضیح بدم. کامپوننت‌های شما، همینطور که تا اینجا دیدید، کار خاصی رو به خودی خودشون انجام نمیدن، چون در حقیقت اِلِمانهای HTML هستند، یا حتی شاید لازم باشه در طول زمان تغییراتی رو پیدا کنن. ملموس‌ترین نوع تغییر، زمانی رخ میده که شما اطلاعاتی رو از جایی (از یک سرور) دریافت میکنید و می‌خواید به کاربر نشون بدید، اما تو مدت زمانی که اطلاعات در حال دریافت هستند، علاقه دارید تا یک اسپینر (spinner) رو نمایش بدید، تا به کاربر بگید که اطلاعات در حال بارگزاری هستن. یه سناریوی دیگه اینکه، با کلیک روی یک چِک‌باکس (checkbox) یک فیلد مخفی شده رو نمایش بدید و مثال‌های دیگه. اینجاست که استیت به کمک شما میاد.استیت در حقیقت محل ذخیره‌ي آخرین تغییرات و حالات کامپوننته. مثلا شما بهش میگید که کامپوننت من در حالت عادی، نمایش داده میشه، اما من میخوام، زمانی که کاربر روی یک دکمه کلیک میکنه، کامپوننتم رو مخفی کنم. اینجا، نمایش داده شدن یا مخفی شدن، جز حالات یا استیت کامپوننت به حساب میاد. ری‌اکت، زمانی که استیت تغییر میکنه، کامپوننت رو مجدد بارگزاری یا رِندِر میکنه.برای اینکه با استیت هم کار کنیم و بهتر درکش کنیم، به تریتیب زیر، به کامپوننت ThisIsAComponent استیت میدیم،حالت دیفالت یا اولیه رو برای کامپوننت تعریف میکنیمتوسط یک ایونت (Event) حالت یا همون استیت رو تغییر میدیم.کامپوننت رو به شکل زیر بازنویسی میکنیم:import React from &quot;react&quot;;

export default class ThisIsAComponent extends React.Component {
    constructor() {
        super()

        this.state = {
            isHidden: false
        }
    }

    toggleState() {
        this.setState({
            isHidden: !this.state.isHidden
        })
    }

    render() {
        return (
            &lt;div&gt;
                &lt;button onClick={this.toggleState.bind(this)}&gt;Change&lt;/button&gt;
                &lt;ul hidden={this.state.isHidden}&gt;
                    &lt;li&gt;Item 1&lt;/li&gt;
                    &lt;li&gt;Item 2&lt;/li&gt;
                    &lt;li&gt;Item 3&lt;/li&gt;
                    &lt;li&gt;Item 4&lt;/li&gt;
                    &lt;li&gt;Item 5&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
        );
    }
}کارهایی که انجام شده، به همراه توضیحاتشون به ترتیب زیر هستن:constructor به کامپوننت اضافه شده. این تابع که در حقیقت از تعاریف کلاس در جاوا‌اسکریپت برگرفته شده، کارهای متفاوتی رو میتونه انجام بده. اما یادتون باشه، هر موقع که میدونستید کامپوننتتون قرار هست حالات مختلفی رو برای نمایش داشته باشه، حالت اولیش (Initial State) رو اینجا تعریف کنید. مهمترین نکته اینه که به محض تعریف کردن  constructor، تابع super() فراخوانی بشه. اگر فراموش کنید که  super() رو بلافاصله فراخوانی کنید، this که در حقیقت همون کامپوننت شماست و اطلاعات کامپوننت رو توی خودش داره، خالی خواهد موند و در نتیجه امکان استفاده از اِستِیت و بقیه ویژگی کامپوننت‌ها رو نخواهید داشت.قدم بعدی، داخل  construct و زیر super()، استیت اولیه یا همون Default رو تعریف کردم. شکل تعریفش هم یه شئ ساده بوده که داخلش فقط از isHidden: false استفاده کردم تا بگم، در حالت عادی نمایش داده نمیشه (اینکه چطور و چه چیزی از این حالت استفاده میکنه و تغییر میکنه رو پایین‌تر توضیح میدم)یک تابعی رو تعریف کردم با اسم دلخواه  toggleState که قرار هست موقع کلیک کردن دکمه، فراخوانی بشه. کاری هم که انجام میده، خیلی ساده، استیت رو تغییر میده. کد نوشته شده شاید شما رو یکم سردرگم کنه. تعریف کد به این شکله: isHidden: !this.state.isHidden و یعنی، مقدار جدید isHidden برابر خواهد بود با هر آنچه که this.state.isHidden بوده، اما چون یک ! هم اولش آوردم، یعنی اون مقدار رو بر عکسش کن. پس اگر this.state.isHidden برابر با false بود، مقدار جدیدش برابر با true میشه و برعکس.چون یک دکمه هم به کامپوننت اضافه کردم، باید کل اِلِمان‌ها رو داخل یک اِلِمان اصلی و والد جا بدم. برای همین هم، تمام المان‌ها رو داخل یک div گذاشتم.زمانی که کاربر روی دکمه کلیک میکنه، رویداد (Event)  onClick اتفاق میوفته. اینجا بهش گفتم، زمانی که این رویداد اتفاق افتاد، تابع toggleState رو صدا بزنه. ضمنا از bind هم استفاده کردم، چون دکمه‌ها در حالت عادی، رویدادها رو انجام نمیدن و بایند (Bind) موظف هست تا حالت اصلی شئی که بهش پاس داده میشه رو حفظ و برای تابع مربوطه ارسالش کنه. در این مورد بعدا بیشتر توضیح میدم.و در نهایت، به المان ul گفتم، تا مخفی بودن یا نبودنش رو از this.state.isHidden بگیره. حالا، هر موقع که isHidden تغییر کنه، المان ul مجددا رِندِر میشه.برنامه رو تست کنید و ببینید که کارکردش چطوره. کارتون که تموم شد، میریم تا یکم دیگه با تئوری دست و پنجه نرم کنیم.درک مفاهیم ری‌اکتمهم‌ترین تفاوت کتاب‌خونه ری‌اکت با فرِیم‌وُرک‌هایی مثل انگولار، اینه که ری‌اکت فقط برای فرانت‌اند ساخته شده. در مورد ری‌اکت، چیزهای خیلی زیادی برای گفتن وجود داره. اما دوتا از ویژگی‌های اصلی ری‌اکت، داشتن مفاهیمی مثل Properties یا به طور خلاصه Prop و همچنین State هست که قبل‌تر کمی با مفهوم State آشنا شدیم. اینجا تصمیم دارم در مورد این دو و همچنین چرخه زندگی کامپوننت‌ها بیشتر توضیح بدم.Propsپراپ‌ها در واقع راهی برای ارتباط بین کامپوننت‌ها و جز ویژگی‌های اونها هستند (هرجا که شما کلاس React.Component رو استفاده یا همون extend کنید، میتونید ازشون بهره‌ ببرید). مهم‌ترین ویژگی پراپ‌ها، اینه که از سمت کامپوننت والد به فرزند منتقل میشن و اصطلاحا uni-directional (یک‌طرفه) هستن. زمانی هم وجود داره که شما مثل استِیت، پراپ‌های اولیه رو تعریف میکنید تا کامپوننت شما با اطلاعات اولیه (و نه حالات اولیه)، شروع به کار کنه. پراپ‌ها به شما کمک میکنن تا اطلاعات رو بین کامپوننت‌ها جابجا کنید، و زمانی که کاربر بخواد مستقیما روی خود کامپوننت تغییری اعمال کنه، باید از استیت استفاده بشه. بذارید با یک مثال ساده از پراپ استفاده کنیم:فرض کنید که توی کامپوننت ThisIsAComponent از یک تگ هدر h1 استفاده میکردیم و قرار بود مقدار داخلش رو توسط کامپوننت والد تغییر بدیم. کد جدیدمون به این شکل میشد (فقط تابع رِندِر رو گذاشتم و مابقی کد دست‌نخورده باقی مونده):render() {
        return (
            &lt;div&gt;
                &lt;h1&gt;{this.props.title}&lt;/h1&gt;
                &lt;button onClick={this.toggleState.bind(this)}&gt;Change&lt;/button&gt;
                &lt;ul hidden={this.state.isHidden}&gt;
                    &lt;li&gt;Item 1&lt;/li&gt;
                    &lt;li&gt;Item 2&lt;/li&gt;
                    &lt;li&gt;Item 3&lt;/li&gt;
                    &lt;li&gt;Item 4&lt;/li&gt;
                    &lt;li&gt;Item 5&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
        );
    }حالا باید مقداری رو برای title از کامپوننت والد، یعنی App در نظر بگیرم. کار آسونیه و به شکل زیر تغییری رو تو App.js ایجاد میکنم:...
&lt;ThisIsAComponent title={&quot;This is a new title&quot;}/&gt;
...Stateپراپ‌ها نباید تغییر کنن (به اصطلاح باید Immutable باشن)، برای همین از استیت استفاده میشه. در حالت عادی، کامپوننت‌ها استیت ندارن و از این جهت اصطلاحا بهشون Stateless گفته میشه. کامپوننت‌هایی که استیت پیدا میکنن، بهشون Stateful میگن.کاربرد استیت برای اینه که کامپوننت بتونه اطلاعاتی که در هر بازسازی دریافت میکنه رو حفظ کنه. زمانی که شما از this.setState() استفاده میکنید، وضعیت کامپوننت بروزرسانی و مجددا بازسازی میشه. تمام این فرایند بازسازی توسط ری‌اکت اتفاق می‌افته و خیلی هم سریعه.پراپ و استیت خیلی شبیه به هم هستند و تقریبا کار مشابهی رو انجام میدن، اما برای کارهای متفاوتی ازشون استفاده میشه. این امکام وجود داره تا خیلی از کامپوننت‌های شما Stateless باشن.چرخه زندگی کامپوننت‌ها (Component Lifecycle)کامپوننت‌ها به شما کمک میکنن تا یو‌آی (UI) رو به تیکه‌های کوچکتر تقسیم کنید. در حالت کلی، شما کامپوننت‌ها رو به شکل کلاس‌های جاوااسکریپت تعریف میکنید:class Greeting extends React.Component {
  render() {
    return &lt;h1&gt;Hello, {this.props.name}&lt;/h1&gt;;
  }
}اما کامپوننت‌ها صرفا جهت نمایش ساخته نمیشن و کارهای بیشتری میشه باهاشون انجام داد. اصطلاحا هر کامپوننتی برای خودش یک چرخه‌زندگی بخصوص یا Lifecycle داره که چندتا از پر کاربردترین‌ها رو توضیح میدم:constructor() که دقیقا قبل از بارگذاری کامپوننت توسط ری‌اکت خونده میشه. بهترین استفادش، تعریف state اولیه کامپوننت هست. اگر کامپوننت stateless باشه، نیازی به تعریف این تابع نیست.componentWillMount() دقیقا قبل از بارگذاری خونده میشه. و قبل از تابع render() اتفاق میوفته. به همین خاطر تعریف استیت تو این تابع پیشنهاد نمیشه. این تابع سمت سرور کارهاش رو انجام میده و اصطلاحا server-side هست. (در این مورد تو بخش Isomorphism توضیح میدم)componentDidMount() بعد از اینکه کامپوننت بارگذاری شد، خونده میشه. این تابع بهترین جا برای ارسال درخواست‌ها به سرور شماست و اگر استیت رو تو این تابع با استفاده از تابع this.setState() تغییر بدید، باعث میشید که باز دوباره تابع render() فراخوانی بشهcomponentWillReceiveProps(nextProps) زمانی فراخوانی میشه، که شما از طریق کامپوننت والد، پراپ‌های کامپوننت فرزند رو تغییر بدید و بخواید استیت جدید رو بر اساس پراپ‌های جدید تنظیم کنید. برای اینکار میتونید آرگومان‌های nextProps و this.props رو با هم مقایسه کرده و تغییرات رو ایجاد کنید. (مقایسه رو حتما انجام بدید!)componentWillUpdate(nextProps, nextState) قبل از بارگذاری مجدد رخ میده، اگر پراپ‌ها و استیت‌های کامپوننت تغییری کرده باشن.componentDidUpdate(prevProps, prevState) بلافاصله بعد از بارگذاری مجدد اتفاق میوفته و به شما این امکان رو میده تا المان‌ها رو دستکاری کنید.componentDidCatch(error, info) برای مدیریت اِرورها و خطاها تو UI استفاده میشه.مطالعه بیشتر...جمع‌بندیپراپها استفاده میشن تا اطلاعات از کامپوننت والد به کامپوننت فرزند یا حتی داخل کامپوننت فرزند منتقل بشن. پراپ‌ها تغییرناپذیر یا به اصطلاح Immutable هستند و نباید در هر رندر تغییر کنند.استیت برای این استفاده میشه تا اطلاعات رو تغییر بدیم، یا اطلاعات تغییر یافته رو نمایش بدیم و اصطلاحا تغییر پذیر یا Mutable هستند. مثلا کاربر چیزی رو در سایت سرچ میکنه و بلافاصله زیرش تعدادی از نزدیک‌ترین نتایج جست‌وجو نمایش داده میشه.مفهوم Isomorphic یا Universalزمانهای قدیم، قبل از موقعی که NodeJS بین برنامه‌نویس‌ها محبوب بشه، جاوااسکریپت زبانی بود که باهاش تغییراتی رو تو صفحه‌های وب ایجاد میکردن تا صفحه‌ها از حالت مرده و استاتیک خارج بشن. تا اون موقع زبان جاوااسکریپت، زبانی بود که تو مرورگر کاربر اجرا میشد و به اصطلاح Client Side یا سمت کاربر بود. بعد از ظهور NodeJS جاوااسکریپت این قابلیت رو پیدا کرد که تو محیط سمت سرور هم اجرا بشه و بعد از اون جاوااسکریپت به یک زبان Server Side هم تبدیل شد.ایزومورفیزم (Isomorphism) از ریاضیات گرفته شده و «هم‌سان» معنی میشه. چون واژه ایزومورفیک برای برنامه‌نویس‌ها کمی مشکل‌ساز میتونه باشه، به جاش از واژه یونیورسال (Universal) هم استفاده میکنن.ایزوموفیک در شاخه وب، به معنی ساخته شدن صفحه سمت سرور یا سمت کاربر هست و در حالت کلی به NodeJS و خود JavaScript اشاره میکنه. برای اینکه تعریف رو ساده‌تر کنم، اینطور در نظر بگیرید که، کدی که سمت سرور ساخته شده، به صورت HTML به کاربر ارسال میشه و کاربر میتونه تو کد صفحهش اون رو ببینه. اما کدی که سمت کاربر ساخته میشه، تو کدهای صفحه قابل مشاهده نیست. اینجا لازم هست که به این نکته اشاره کنم، که منظور از سرور، الزاما بک‌اند نیست، و اونچه که مد نظر هست، ابزاریه که وظیفه تبادل ارتباطات رو به عهده داره.دلایل مختلفی وجود دارن که برنامه‌نویس‌ها به اپ‌های ایزومورف علاقه‌مندند:بهبود سئو،پرفورمنس بهتر،و نگهداری راحت‌تر.یکی از مضوعاتی که خیلی در این مورد مهم هست، اینه که کد‌های ایزومورفیک که سمت کاربر ساخته شدن، توسط موتورهای جست‌وجو به خوبی خونده نمیشن، برای همین هم اپ‌های SPA معمولا با این ساختار دچار مشکل میشن و لازم هست تا کدشون سمت سرور ساخته بشه. (سرور رو الزاما با کامپیوتر سرور اشتباه نگیرید!)Promise و درک ناهم‌گام‌سازی (Asynchronous)بیاید با هم یه دنیای جالبی رو تجسم کنیم، تو این دنیای ما، هنوز گوگل وجود نداره و شما رئیس یک شرکت «پاسخ به سوالات» هستید. نحوه کار به این شکله که کاربر سوال خودش رو بسته‌بندی میکنه (Data Package) و اون رو به یک پست‌چی میده، پست‌چی این بسته رو میاره برای شرکت شما (Request) و شما بسته رو باز میکنید، به سوال جواب میدید و اون رو به پست‌چی میدید و ایشون هم برای کاربر جواب رو میبره (Response). پروسه تا اینجا واضحه فقط چند شرط وجود داره:از اونجایی که شرکت ما خیلی خاصه :دی،کاربر زمانی که بسته رو به پست‌چی میده، باید دم در خونه صبر کنه تا پست‌چی برگرده (و از کار و زندگیش هم می‌افته)پستچی تا زمانی که شما پاسخ رو بسته‌بندی نکردید و بهش تحویل ندادید پیش شما میمونه.این روش ارتباط، روش هم‌گام یا اصطلاحا Synchronous نام داره و همون روش قدیمیه کار با اینترنته، کد PHP مینوشتیم و با هربار کلیک رو دکمه، کاربر باید منتظر صفحه جدید میموند و نمیتونست کارهای دیگه توی سایت رو انجام بده.حالا شرکتمون رو کمی پیشرفته‌تر میکنیم، فرایند همون شکل قبلی رو داره اما:زمانی که کاربر درخواستش رو بسته‌بندی کرد و به پست‌چی داد، برمی‌گرده خونش و کارهاش رو انجام میدهشما فقط یک پست‌چی ندارید و پست‌چی‌ها میتونن از کاربر درخواست‌های مختلفی رو بگیرن و برای شما بیارناین نوع ارتباط، ارتباط نا‌هم‌گام یا Asynchronous نام داره و خیلی تو وب‌اپ‌های SPA پر کاربرده و AJAX یکی از معروف‌ترین تکنیک‌ها برای برقراری این نوع ارتباطهاست. تو نسخه‌های جدید جی‌اس، برای اینکه کاربر رو منتظر نذاریم بعد از اینکه درخواستش رو ارسال کرد، بهش قول میدیم که در آینده جوابی رو برای درخواستش ارسال میکنیم، و کاربر میتونه به کارش ادامه بده و ماهم پردازشمون رو انجام میدیم. اینجاست که پرامِس (پرامیس؟) یا همون Promiseها خودشون رو نشون میدن.قبل از معرفی شدن پرامس‌ها، تو جاوااسکریپت از Callbackها استفاده میشد، کال‌بک‌ها توابعی بودن که مثلا به عنوان آرگومان یک تابع دیگه تعریف میشدن، تا هنگام بُروز یک رویداد خاص (Event) کار خاصی رو هم انجام بدن. مشکل اینجا بود که ایده‌ی کال‌بک‌ها، هرچقدر هم که قشنگ بوده، تو پردازش‌های پیچیده مدیریت کد رو خیلی سخت میکرده و به اصطلاح، برنامه‌نویس رو وارد جهنم کالبَک‌ها یا همون Callback-Hell میکرده. برای همین پرامس‌ها ساخته شدند تا جایگزینی برای کال‌بک‌ها باشن.پرامس‌ها یا جوابی رو برمیگردونن یا اینکه دلیلی رو برای عدم انجام موفقیت‌آمیز اون فرایند ارائه میدن. از اینجا میشه گفت که پرامس‌ها ساختار مشابهی مثل try/catch دارن و از همه مهمتر، سه وضعیت کلی رو شامل میشن:Pending: که یعنی در حال انجام کاری هستند،fulfilled: که یعنی کارشون رو به خوبی انجام دادن وrejected: که یعنی از پس کاری که بهشون داده شده بر نیومدن.یه مثال ساده برای اینکه با نمونه‌ای از یک پرامس آشنا بشید به این شکله:fetch(url)
  .then(process)
  .then(save)
  .catch(handleErrors)
;??اینجا، تابع  process صبر میکنه تا کار تابع fetch تموم بشه، بعد تابع save منتظر process میمونه و اگر هرکدوم از این توابع جایی به مشکل خوردند، تابه handleErrors وظیفش رو انجام میده.اگر هرکدوم از این توابع، پرامس باشن، میتونن ساختار مشابهی رو برای خودشون بگیرن، در واقع این قابلیت رو به شما میدن تا بتونید پرامس‌ها رو تودرتو کنید.استفاده از fetchحالا که متوجه مفهوم ایزومورفیک و همچنین درخواست‌های نا‌همگام شدید، بریم تا با یه مثال تو پروژمون به درک بیشتری ازشون برسیم.قدم اول، نصب کتابخونه isomorphic-fetch از مخازن npm هست. fetch یکی از کتابخونه‌های مورد علاقه‌ی من که در کنارش کتابخونه axios وجود داره. تفاوت عمده این دو کتابخونه، تو پردازش اطلاعات هست و اکسیوس برای ای‌اس۶ آمادگی بیشتری داره، منتهی من طبق عادت پیش میرم و از فِچ (fetch) استفاده میکنم.$ npm install --save isomorphic-fetchکتابخونه رو نصب کنید، اینکه واژه ایزومورفیک اولش استفاده شده، نشون میده که این کتابخونه رو، هم میشه سمت سرور و هم سمت کاربر استفاده کرد. حالا، کامپوننت ThisIsAComponent رو یکمی تغییر میدیم. در نهایت کدمون باید به شکل زیر بشه:import React from &quot;react&quot;;
import fetch from &quot;isomorphic-fetch&quot;;

export default class ThisIsAComponent extends React.Component {
    constructor() {
        super()

        this.state = {
            done: true,
            items: []
        }
    }

    fetchData() {
        this.setState({
            done: false
        });

        fetch(&#039;http://jsonplaceholder.typicode.com/posts&#039;)
        .then(data =&gt; {
            data.json()
            .then(res =&gt; {
                this.setState({
                    done: true,
                    items: res
                })
            })
        })
        .catch(error =&gt; {
            console.log(error)
        })
    }

    render() {
        return (
            &lt;div&gt;
                &lt;h1&gt;{this.props.title}&lt;/h1&gt;
                &lt;button onClick={this.fetchData.bind(this)}&gt;Get Data&lt;/button&gt;
                &lt;p hidden={this.state.done}&gt;Loading&lt;/p&gt;
                &lt;div&gt;
                    {
                        this.state.items.map(item =&gt; {
                            return (
                                &lt;p&gt;{item.title}&lt;/p&gt;
                            )
                        })
                    }
                &lt;/div&gt;
            &lt;/div&gt;
        );
    }
}
خط به خط بریم جلو ببینیم چه اتفاقی افتاده:اول، از کتابخونه isomorphic-fetch شئ fetch رو فراخوانی کردم.تو تابع constructor، استیت اولیه رو تغییر دادم و به جای isHidden که اول داشتیم، done رو، که وظیفه نگهداری از وضعیت بارگذاری آیتم‌ها رو به عهده داره و items که نگهدارنده آیتم‌های دریافت شده از سرور هستند رو ساختم.تابع toggleState رو پاک کردم و به جاش از fetchData استفاده کردم. اسمش رو هم خودم انتخاب کردم. داخل این تابع اتفاقات جالبی میوفته.زمانی که این تابع خونده میشه (یا در واقع رو دکمه‌ای کلیک میشه که باید این تابع رو اجرا کنه) وضعیت done به false تغییر پیدا میکنه. چون در حقیقت آیتمی دریافت و کار ما هم تموم نشده.قدم بعدی، از fetch استفاده کردم تا از یک آدرس پیش‌فرض، یک‌سری اطلاعات الکی رو دریافت کنم. نکته مهم اینه که fetch یک پرامس هست و وضعیتش رو میشه کنترل کرد. برای همین، تو خط پایینش گفتم، هر موقع که دریافت اطلاعات تموم شد، از اطلاعات دریافت شده که اسمشون رو data گذاشتم استفاده کن و...یکی از مهم‌ترین تفاوت‌های fetch و axios تو این مرحلست، پاسخی که fetch به شما برمیگردونه، یک پاسخ خام هست و باید تبدیل به دیتای قابل خوندن بشه. fetch این کار رو با برگردوندن یک پرامس انجام میده (برای نوشتن توابع از Arrow Functionها استفاده کردم). پس گفتم، زمانی که جواب رو از سرور گرفتی، اون رو به json تبدیل کن (که خود تابع json یک پرامس برمیگردونه) و بعد از اینکه عمل تبدیل به json درست انجام شد، از حاصلش استفاده کن تا دوباره استیت رو تغییر بدی.done رو هم برابر با true کردم تا نشون بدم عمل دریافت اطلاعات کامل شده. در نهایت نتیجه حاصل از دریافت اطلاعات، یا همون آیتم‌های مورد نظرم رو، که حالا تبدیل به json شدند، داخل items استیت ذخیره کردم.اینکار باعث میشه که ری‌اکت، یکبار دیگه کامپوننت‌هایی که از این استیت استفاده میکنن رو بارگذاری کنه. در نهایت هم بررسی میکنه که آیا اشکالی وجود داشته تو کل این فرایند یا نه.آخر سر، تو تابع  render دکمه Get Data رو به تابع fetchData وصل کردم. یک تگ p هم اضافه کردم که بهش گفتم، وضعیت hidden بودنش رو از done موجود تو استیت بگیره. (هر موقع که بارگذاری تموم شده بود، این المان محو میشه و هرموقع بارگذاری در حال انجام بود، این المان نمایش داده میشه)داخل المان div که به جای ul نشسته، با استفاده از تابع map() که شکل جدیدی از forEach هست، آیتم‌ها رو نمایش دادم. (پایین‌تر درمورد map توضیحات بیشتری میدم)ادامه مطلب در سایت خودم...</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Tue, 08 May 2018 20:56:32 +0430</pubDate>
            </item>
                    <item>
                <title>رمزهای کاربرها رو امن ذخیره کنید!</title>
                <link>https://virgool.io/InfoSec/%D8%B1%D9%85%D8%B2%D9%87%D8%A7%DB%8C-%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%D9%87%D8%A7-%D8%B1%D9%88-%D8%A7%D9%85%D9%86-%D8%B0%D8%AE%DB%8C%D8%B1%D9%87-%DA%A9%D9%86%DB%8C%D8%AF-dhkgsxqfgj7f</link>
                <description>مقدمهاگر شما دولوپر باشید، حتما لازم بوده که سیستم مدیریت کاربرها رو (Authentication and user management service) بسازید. مهمترین ویژگی این سیستم اینه که پسوردها چطور مدیریت میشن. خب واضح هست که پایگاه‌داده‌هایی که اطلاعات کاربرها توشون هست خیلی زیاد مورد حمله قرار می‌گیرن، بنابراین حتما باید فکری برای مراقبت و نگه‌داری از رمزها کرده باشید! یکی از بهترین روش‌های رمز‌گذاری، استفاده از متد Salted Password Hashin یا استفاده از سالت برای رمز‌گذاری روی پسوردهاست.ایده‌‌های خیلی زیادی (و غلط!) و مفاهیم متعددی برای توضیح رمزگذاری وجود داره که یکی از دلایل وجود این‌همه اطلاعات اشتباه بنظرم، مدیریت نادرست اطلاعات در وب‌سایت‌هاست. هش کردن رمزها یکی از همین مفاهیم ساده رمزگذاریه که متاسفانه خیلی وقت‌ها به اشتباه انجام میشه. اینجا سعی دارم تا توضیح بدم که این کار رو چطور به روش درست انجام بدیم.توجه! اگر به این فکر میکنید که روش رمزگذاری خودتون رو پیاده کنید، بدونید که دارید اشتباه میکنید! خیلی راحت میشه همه‌چیز رو خراب کرد. حتی اگر کلاس‌های مختلف رمز‌گذاری رو هم گذروندید باز هم راه دوری نرفتید و اصلا برای اینکار تلاش نکنید.یادتون باشه که مشکل ذخیره کردن رمزها قبلا حل شده و شما چیز جدیدی رو نمیسازید (مگر اینکه یه نابغه رمزنگاری باشید)اگر به هر شکلی توضیح بالا رو از دست داید، لطفا برگردید و حتما بخونیدش. من اینجا توضیح نمیدم که چطور رمزگذاری خودتون رو پیاده کنید، بلکه اینجا میگم روش درست رمزنگاری چی هست.هَش کردن رمز چی هست؟hash(&quot;aien&quot;) = f3bab1f4f25e655834c6c0ab5189248e
hash(&quot;Aien&quot;) = 478a2428cde6daf521d8bb3ad1376f70
hash(&quot;saidi27.com&quot;) = 478a2428cde6daf521d8bb3ad1376f70الگوریتم‌های هش، توابعی یک‌به‌یک هستند. این توابع ورودی‌هاشون رو به داده‌هایی با طول یکسان تبدیل میکنند که قابل برگشت نیستن. یعنی شما میتونید مثلا اسمتون رو به هش تبدیل کنید، اما هش اسمتون رو نمیتونید به اسمتون برگردونید. یکی از مهمترین ویژگی‌های این توابع، اینه که با هر تغییر کوچیکی، خروجی متفاوتی میدن (به مثال بالا توجه کنید). این روش خیلی خوبی برای دخیره‌کردن رمزهاست، چون ما می‌خوایم که رمزها ناخوانا باشن، و در عین حال باید بتونیم این رمزها رو چک کنیم تا به کاربر مجوزهای لازم رو بدیم.جریان کلی رجیستر کردن کاربرها و مجوز دادن بهشون، تو سیستم‌های هش به این ترتیبه:کاربر اکانتش رو میسازه،رمزش هش میشه و توی پایگاه‌داده ذخیره میشه (هرگز نباید رمز خام (Plain Password) که هش نشده، تو پایگاه‌داده ذخیره بشه).زمانی که کاربر درخواست ورود میکنه، رمز هش شدش، با رمز هش شده‌ای که تو پایگاه‌داده ذخیره کردیم بررسی میشه.اگر هش‌ها با هم یکی بودن، کاربر اجازه ورود داره، اگر نه باید بهشون گفت که یه اشکالی هست.تو مرحله چهارم، هیچوقت به کاربر نگید که کدوم یک از نام‌کاربری یا پسوردشون اشتباهه! چون هکرها نباید بفهمن که یوزر درستی رو وارد کردن تا پسوردش رو چک کنن.مهمترین نکته اینه که این توابع هش‌گذاری، اصلا امن نیستن و سرعت بالایی دارن. برای هش‌کردن رمزها باید از توابع هش رمزنگاری‌شده یا Cyptographic hash functions استفاده کنید. توابعی مثل SHA256، SHA512 و RipeMD توابع رمز‌گذاری شده هستند.خیلی ساده میشه به این فکر کرد، که فقط کافیه رمز کاربر رو تو یکی از این توابع بندازید و خروجیش رو دخیره کنید چون امن شده. باید بگم که اشتباه میکنید! روش‌های خیلی زیادی برای بازگردوندن رمزها و چک کردنشون وجود داره که این پایین چندتاشون رو توضیح میدم:هش‌ها چطور شکسته میشن؟دیکشنری و Brute Force AttackDictionary AttackTrying ramz        : failedTrying password    : failedTrying amirali : failed...Trying p@ssword      : failedTrying s3cr3t       : success!Brute Force AttackTrying aaaa : failedTrying aaab : failedTrying aaac : failed...Trying acdb : failedTrying acdc : success!راحت‌ترین روش برای شکستن هش‌ها، حدس زدنشونه، هر کدوم از حدس‌ها رو هش میکنیم و درخواست رو میفرستیم، و در نهایت به رمز خواهیم رسید. دو تا از معروف‌ترین روش‌ها، دیکشنری اتک و بروت فورس اتک هستن.دیکشنری اتک به این صورت کار میکنه که یک فایلی داریم که حاوی تعداد زیادی کلمه، واژه و رمزهای معروفیه که اکثرا کاربرها استفاده میکنن و احتمال داره که هرکدومشون به عنوان رمز استفاده بشن. هر کدوم از این کلمات هش میشن و به سرور ارسال میشن...بروت فورس اتک سعی میکنه که ترکیب‌های مختلف و محتمل از کاراکترها رو کنار هم قرار بده و رمزهای مختلف رو بسازه. این روش از نظر منابع کامپیوتری خیلی گرون قیمته، اما در نهایت رمز رو باز میکنه. تنها روش مقابله با این روش، اینه که رمز‌ها انقدر طولانی باشن که جستجو بین محتملات رو تقریبا غیر ممکن یا انقدر پر هزینه کنن که برای کسی صرف نکنه.هیچ روشی برای جلوگیری از این دو متد هک وجود نداره، بهترین راه در مقابلشون اینه که فقط کار رو براشون سخت کنیم.Lookup TableSearching: 5f4dcc3b5aa765d61d8327deb882cf99: FOUND: password5Searching: 6cbe615c106f422d23669b610b564800:  not in databaseSearching: 630bf032efe4507f2c57b280995925a9: FOUND: letMEin12 Searching: 386f43fab5d096a7a66d67c8f213e5ec: FOUND: mcd0naldsSearching: d5ec75d5fe70d428685510fae36492d9: FOUND: p@ssw0rd!این روش عالیه برای هک کردن رمز. ایده‌ی کلی اینه که هش رمزهارو از قبل ذخیره کنیم و این هش‌هارو با هش‌های داخل دیتابیس مقایسه کنیم.اضافه کردن سالت (Salt)hash(&quot;hello&quot;) = 5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03hash(&quot;hello&quot; + &quot;QxLUF1bgIAdeQX&quot;) = 68290787dab7259f607c8d9fa58df0ac07ec0a33d151a60127a55f429d09ad52hash(&quot;hello&quot; + &quot;bv5PehSMfV11Cd&quot;) = 0a7d4f0c9b8962788d4b6b157e9e6cdf794bf5c9b790915dd24ba5ab962a3fe2hash(&quot;hello&quot; + &quot;YYLmfY6IehjZMQ&quot;) = 6034fd9ad717f98425f8135fcfe9de956b7d94d885b371394ee149f8a3ce1e24روش‌هایی که بالاتر گفتم، زمانی کار میکنن که کلمات مختلف رو کنار هم بذارن و اونارو چک کنن. مثلا اگر دوتا کاربر رمزهای یکسانی داشته باشن، هش رمزشون هم مثل هم میشه. ما میتونیم جلوی این حملات رو بگیریم، اگر هش‌ها رو تعییر بدیم و تصادفیشون کنیم، در نتیجه اگر رمزی شکسته بشه، رمز مشابهش دیگه شکسته نمیشه و کار هکر سختتر میشه.میتونیم رمزها رو تصادفی کنیم، به شرطی که بهشون هش‌های تصادفی رو اضافه کنیم. به این هش‌های تصادفی میگن سالت یا Salt. در واقع ما به رمز خام، یک هش رو اضافه میکنیم و نتیجه رو هش میکنیم (مثال بالا)، این کار باعث میشه که حتی با داشتن رمزهای خام ثابت، هش‌های متفاوتی رو داشته باشیم. برای اینکه رمز کاربر رو چک کنیم تا بهش اجازه ورود بدیم، باید سالتش رو که توی پایگاه‌داده ذخیره کردیم، به رمزش اضافه کنیم و نتیجه رو با رمزی که توی پایگاه داده ذخیره شده مطابقت بدیم.سالت نیازی نداره که امن باشه. ما با اینکار صرفا رمزشکنی رو سخت‌تر میکنیم. دلیلش اینه که هکر نمیدونه که سالت ذخیره شده چیه و نمیتونه هش رو ازش دریافت کنه.روش غلط سالت کردن: سالت‌های کوتاه و مشابهدو روش معمول (و غلط) برای سالت‌کردن و ساختن سالت‌ها وجود داره، که یکیش استفاده از سالت‌های مشابه هست و دیگری استفاده از سالت‌های کوتاهسالت‌های مشابهیک اشتباه بزرگ اینه که از یک سالت برای هش‌ها استفاده کنیم! تو این روش یا اصل سالت رو تو برنامه مینویسیم (هارد کد میکنیم)  یا اینکه از یه الگوریتمی استفاده میکنیم که بالاخره یه‌جایی تکرار میشه و یک عدد تکراری رو برمی‌گردونه. این روش بدرد نمیخوره، چون اگر دو کاربر پسورد یکسانی داشته باشن، هش پسوردشون هم مثل هم میشه و هکر ها از راه جداول لوک‌آپ به پسورد دسترسی پیدا کنن. فقط کافیه سالت رو پیدا کنن و به هر رمز بچسبونن و لوک‌آپ کنن.همیشه باید برای هر کاربر، سالت جداگانه ساخته بشه!سالت‌های کوتاهاگر سالت کوتاه باشه، هکر میتونه یه جدول لوک‌آپ برای سالت‌ها بسازه. مثلا اگر سالت فقط ۲تا کاراکتر اسکی (ASCII) باشه، فقط ۸۵۷هزارتا (حدودا) سالت وجود خواهد داشت که شاید به نظر زیاد بیاد ولی با فرض اینکه هر جدول لوک‌آپ هم ۱مگابایت حجم داشته باشه، حدودا ۸۳۰گیگابایت برای داشتن تمام رمز‌ها لازم داره که خب، هارد درایو با این حجم زیاد گرون نیست و هر کسی میتونه داشته باشه.به همین دلیل، نام کاربری نباید به عنوان سالت استفاده بشه. شاید برای یه سایتی، نام‌های کاربری یکتا باشن، اما قابل پیشبینی هستند و معمولا کاربرها از یک نام‌کاربری برای چند سایت استفاده می‌کنن.برای اینکه کار برای هکرها سخت بشه، سالت باید طولانی باشه. یک نکته خوب اینه که اندازه سالت، با اندازه رمز هش شده یکی باشه (مثلا هر دو ۳۲ بایت باشن). به عنوان مثال، SHA256 به شما ۲۵۶ بیت برمی‌گردونه (۳۲ بایت)، برای همین هم سالت باید ۳۲ بایت رندوم باشه.روش غلط سالت کردن: سالت‌های تو در تو یا ضعیفاینجا به روش‌های دیگه‌ای اشاره میکنم که عموما به صورت اشتباه توی سایت‌‌ها بکار میرن، به این امید که پسورد‌های امنی بسازن: هش‌های تو در تو!خیلی راحت ممکنه به این فکر کنید که میشه توابع مختلف رو باهم استفاده کرد (توابع تو در تو) به این امید که هش بدست اومده امن باشه. با این حال در عمل تقریبا شانسی برای اینکار نیست و نتیجه بدست اومده با اونچه که شما فکر می‌کنید متفاوت خواهد بود. در واقع این روش تنها کاری که میکنه، احتمال همکاری بین متدها رو کم میکنه و حتی ممکنه هش‌هایی رو بسازه که حتی کمتر امن هستن! هیچوقت تلاش نکنید که رمزنگاری خودتون رو بسازید، همیشه از یک استاندارد استفاده کنید که توسط افراد حرفه‌ای ساخته شده.بعضی‌ها ممکنه بگن که استفاده از روش تو در تو، زمان زیادی رو برای هش کردن ایجاد میکنه و در نتیجه پروسه شکستن و کرک کردن رمز میتونه بیشتر زمان ببره. من اینجا یک روش بهتر برای کند کردن این پروسه بهتون ارائه میدم که پایین‌تر توضیح میدم.اینا نمونه‌هایی از هش‌‌ها و سالت‌های تودرتو هستن که نباید ازشون استفاده بشه:md5(sha1(password))md5(md5(salt) + md5(password))sha1(sha1(password))sha1(str_rot13(password + salt))md5(sha1(md5(md5(password) + sha1(password)) + md5(password)))این قسمت میتونه بحث‌برانگیز باشه، که بعضی‌ها بگن استفاده از هش‌های تودرتو خوبه چون هکر‌ها نمیدونن از چه الگوریتم‌هایی استفاده میشه و خیلی بعیده که برای رمزها لوک‌آپ داشته باشن.این حرف درسته، هکر‌ها نمیتونن حمله کنن اگر الگوریتم‌ها رو نداشته باشن، اما نکته اینجاست که اکثر هکرها به سورس‌کد دسترسی دارن! (خصوصا اگر اوپن‌سورس باشه نرم‌افزار) و از اونجایی که الگوریتم‌های زیادی برای رمزنگاری وجود ندارن، مهندسی معکوس کردن کار خیلی سختی نخواهد بود. درسته، زمان بیشتری طی میشه تا هش‌های تودرتو شکسته بشن، ولی این زمان تفاوت خیلی زیادی با حالت عادی نمیکته (شاید در حد چند ساعت!).اگر هدفتون اینه که از هش‌های تودرتو استاندارد مثل HMAC استفاده کنید مشکلی نیست، اما اگر صرفا هدفتون اینه که سرعت پردازش رو پایین بیارید، باید بگم که در اشتباه هستید.روش درست سالت کردناز اونجایی که الگوریتم‌ها هش، ورودی‌ها رو به تعداد مشخصی کاراکتر تبدیل میکنن، باید ورودی‌هایی وجود داشته باشن که به هش‌های یکسانی تبدیل بشن (اگر میخواید اطلاعات عمیق‌تری پیدا کنید این مقاله رو بخونید). توابع هش رمزنگاری شده، احتمال این یکنواختی (Hash Collision) رو بسیار کم میکنن.روش درست هش کردن رمزها!من اینجا سعی میکنم به طور کامل توضیح بدم که هش کردن صحیح رمزها چطور باید انجام بشه. اوایل به مسائل ساده رسیدگی و کم‌کم پیچیده‌ترش میکنم.پایه: هش کردن با سالتقبلا توضیح دادم که هکرها چطور میتونن هش‌های ساده رو بشکنن و رمزها رو بردارن و فهمیدیم که چطور میشه سالت رو ساخت.سالت حتما باید توسط CSPRNGها یا (Cryptographically Secure Pseudo-Random Number Generator)ها ساخته بشن. سعی کردم فارسیش رو پیدا کنم و موفق نشدم، برای همین از اینجا به بعد بهشون CSPRNG میگم.CSPRNGها با سازنده‌های اعداد معمولی خیلی فرق دارن (نمونش تابع rand() در زبان C). در واقع CSPRNGها ساخته شدن تا از نظر رمزنگاری امن باشن، به این معنی که خروجیشون خیلی تصادفی‌تر از توابع معمولیه و کاملا غیر قابل پیشبینی هستند. ما هم نمیخوایم که سالت‌هامون قابل پیشبینی باشن، برای همین باید از CSPRNGها استفاده کنیم.این پایین CSPRNGهایی که برای زبان‌های مورد استفاده خودم رو مینویسم، اگر زبانتون متفاوت هست، فقط کافیه یکمی جست‌وجو کنید، یا به من بگید تا به این لیست اضافه کنم (که خیلی خوب میشه!)CSPRNGزبانmcrypt_create_iv($size)PHPcrypto/randGolangcsprngJavaScriptSecureRandom()Javaسالت‌ها باید به ازای کاربر و رمز یکتا باشن. هربار که کاربری، حسابی رو می‌سازه یا رمزش رو بروز می‌کنه، رمزش باید توسط یک سالت جدید هش بشه. هیچوقت از یک سالت نباید چندبار استفاده بشه و باید در عین حال طول زیادی داشته باشه. (حداقل به اندازه هش پسورد)برای ذخیره رمز کافیه که:یک سالت طولانی با استفاده از CSPRNGها بسازیدسالت رو به رمز بچسبونید و حاصل رو با استفاده از یک تابع هش استاندارد مثل bcrypt هش کنیدهش و سالت رو به صورت جداگانه تو پایگاه داده ذخیره کنید.برای بررسی رمزها هم:سالت کاربر رو از پایگاه داده بخونید،سالت و رمز رو به هم بجسبونید و با همون الگوریتم قبلی هش کنید،هش ساخته شده رو با اونچه که تو پایگاه داده ذخیره کردید بررسی کنید.اگر از وب‌اپلیکیشن‌ها استفاده می‌کنید و مشغول ساخت یکی هستید، حتما هش رو سمت سرور انجام بدید! (قابل توجه برنامه‌نویس‌های React, Vue و غیره)اگر در حال ساخت یک وب‌اپلیکیشن هستید، شاید براتون سوال بشه که هش رو باید کجا انجام بدید؟ آیا رمز باید سمت کاربر هش بشه یا سمت سرور؟ یا اینکه باید بصورت خام یا plain سمت سرور ارسال بشه و بعد تبدیل بشه؟حتی اگر رمز کاربر رو با جاوااسکریپت هش میکنید، حتما این کار رو سمت سرور انجام بدید! ممکنه بگید، من رمز رو سمت کاربر نگه می‌دارم و اینطوری اصلا رمزی به سرور ارسال نمیشه و اینطوری امن‌تر به نظر میاد. اما اینطور نیست!مشکل اینجاست که هشی که سمت کاربر ساخته شده، تبدیل به رمز کاربر میشه، و شما تنها کاری که کافیه بکنید اینه که هش رو به سرور بفرستید و ببینید که جواب میگیرید یا نه. حالا این وسط اگر یه هکر، صرفا هش شده رمز رو پیدا کنه میتونه وارد حساب کاربر بشه، بدون اینکه خود رمز رو بدونه! درواقع اگر هکر رمزها رو از پایگاه داده برداره، به حساب‌های همه دسترسی داره بدون اینکه اصلا رمزشون رو بدونه.هش کردن سمت کاربر خوبه، ولی حتما باید این شروط برقرار باشن:هش کردن سمت کاربر، اگر ارتباط امن نباشه (HTTPSهای SSL یا TLS) کاربردی نداره، یک واسط خیلی راحت میتونه این وسط قرار بگیره و سورس کد رو دستکاری کنه و رمز رو استفاده کنه،بعضی از مرورگرها جاوااسکریپت رو خوب پشتیبانی نمیکنن، بعضی کاربرها ممکنه جاوااسکریپت رو غیر فعال کرده باشن و مشکلات دیگه‌ای وجود داشته باشه. برای راحتی بیشتر، اپ شما باید چک کنه که اصلا میتونه اینکار رو انجام بده یا نه،هر هشی که از سمت کاربر میاد رو هم باید سالت کنید! راحتترین روش اینه که از سرور بخواید تا براتون سالت رو ارسال کنه تا شما سمت کاربر رمز و سالت رو بررسی کنید، نکنید این کار رو!شکستن رمز رو سخت‌تر کنیدبرای اینکار میشه از توابع هش کند استفاده کرد. کاری که سالت انجام میده اینه که کار رو برای هکرها از طریق جداول لوک‌آپ و رنگین‌کمان سخت‌تر میکنه، اما نمیتونه جلوی بروت فورس اتک و دیکشنری رو بگیره. امروزه کارت گرافیک‌های پیشرفته (GPU) میتونن میلیاردها هش رو در ثانیه حساب کنن، پس همچنان این حمله‌ها اثر گذار خواهند بود. برای اینکه بشه جلوی این روش ها رو تا حدود زیادی گرفت، باید از تکنیک کشش کلیدی یا Key Stretching استفاده کرد.ایده اینه که هش‌هارو با توابع خیلی کند بسازیم، که شکستنشون زمان زیادی ببره و عملا استفاده از این روش‌ها رو بی‌ارزش یا خیلی گرون قیمت کنه. این روش در عین حال باید برای کاربر سریع باشه.کشش کلیدی از توابع خاصی استفاده میکنه که مستقیما از سی‌پی‌یو کار میکشن. این توابع، معمولا یه فاکتور امنیتی یا تعداد تکرار رو به عنوان آرگومان دریافت میکنن. این آرگومان مشخص میکنه که این پروسه چقدر باید کند انجام بشه.حواستون باشه که اگر از وب‌اپ استفاده می‌کنید، این روش میتونه ضربه حاصل از حملات داس (DoS یا Denial of Service) رو زیاد کنه. بنابراین فاکتور امنیتی رو باید به دقت انتخاب کنید، و بهتره تعداد پایین رو در نظر داشته باشید. یکی از کارهایی هم که میتونید بکنید، استفاده از کد کپچا (Captcha) برای هربار لاگین توسط کاربره. این میتونه جلوی حملات داس رو بگیره.شکستن رمز رو غیر ممکن کنید!هکرها همیشه میتونن با استفاده از بروت فورس اتک رمز رو پیدا کنن. اینجا میخوام روشی رو توضیح بدم که با استفاده از اون، هش‌ها رو فقط برای یک شخص خاص قابل استفاده میکنه.اضافه کردن یک کلید امنیتی یا Secret Key به رمزها، باعث میشه تا رمز فقط برای شخص یا اشخاصی که به این کلید دسترسی دارن بتونن از رمز استفاده کنن. این کار با استفاده از رمزنگاری توسط سایفری مثل AES و یا اضافه کردن کلیدی به هش با استفاده از HMAC هست.اینکار انقدرها هم که به نظر میاد ساده نیست. کلید چیزیه که حتما باید هنگام نفوذ از دست هکرها دور بمونه. اگر هکرها به کل سیستم دسترسی پیدا کنن، کلید هیچ فایده‌ای نداره و دیگه سیستم امن نیست. برای همین بهترین‌کار اینه که کلید رو مثلا تو یه پارتیشن دیگه که خ.ودش رمزنگاری شده نگه‌داریم.من این روش رو به هر سرویسی که بیشتر از ۱۰۰هزار کاربر داره توصیه میکنم و بنظر سرویس‌هایی که بیش از یک میلیون کاربر دارن حتما باید از این روش استفاده کنن.اگر توانایی خرید سرورهای مختلف رو ندارید، میتونید مثلا با یه اسکریپت موقع نصب سایت روی سرور و کانفیگش، یک کد تصادفی بسازید و اون رو توی یک فایل ذخیره کنید که دسترسی بهش به جز از طریق کد شما، غیر مجاز باشه.کارهایی که حتما باید انجام بدیدتمام توضیحات بالا برای این هستن که اگر سایت نفوذ پیدا کرد، رمزها به سرقت نرن! یادتون باشه که باید تلاش کنید تا هکرها حتی به مرحله نفوذ هم نرسنحتی برنامه‌نویس‌های حرفه‌ای هم میتونن اشتباهات امنیتی کنن. سعی کنید در مورد امنیت اطلاعات کسب کنید و دانشتون رو بالا ببرید.همیشه از برنامه‌هاتون تست نفوذ بگیریدسرورتون رو مانیتور کنید و مطمئن بشید که کسی مشغول دستکاری نیستبرای راحتی، یک نمونه کد هم به زبان Go نوشتم و پاسخ برخی از سوالاتی که به طور معمول برای برنامه‌نویس‌ها ایجاد میشه رو هم دادم. برای ادامه این مطلب میتونید به سایت خودم یه سری بزنید.موفق باشید</description>
                <category>آیین</category>
                <author>آیین</author>
                <pubDate>Sun, 18 Mar 2018 19:33:46 +0330</pubDate>
            </item>
            </channel>
</rss>