<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های عامر لطفی اوریمی</title>
        <link>https://virgool.io/feed/@amerllica</link>
        <description>دولوپر فرانت‌اند - علاقمند به جاوااسکریپ (تایپ‌اسکریپت)، ری‌اکت، ری‌اکت‌نیتیو - فرانت‌اند دولوپر سابق دیجی‌کالا، دیجی‌کالامگ، شیپور و سیبچه</description>
        <language>fa</language>
        <pubDate>2026-06-19 12:17:30</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/10350/avatar/o1Yrzx.png?height=120&amp;width=120</url>
            <title>عامر لطفی اوریمی</title>
            <link>https://virgool.io/@amerllica</link>
        </image>

                    <item>
                <title>پیش پردازنده‌های CSS</title>
                <link>https://virgool.io/JavaScript8/%D9%BE%DB%8C%D8%B4-%D9%BE%D8%B1%D8%AF%D8%A7%D8%B2%D9%86%D8%AF%D9%87%D9%87%D8%A7%DB%8C-css-px0jj3r4crjk</link>
                <description>مدتی هست که می‌خوام مقاله‌ای رو انتشار بدم که در مورد چند مورد جدید در JavaScript هست، ولی بر اثر چند مورد پیش اومده احساس کردم شاید اونطور که باید حق مطلب، در مورد CSS و مسائل، چالش‌ها و ابزارهای مربوط به اون بیان نشده. توی این مقاله قصد دارم در مورد پیش پردازنده‌های CSS یا همون CSS Preprocessors و فواید استفاده از اون‌ها صحبت کنم. امیدوارم که شما دوستان علاقمند به برنامه نویسی UI و کلا دولوپ سمت front-end از این مطلب خوشتون بیاد.CSSکلا CSS چیه؟درواقع Cascading Style Sheets یا همون CSS مفسر این هستند که چطور المان‌های HTML روی صفحه نشون داده بشن و به چند شکل به پروژه افزوده میشن و مرورگر با لود کردن و اعمال اون‌ها به صورت آبشاری UI رو می‌سازه. هر مرورگری بسته به دانش خودش از CSS ظاهری رو نشون میده که فکر کنم توی این جمع همه با Internet Explorer آشنا هستیم. بعله. مخصوصا نسخه‌های قدیمیش که واقعا برای front-end کارها دردسرهای زیادی رو فراهم کرده.خوشبختانه در سالهای اخیر شاهد مرگ نسخه ۶، ۷ و ۸ این مرورگر هستیم و ان‌شاءالله تا یه چند وقت دیگه الباقیشم به خاطره‌ها می‌پیوندن و راحت می‌شیم از دستشون. گرچه مایکروسافت دست بردار نیست و همچنان داره مرورگر میسازه. الحمدالله این نسخه‌های جدید که با نام edge معرف حضور هستند دارند کمی بهتر عمل می‌کننپردازش روی CSSدر نگاه اول، پردازش روی CSS مفهوم خاصی نداره. یعنی چی؟ CSS مجموعه‌ای از کدهای هست که قراره مفسر HTML تگ‌ها باشند و بدون جاوااسکریپت پویا نیستند و ثابت هستند. پس این پردازش یعنی چی؟درواقع، منظور از پردازش در زمان ساخت یا همون develop هست. یعنی شما کد‌ها رو می‌نویسید و از شیوه‌ها و از syntax های خاصی استفاده می‌کنید و کتاب خونه‌ای این وسط میاد اون شیوه‌ها و syntax ها رو ترجمه می‌کنه به یک یا چند فایل CSS و ضمن این کار، شما خیلی از کارهایی که قبلا دستی انجام می‌دادید رو به ماشین می‌سپارید.پردازش‌هایی هم هستند مثل PostCSS که می‌تونه بعد از ساخته شدن CSS انجام بشه و اون رو هر چه بهتر، فشرده‌تر و کارآمد‌تر کنه. توی این مقاله فقط در مورد پیش پردازشگر توضیح می‌دم.پیش پردازشگر SCSSتوی این زمینه پیش پردازشگرهای زیادی وجود دارند که معروف ترین‌های اونها Less هست. Less توی نسخه‌های قدیمیش کمبود‌هایی داشت و توی حجم بالای پروژه پردازش دولوپش فوق العاده کـُند میشد برای همین برنامه نویس‌ها به سمت Sass رفتن. نسخه‌های اولیه اون با ruby نوشته شد که هنوز هم پایدار هستند ولی بعد node-sass هم ساخته شد که توی پروژه‌های بزرگ جاوااسکرپتی مثل React App ها ازش استفاده میشه. کلمه Sass مخفف مجموعه کلمات Syntactically awesome style sheets هست. ولی این نسخه خیلی syntax جالبی نداشت و به جای curly brace از indent استفاده می‌کرد. چیزی شبیه pythonکمی بعد نسخه‌ای از Sass منتشر شد که از آکولاد استفاده کرد و چهره‌اش خیلی خیلی شبیه CSS شد. این نسخه رو Sassy CSS یا همون SCSS نامگذاری کردند. سینتکس بسیار جالب و شبیه به CSS که قابلیت‌های nesting, function, loop, placeholder, extend, include, mixins و خیلی چیزهای دیگه رو داشت.راهنمایی نصب و راه اندازی و مثال‌هاش توی سایت خودش هست و واقعا انقدر واضحه که نیازی به توضیح دادن و ورودش به اینجا نیست. خودتون می‌تونید برید ببیند و بخونید و توی پروژه‌های خودتون ازش استفاده کنید.فواید استفاده از پیش پردازش‌گرهادوست ندارم خیلی ریز و دقیق بشم و متن حوصله سر بر بشه. فرض کنید طراح از یه سری رنگ استفاده کرده. مثلا پالت پروژه رو با ۷ رنگ ساخته و با این ۷ رنگ طرح‌ها رو پیاده کرده و جاهایی که خواسته تیره و روشن کنه روی Photoshop یا Sketch ش از همین رنگ‌ها استفاده کرده و شما هم با دست خالی و بدون هیچ ابزاری کد زدید. یا مثلا فاصله‌ها و padding, margin ها رو یه عدد خواص مثل ۱۲ گذاشته.بعد یهو به دلایل UXی یا دستورات مدیریتی یا هرچیز دیگه میان اون ۷ رنگ اصلی رو عوض می‌کنن یا مثلا اون ۱۲ رو می‌کنن ۱۶.فاجعه شروع شد! شما باید کل CSS ‌ها رو از زیر ذره بین رد کنی و همه این مقادیر رو تغییر بدی. خیلی خیلی بده. در صورتی که توی پروژه‌ای که با یک پیش پردازشگر استارت خورده ما همچین چیزی داریم:$primary: #f00;
$secondary: #0a0;
...
$gutter: 12px;و در کد اصلی استفاده می‌کنیم:.wrapper {
    padding: $gutter;
    
    &amp;__header {
        background-color: $primary;
    }
}خروجی هم اینه:.wrapper {
    padding: 12px;
}
.wrapper__header {
    background-color: #f00;
}یعنی اینجا شما نیاز نداری بری کل پروژه رو چرخ بزنی مقادیر رو عوض کنی. فقط اونجایی که variables رو تعریف کردی تغییرات جدید رو می‌ذاری و CSS فایل جدید با مقادیر جدید برات ساخته میشه.پیش پردازنده‌ها فواید زیاد دارن. مثلا Cross-Browser بودن کدهای خروجی. شما می‌تونید از mixins ها یا از placeholder ها استفاده کنید و کدهایی رو بنویسید که نسخه‌های مختلفش نوشته شده و دیگه نیاز نیست دستی همه نسخه‌ها رو با هم بزنید. مثلا:%displayFlexPlaceholder { 
    display: -webkit-box;
    display: -webkit-flex;
    display: -moz-box;
    display: -ms-flexbox;
    display: flex;
}
...
.container {
    @export %displayFlexPlaceholder;
}
.box {
    @export %displayFlexPlaceholder;
}
#rootWrapper {
    @export %displayFlexPlaceholder;
}و خروجی:.container, .box, #rootWrapper {
    display: -webkit-box;
    display: -webkit-flex;
    display: -moz-box;
    display: -ms-flexbox;
    display: flex;
}روش بالا اسمش placeholder هست. mixin ها یکم متفاوت هستند ولی تقریبا کار مشابهی می‌کنن. حتی شما می‌تونید کد‌هاتون رو تیکه تیکه کنید. یعنی فولدر بندی کنید و همه رو یک جا import کنید. مثلا فایل variables رو جدا کنید. فایل تعریف fonts رو جدا کنید. اسم صفحات رو از هم جدا کنید. قسمت‌های مختلف هر صفحه رو جدا کنید و توی یک زیر فولدر قرار بدید. قسمت‌های public رو که همه استفاده می‌کنن رو توی یه public.scss بگذارید. به این کار partialise کردن میگن.این partialise کردن فوق العاده مهمه، چون وقتی پروژه بزرگ میشه دیباگ رو خیلی خیلی راحت می‌کنه. من خودم همیشه یه پوشه می‌سازم به اسم helpers و ۴ تا فایل توش تعریف می‌کنم به نام‌های reset, variables, requirement, extensions. توی extensions میام تمام placeholder ها رو قرار میدم. همونی که توی مثال بالا نوشتم و اولش % داشت. اینا به هیچی تبدیل نمی‌شن، وقتی فایل آخر ساخته شد اون‌هایی که ازش extend گرفتن مقادیر اون placeholder رو بر میدارن و توی requirement هم تعریف فونت‌ها، انیمیشن‌ها،‌ اشکال فونتی و غیره رو انجام می‌دم. نمی‌گم این استاندارده و همه اینطوری می‌نویسن ولی طبق تجربه‌ام به این تقسیم بندی خوب رسیدم.کنار پوشه helpers یه پوشه می‌سازم به اسم public که توش menu, header, footer و کلا چیزهایی که توی کل پروژه استفاده می‌شه رو قرار می‌دم. الباقی پوشه بندی هم طبق ساختار جلو می‌رم مثلا pages یا routes و توی pages باز پوشه می‌سازم و دونه دونه صفحات رو می‌نویسم. و اگر نیاز شد که صفحات رو به قسمت‌های ریزی تبدیل کنم توی پوشه صفحات یه فولدر می‌سازم به نام partials که اونجا قطعات ریز‌تر رو میذارم. این آخرین مرحله از تقسیم گری هست و درخت فایل‌های SCSS از این عمیق‌تر نمیشه.فولدر بندی من برای partialise کردن فایل‌ها.بعدش توی فایل style که میشه گفت ریشه اصلی این درخت هست، اینطوری می‌نویسم:/* @import helpers */
@import &#039;helpers/variables&#039;;
@import &#039;helpers/requirement&#039;;
@import &#039;helpers/extensions&#039;;
@import &#039;helpers/reset&#039;;

/* @import public */
@import &#039;public/public&#039;;

/* @import home; */
@import &#039;pages/pages&#039;;ترتیب در کد بالا، خیلی اهمیت داره. همین کار رو برای public و pages هم باید انجام بدیم، مثلا فایل pages رو هم اینجا می‌نویسم:/* @import pages */
@import &#039;home/home&#039;;
@import &#039;login/login&#039;;
@import &#039;sourcePayment/sourcePayment&#039;;
@import &#039;requestMoney/request-money&#039;;
@import &#039;ipgBack/ipg-back&#039;;و چون طبق عکس صفحه sourcePayment قسمت زیرین هم داشت بد نیست کد اون رو هم ببینید:/* @import partials */
@import &quot;partials/buttons&quot;;

/** @define source payment; */
.source-payment {

    &amp;__text-field {
        @extend %align-row;
        justify-content: space-between;
        margin-bottom: 20px;
        width: 85%;

        &amp;--money {
            @extend %align-row;
            justify-content: center;
            margin-bottom: 20px;
            width: 85%;
        }

        &amp;__help-text {
            display: block;
            width: 235px;
        }

        &amp;__avatar {
            @extend %radius-circle;
            @extend %center;
            width: 100px;
            height: 100px;
        }
    }

    input {
        width: 85%;
    }
}

.single-button {
    @extend %align-row;
    justify-content: flex-end;
}

.modal-pin-code {
    @extend %position-c-c;
    width: 85%;
    padding: 20px;

    &gt; div &gt; div {
        margin-bottom: 20px;
    }
}برای کسب اطلاعات و مثال‌های کامل‌تر می‌تونید از سایت اصلی خودش بخونید.امیدوارم که این مقاله تونسته باشه اونطور که باید حق مطلب رو ادا کرده باشه.</description>
                <category>عامر لطفی اوریمی</category>
                <author>عامر لطفی اوریمی</author>
                <pubDate>Fri, 28 Dec 2018 12:07:44 +0330</pubDate>
            </item>
                    <item>
                <title>مقایسه PureComponent و memo در React.js</title>
                <link>https://virgool.io/iran-react-community/%D9%85%D9%82%D8%A7%DB%8C%D8%B3%D9%87-purecomponent-%D9%88-memo-%D8%AF%D8%B1-reactjs-pp5wyhwgjjus</link>
                <description>React.jsمقدمهمدتیه که به وضوح داره دیده میشه استفاده از React توی پروژه‌ها زیاد شده. syntax تمیز، تفکر اصولی در معماری این کتابخونه و روش قابل فهم برای دولوپرها و انعطاف پذیری React در پیاده سازی برای انواع پروژه‌ها مخصوصا پروژه‌های legacy باعث شده محبوب بشه. جا داره یه ریز به React Native اشاره کنم که خب در نوع خودش منحصر به فرد هست و با اینکه هنوز به نسخه یک نرسیده، انقدر قابلیت داره که انتخاب خیلی‌ها برای دولوپ برنامه‌های Android و iOS شده.مدتی میشه که تیم React چند مورد جدید به کتابخونه اضافه کرده که خیلی خیلی جذاب هستن. می‌تونید برای دیدن این موارد جدید به مقاله زیر مراجعه کنید: https://virgool.io/JavaScript8/reactjs-for-the-future-consrpouwfu6 اما توی این مقاله می‌خوام یه نگاه دقیق تری به نوشتن کامپوننت‌ها داشته باشم. نوشتن کامپوننت‌ها، در ابتدا راحت و ساده به نظر میاد ولی وقتی پروژه بزرگ و بزرگ‌تر میشه می‌بینیم که یکم پردازش زیاد میشه، مخصوصا موقع دولوپ، حتی ممکنه صفحه پروژه روی موبایل لگ‌های زیاد و اعصاب خوردکنی پیدا کنه.صفحه وبی که با لگ شدیدی روی موبایل اسکرول می‌شهاین یک مثاله و مشکلات زیاد دیگه‌ای هم پیش میاد که حتی روی سیستم دسکتاپتون هم مشاهده میشه و باعث هنگ کردن مرورگرتون میشه.واسه React Native که نگم براتون، برنامه قسمت‌های native داره که به صورت نرمال front-end کارها ازش اطلاعاتی ندارن. و باید تا جایی که می‌تونن قسمت JavaScript رو با ظرافت و تیز بینی بنویسن. ازین سبک مشکلات پرفورمنسی باعث منصرف زیاد باطری، کندی، لگ و در نهایت کرش می‌شه که واقعا دیباگش و پیدا کردن مشکلاتش فوق العاده سخته.توی این مقاله قصد دارم توضیحاتی در مورد component lifecycle method مهمی به نام shouldComponentUpdate بدم که خیلی واضح به PureComponent و memo می‌رسیم.فرق Component و PureComponentزمانی بود که برای نوشتن برنامه سریع Component رو از کتابخونه React دیستراکت import می‌کردم و سریع یه کامپوننت می‌ساختم و خیلی هم خوشحال بودم.import React, { Component } from &#039;react&#039;;تا اینکه با دوستم سهیل آشنا شدم. یکبار به من گفت چرا کامپوننت رو همیشه render می‌کنی! من اولش متوجه نشدم و ایشون اشاره به مبحث Shallow Comparison کرد. با جستجوی ریزی به این رسیدم که یک lifecycle method ی وجود داره به نام shouldComponentUpdate که همیشه توی React.Component داره مقدار true بر می‌گردونه;shouldComponentUpdate() {
    return true;
}درسته، ما نمی‌بینیمش ولی همینه. این یعنی وقتی والدم آپدیت شد و داره رندر میشه من رو هم رندر کن. خب وقتی نیازی به این کار نیست چرا باید اینطوری بشه؟ این در صورتی هست که توی PureComponent اینطور نیست:import React, { PureComponent } from &#039;react&#039;;
...
shouldComponentUpdate( nextProps, nextState ) {
    if ( notEqual( this.props, nextProps ) ) {
        return true;
    }
    if ( notEqual( this.state, nextState ) ) {
        return true;
    }
    return false;
}
...یعنی تا زمانی که props یا state تغییری نکنه رندر دوباره‌ای در کار نیست. و این عالیه.فرق Functional Component و Class Componentببینید، خیلی راحته، شما هم می‌تونید یک کامپوننت ساده Hello World ری‌اکت رو هم به صورت یک function جاوااسکریپت بنویسید هم به صورت کلاس‌های ES6 ی تعریف کنید. اما این دو چه فرقی با هم دارن؟ خروجی که همون خروجی هست. برای نشون دادن فرق‌های این دو لازمه که اول سه فرق ساده رو بگم:اول از همه قیافشونه. وقتی یک قسمت کاملا نمایشی داریم که هیچ interaction ی نداره برای چی باید کد بیشتری بنویسیم. لزومی نداره.مورد بعدی بحث state هست. آره مثلا شما بخوای یه کلید سوئیچ بسازی باید state بسازی و تاگلش رو بذاری توی state ولی وقتی فقط از props یه چیزی میگیره و نمایش میده چرا باید Component بنویسیم. لزومی نداره.مبحثی هست به نام lifecycle methods  که به برنامه نویس توابعی رو میده که میشه توی زمان‌های مختلف زندگی یک کامپوننت کدهایی رو اجرا کرد. مثل قبل از اتصال به VDOM، بعد اتصال، در هر آپدیت و رندر شدن و ... که این‌ها رو functional component نداریم. وقتی نیاز به این‌ها نداریم پس بازم لزومی نداره که کامپوننتمون رو کلاس طوری بنویسیم.و اما آخری... زمانی که کامپوننت ساده Hello World رو به دو صورت می‌نویسیم و نسخه production build می‌گیریم، code دیدن داره... خودتون تماشا کنید:DEV - function component:import React from &#039;react&#039;;

const HelloWorld = () =&gt; &lt;div&gt;Hello World&lt;/div&gt;;

export default HelloWorld;DEV - class component:import React, { PureComponent } from &#039;react&#039;;

class HelloWorld extends React.PureComponent {
    render() {
        return (
            &lt;div&gt;Hello World&lt;/div&gt;
        );
    }
}

export default HelloWorld;PROD - functional component &#039;use strict&#039;;

Object.defineProperty(exports, &quot;__esModule&quot;, {
  value: true
});

var _react = require(&#039;react&#039;);

var _react2 = _interopRequireDefault(_react);

function _interopRequireDefault(obj) { return obj &amp;&amp; obj.__esModule ? obj : { default: obj }; }

var HelloWorld = function HelloWorld() {
  return _react2.default.createElement(
    &#039;div&#039;,
    null,
    &#039;Hello World&#039;
  );
};

exports.default = HelloWorld;فقط نگاه کنید و ببیند که یک function ساده با الکی کلاس کامپوننت نوشتن به چه چیزی تبدیل شده:PROD - class component&#039;use strict&#039;;

Object.defineProperty(exports, &quot;__esModule&quot;, {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i &lt; props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (&quot;value&quot; in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _react = require(&#039;react&#039;);

var _react2 = _interopRequireDefault(_react);

function _interopRequireDefault(obj) { return obj &amp;&amp; obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(&quot;Cannot call a class as a function&quot;); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(&quot;this hasn&#039;t been initialised - super() hasn&#039;t been called&quot;); } return call &amp;&amp; (typeof call === &quot;object&quot; || typeof call === &quot;function&quot;) ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== &quot;function&quot; &amp;&amp; superClass !== null) { throw new TypeError(&quot;Super expression must either be null or a function, not &quot; + typeof superClass); } subClass.prototype = Object.create(superClass &amp;&amp; superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var HelloWorld = function (_React$PureComponent) {
  _inherits(HelloWorld, _React$PureComponent);

  function HelloWorld() {
    _classCallCheck(this, HelloWorld);

    return _possibleConstructorReturn(this, (HelloWorld.__proto__ || Object.getPrototypeOf(HelloWorld)).apply(this, arguments));
  }

  _createClass(HelloWorld, [{
    key: &#039;render&#039;,
    value: function render() {
      return _react2.default.createElement(
        &#039;div&#039;,
        null,
        &#039;Hello World&#039;
      );
    }
  }]);

  return HelloWorld;
}(_react2.default.PureComponent);

exports.default = HelloWorld;آره... می‌دونم باور نمی‌کنید. هر کسی باور نمی‌کنه، خودش بره به این آدرس سر بزنه، خودش امتحان کنه.البته بگما میشه فشرده‌اش کرد و یکم این هیولا رو درستش کرد ولی همینه که می‌بینید، عمق فاجعه همینه.بهینگی PureComponent یا سادگی functionاگر  یکم فکر کنید یک سوال trade-off ی پیش میاد. یکی بهینه هستش و الکی رندر نمیشه و یکی دیگه خیلی کم حجم هست.خوب الآن ما از کدوم استفاده کنیم؟آخه functional component که چیزی نداره، فقط  چیزهایی رو که از props ش می‌گیره رو نمایش میده. پس همیشه رندر میشه. و در کنارش کلاس کامپوننت مخصوصا PureComponent از یک lifecycle method استفاده می‌کنه که میشه باهاش از رندرهای الکی جلوگیری کرد.چیکار باید بکنیم؟ ???تولد memoاینجا بود که در نسخه جدید ری‌اکت Hook ها رو وارد کردند. ابزار بسیار مفیدی که خیلی از چالش‌ها و trade-off ها رو حل کرده. memo در واقع برای functional component ها ساخته شده. تا زمانی که props ش تغیری نکنه نمیذاره که الکی توی آپدیت‌ها رندر بشه. فانکشن هم که state نداره پس داستان تمامه. کد بهینه و کم حجم.به کد زیر دقت کنید:import React, { memo } from &#039;react&#039;;

const HelloWorld = () =&gt; &lt;div&gt;Hello World&lt;/div&gt;;

export default memo(HelloWorld);و حالا نسخه پروداکشن:&#039;use strict&#039;;

Object.defineProperty(exports, &quot;__esModule&quot;, {
  value: true
});

var _react = require(&#039;react&#039;);

var _react2 = _interopRequireDefault(_react);

function _interopRequireDefault(obj) { return obj &amp;&amp; obj.__esModule ? obj : { default: obj }; }

var HelloWorld = function HelloWorld() {
  return _react2.default.createElement(
    &#039;div&#039;,
    null,
    &#039;Hello World&#039;
  );
};

exports.default = (0, _react.memo)(HelloWorld);به نظرم واضح و کامله همه چیز. چیزی برای گفتن ندارم. موفق باشید.</description>
                <category>عامر لطفی اوریمی</category>
                <author>عامر لطفی اوریمی</author>
                <pubDate>Thu, 27 Dec 2018 02:07:32 +0330</pubDate>
            </item>
                    <item>
                <title>همکار خوبی باشیم</title>
                <link>https://virgool.io/programmers-revolution/%D9%87%D9%85%DA%A9%D8%A7%D8%B1-%D8%AE%D9%88%D8%A8%DB%8C-%D8%A8%D8%A7%D8%B4%DB%8C%D9%85-dqhc4zk11dxd</link>
                <description>همکاران خوبمقدمهتوی مدتی که از سال ۹۰ تا حالا وارد بازار کار شدم با افراد زیادی روبرو شدم و باهاشون همکار شدم و کنار هم مدتی رو کار کردیم. توی این دوران دوستان و آشنایان زیادی رو پیدا کردم و هنوز هم با اینکه خیلی از هم دور هستیم جویای احوال همدیگه هستیم و با چند نفر از این دوستان هنوز هم همکاری‌هایی رو داریم. موضوعی که باعث شد این نوشته رو بنویسم اینه بود که چطور میشه رابطه‌ها در محیط کار فقط در حد یک رابطه و سلام و علیک یا یه آشنایی و نه بیشتر می‌مونه و چطور میشه رابطه‌ها به یک دوستی عمیق و حتی خانوادگی منجر میشه. چه مسائلی هست که نمیشه بیان کرد و کاملا هم از طرفین به طور پیشفرض انتظار میره.امروز دل به دریا زدم و گفتم که بنویسم. شاید کمی متن این نوشته تند و حتی جاهایش زشت و خارج از عرف باشه ولی به نظرم یکی باید این‌ها رو بگه. مواردی رو که عرض می‌کنم بعضی‌هاش به خودِ من هم می‌خوره. پس اگر جسارت به کسی شد من عذرخواهی می‌کنم.پاکیزگی شخصی (personal hygiene)پاکیزگی شخصی شاید به نظر اول کمی خنده‌دار بیاد ولی موضوع کاملا جدی‌ای هست. اولین موضوع جدی و شرط لازم و کافی برای یک همکار خوب بودن هست. هرکسی اگر از نظر دانش کاری بهترین توی زمینه خودش باشه و فوق العاده اهل سعی و گوشش و خودسازی باشه ولی پاکیزگی و بهداشت شخصی رو رعایت نکنه از نظر همه رد شده هستش. شاید هرکسی رو الآن بخوان بخاطر مهارتش ولی در نهایت که کارشون تمام شد یطوری میگن که بره، همیشه هم براش سواله چرا! چون اون‌ها روشون نمی‌شد بگن که اون فرد بوی بد می‌داد.همکار بد بو!بعله، خیلی برای هر دو طرف ناراحت کننده هستش، هم اونی که داره همکار بدبو رو تحمل می‌کنه هم اونی که از همکارش می‌شنوه که بو میده و یا با رفتار همکاران می‌فهمه که داره شرایط خوب کار رو در محیط از همکاراناش می‌گیره.خیلی سخت نیست. راه حل‌هاش خیلی ساده هست، نباید نگاه زودگذر و سطحی داشته باشیم. مثلا فقط سریع بریم چندتا لباس نو بخریم و عطر و ادکلن بزنیم و فکر کنیم موضوع حل شده. چون با رعایت نکردن موارد ریشه‌ای چند روز بعد باز هم همون شرایط به وجود خواهد اومد. چاره‌اش چند تا راه ساده هستش:سعی کنیم هر روز حموم بریم، اگر هر روز نمیشه، یا نمی‌تونیم یا تنبلی نمی‌ذاره، یک روز در میون بریم حتما. لازم هم نیست از شامپوهای گرون یا چیز خاصی استفاده کنید. شستن موی سر و بدن و جاهایی از بدن خودمون که احساس می‌کنیم خیلی عرق می‌کنه کافیه که ما رو متفاوت کنه با گذشته.جسارته ولی چون زندگی پنج ساله در خوابگاه دانشجویی و دوره خدمت سربازی، چیز‌هایی رو به من نشون داد که باورش برام سخت بود این روش خصوصی و حرف زشت رو می‌زنم. ?، باز هم عذرخواهی می‌کنم: موهای زیربغل رو همیشه بزنیم و نگذاریم بیشتر از ۱ میلی‌متر بشه. وجود موهای زیاد در این ناحیه بوی عرق و موندگی رو شدیدا تشدید می‌کنه و توی محل کار حیطه بدی رو دور نفر ایجاد می‌کنه.نحوه اصلاح موهای زائد زیربغل۳. بعد از حمام رسیدگی‌های زیادی وجود داره ولی نیازی نیست همه اون‌ها رو انجام بدیم. می‌دونم شاید تنبلی و بی حوصله بودن یا شاید هم کار زیاد و کمبود وقت نذاره به انواع کِرِم‌ها و لوسیون‌ها فکر کنیم ولی استفاده از یک مام می‌تونه از تعریق زیاد جلوگیری کنه و حتی بعد از عرق هم باعث خوشبویی بشه. پیشنهاد من مام صابونی رکسونا هستش. رنگ بندی زیادی داره و هر کدوم خاصیت جالبی داره ولی شکلش دقیقا به شکل زیر هست:مام صابونی رکسونا (چهار رنگ)۴.  مسواک و تمیز بودن دهان علاوه بر اینکه سلامتی برای خود شخص داره تا حد خیلی زیادی باعث میشه بوی بد دهان از بین بره، ولی واقعا کافی نیست. چون بوی بد دهان علل مختلفی داره. گاهی زیاد سیگار کشیدن، گاهی گرسنگی و خالی بودن معده، گاهی خرابی دندون گاهی مریضی حتی چیزی مثل سرماخوردگی می‌تونه باعثش بشه. واقعا برای برطرف کردن علل مختلف باید زمان و هزینه گذاشت که خوب زمان می‌بره و این در صورتی هست که همکاران ما الآن دارن اذیت می‌شن. به نظر من چیزی که می‌تونه یکم سر این موضوع برامون زمان بخره استفاده از آدامسه. خرج سنگینی هم نداره. انواع آدامس هم در بازار هست و هرکس به سلیقه و نظرش روی سطح هزینه می‌تونه تهیه کنه و همیشه توی جیبش داشته باشه. من از آدامس 5 استفاده می‌کنم.آدامس فایو - 5۵.  شاید این موردی که دارم میگم یکم براتون خنده‌دار باشه ولی این موضوع همه جایی هست و هم بین آقایون و هم بین خانم‌ها رواج زیادی داره. توی محیط کار کفشتون رو در نیارید و یا اگر محیط کارتون فضای خیلی خودمونی و خونگی‌ای داره حتما در مورد بوی کفشتون و یا تمیزی و پاکیزگی جورابتون مطمئن باشید. برای این مورد میشه از کفی‌های نازک بوگیر برای کفش استفاده کنید یا از جوراب‌های مخوصص که بوگیر هستند استفاده کنید. ولی باز هم پیشنهاد من اینه که پاتون رو از کفشتون در نیارید.۶.  پاکیزگی خود لباس علاوه بر اینکه خود فرد رو تبدیل به یک آدم شیک پوش می‌کنه باعث میشه زحماتی که در قسمت‌های بالا کشید هدر نره. اتو داشتن یا نداشتنش کاملا به خود فرد ربط داره ولی اینکه شسته شده باشه و بو نده یک امر محیطی هستش. پس باید رعایت بشه. الکی نباید لباس‌های برند و گرون قیمت خریداری بشه. هیشکی نظرش به خاطر اینکه فردی فلان برند رو می‌پوشه تغییر نمی‌کنه. مرتب شسته شدن و تمیز بودن و در کل بو ندادن در اولویت هستش.۷.  موارد بالا کافیه که یک نفر پاکیزه باشه، چیزی که شخصیه ولی به دیگران هم مربوط میشه. حالا داشتن یک عطر یا ادکلن خوب باعث میشه شما خاص باشید. این مورد شرط لازمی نیست و من فقط برای کمال این بخش، عرض کردم. این قسمت خیلی حساسه چون دقیقا در نقطه مقابل بوی بد هست. ممکنه من، به نظر خودم عطر خوبی بزنم ولی انقدر تند باشه که دیگران خیلی خوششون نیاد. مثل عطر‌هایی که نت‌های گرم و زمستونه دارن مثل Black Afgano یا همون بلک‌افغان، خودم مدتی از همین عطر استفاده می‌کردم و یک بار یکی از همکارانم به من این موضوع رو گفت و من سریعا از عطر سبکتری با رایحه چوب استفاده کردم. پس باید مواظب باشید. ولی تذکر شنیدن توی این مورد خیلی خیلی بهتر از تذکر شنیدن و یا دیدن رفتارهای خاص دیگران برای بدبو بودنه.تعادل رفتارموضوعات شخصی و مشکلات زندگی هر کسی به خودش ربط داره و این نباید به محل کار کشیده بشه. این دقیقا در نقطه مقابل اون مساله هست که شما نباید مشکلات کاری خودتون رو به منزل ببرید. این دو محیط باید از هم جدا باشند. دلیلی نداره که چون فردی از دست نامزدش ناراحته یا داره رابطشون خراب میشه این مسائل رو به محیط کار بکشونه و با کوچکترین موضوعی شروع به پرخاش کنه.خشونت در محل کار حتی اگر رفتار فردی یا جمعی نامناسب، در محل کار شد، میشه طی یک جلسه یا صحبت‌های چهره به چهره موضوع رو بیان کرد و دوستانه یا یکم جدی‌تر موضوع رو حل کرد. اگر احساس کردیم یکی از همکاران که به تازگی ارتقا گرفته داره به سبک خاصی رئیس بازی در میاره می‌تونیم این موضوع رو دوستانه و حتی با حالت غمگین و اینکه من ازت انتظار اینچنین رفتاری رو ندارم، علت این موضوع رو ازش بخوایم به احتمال زیاد این به نتیجه می‌رسه.حرف به حرف کردن و پشت کسی صحبت کردن هرگز به نتیجه مطلوب نرسیده. این رو کامل در این ۷ سال دیدم. پشت کسی صحبت کردن فقط کار ترسو‌ها هستش. اگر از کسی انرژی منفی میگیریم بریم به خودش بگیم، اگر واقعا می‌بینیم که نمیشه با این آدم کار کرد و گوش شنوا نداره و با تذکرات جداگانه اعضا، خودش رو اصلاح نمی‌کنه، سلسله مراتبی عمل کنیم و اگر باز نتیجه نگرفتیم از اونجا بریم. اون محل کار مناسبی نیست. ولی باز هم هنگام خروج بد رفتار نکنیم. کارهایی رو که باید، انجام و تحویل بدیم. ما حرفه‌ای برخورد کنیم و طوری رفتار کنیم که همه یاد روز‌های خوشِ اونجا باشن. ما از خودمون انرژی و اثر مثبت بگذاریم. دنیا به قدری کوچیکه که همه یه چندبار دیگه به هم می‌رسن. و کاری کنیم که این ما نباشید که خجل باشیم. این به مراتب برام اتفاق افتاده که عرض می‌کنم.خداحافظی حرفه‌ایجانشین پروریباور کنید نمیشه برای ارتقا، حد و مرز تعیین کرد. به نظرم هیچ کس نباید به جایگاه کاری خودش بسنده کنه و فکر کنه که به نهایت رسیده که اگر اینطور باشه یواش یواش دست از خودآموزی و رشد می‌کشه و شروع می‌کنه به حفظ و نگه‌داری از پُست کاری. خیلی‌ها رو دیدم که بر اثر تلاش خودشون یا اتفاقی، به مدیریت یا سرپرستی یا تیم لیدی رسیدن و از یک جایی به بعد به جای اینکه نگاه کنند چطور می‌تونن باز هم پیشرفت کنن تصمیم به محافظت از جایگاه فعلی خودشون گرفتن. این تصمیم در هر صورت با شکست روبرو میشه. اون کسی که این تصمیم رو می‌گیره شاید خودش هم ندونه، ولی ناخودآگاه نیروهای خبره رو از محل کار دور می‌کنه و خیلی‌ها ازونجا میرن، خودش چیزی یاد نمی‌گیره و دائم مواظب دیگرانه که بر علیه‌ش توطئه نکنن، به جایی می‌رسه که این رفتارش تبدیل به بیماری میشه، حتی رشد دانشی و خودآموزیِ افراد تیم رو یک نوع توطئه می‌بینه و بر علیه اون اقدامات زشتی انجام میده. این اعمال نه تنها محل کار رو تبدیل به جای بدی می‌کنه بلکه منافع سازمان رو مورد خطر قرار میده و ممکنه پروژه‌های خوبی توی سازمان شکل نگیره، رشد نکنه، ارتقا پیدا نکنه، افراد کلیدی برن و حتی انقلاب‌هایی، هرچند کوچیک بیاد و مثل سیل همه چیز رو با خودش ببره و همه این‌ها اتفاق افتاده چون اون فرد به فکر جایگاه خودش بوده. متاسفانه سیستم اینطور عوامل رو خواه ناخواه، بالاخره حذف می‌کنه و فقط این به یاد‌ها می‌مونه که همکاریهِ خوبی شکل نگرفته.عاشقان منصب و مقامبه نظرم به جای این بیایم به همکاران و افراد تحت نظر، آموزش بدیم و فرصت رشد براشون ایجاد کنیم و برای رشد خودمون و حتی امتحان کردن چالش‌های دیگه زمان خداحافظی با جایگاه تعیین کنیم و به جای اینکه سیستم ما رو مثل یک عنصر از کار افتاده و ناکارآمد حذف کنه، خودمون کنار بکشیم و راه رو برای افراد جدید باز کنیم. نباید فکر کنیم که چون ما به تیم لیدیِ فلان استک در فلان شرکت رسیدیم پس هیچ کس دیگه نمی‌تونه برسه. جهان پر بوده از مدیران موفق و بعدش مدیران موفق‌تر از اون‌ها، و دوباره بعدش نابغه‌های مدیریت که خیلی خیلی بهتر از قبلی‌ها عمل کردن.اشتراک گذاری دانششاید این قسمت کمی شبیه همون قسمت جانشین پروری باشه که دقیقا هم هست ولی تفاوت‌هایی هم داره که باعث شد این قسمت رو در بخش جدایی بیارم، دانش مثل آب زلال می‌مونه و آب زمانی که به چرخش در میاد و در شکل‌های مختلف جریان پیدا می‌کنه زندگی رو ایجاد می‌کنه. یادمه خیلی قدیم‌ها افراد خبره‌ای که توی سازمان یا حتی جامعه بودند دانششون و اون فوت کوزه‌گری رو به هیچ کسی نمی‌گفتند. درسته اون رو به سختی به دست آوردن ولی واقعا چه دلیلی داشت که اونطوری در انحصار داشته باشنش؟ نشر دانشمدت‌ها گذشت و وقتی اینترنت و بنیاد‌های متن باز رسیدند این رفتارها کنار رفت و خودتون می‌تونید ببینید دنیا برای رشد چه سرعتی در پیش گرفته. مخصوصا دنیای Information Technology که واقعا سرعت باورنکردنی‌ای داره.حداقل برای اینکه ازین فرهنگ جهانی جا نمونیم، می‌تونیم دانشمون رو با سخاوتمندی هرچه تمام در اختیار نیرو‌های جدید و همکارانمون بذاریم. یادمون باشه که چیزی بلد نبودن عیب نیست، چون با تلاش به دست میاد. این عیبه که یک فردی توی یه سازمانی مدتی باشه و در اون مدت همونطور بمونه. اونوقت باید از خود اون فرد تا کل بخش بخش‌های سازمان زیر سوال برن.تیم یا محیط کاری‌ای که برای افرادش آموزش و یادگیری به همراه داره، انقدر دوست داشتنی میشه که هیچ کس دلش نمی‌خواد به هیچ نحوی بهش ضربه وارد بشه. این‌ها شعار نیست و در تیم‌ها و شرکت‌هایی از همین کشور خودمون این شکل از رفتارها وجود داره. یادمه که در دو مصاحبه کاری از استارتاپ‌های مختلف، این موضوع رو اذعان داشتم که اینی که شما می‌خواین رو من بلد نیستم، و یکیشون بهم گفت عیب نداره. ۵۰ ساعت کاری اول از شما Code نمی‌خوایم شما مطالعه کن یاد بگیر. یا جای فعلی‌ای که هستم، تیم لیدی که با من مصاحبه کرد گفت عیب نداره باهم می‌خونیم یاد میگیریم. بعدا فهمیدم خودش خبره بود، اینطوری می‌‌گفت که من اعتماد به نفسم رو از دست ندم چرا که TypeScript بلد نیست. پس رویا نیست. میشه با یه تغییر کوچیک و یک نگرش ساده و رفتار خوب خیلی خیلی ساده همکار بهتری باشیم و محل کار دلچسب‌تری برای خودمون و همکارانمون بسازیم.بخش پایانیاصلا دوست ندارم اینطور برداشت بشه که این نوشته یه نصیحت بزرگترانه بوده، خیلی از این رفتارها و اعمال به خودِ من هم مربوط میشه. و قطعا برای یه همکار خوب بودن و شاد بودن کنار همکارن، کنار کسانی که از خانوادمون بیشتر می‌بینمشون کارهای بیشتری میشه کرد. ولی خُب! به نگاه و دید محدودِ من، این موارد از اصلوب همکارِ خوب بودن هست. امیدوارم کسی رو ناراحت نکرده باشم و امیدوارم که همه همکاران و دوستان خوبی برای همدیگه باشیم.</description>
                <category>عامر لطفی اوریمی</category>
                <author>عامر لطفی اوریمی</author>
                <pubDate>Thu, 08 Nov 2018 20:47:45 +0330</pubDate>
            </item>
                    <item>
                <title>مثال کاملی از پیاده سازی یک برنامه وبی پایه بر React</title>
                <link>https://virgool.io/iran-react-community/%D9%85%D8%AB%D8%A7%D9%84-%DA%A9%D8%A7%D9%85%D9%84%DB%8C-%D8%A7%D8%B2-%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%DB%8C%DA%A9-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%88%D8%A8%DB%8C-%D9%BE%D8%A7%DB%8C%D9%87-%D8%A8%D8%B1-react-efebuxevlbih</link>
                <description>A perfect React application on the cutting edge of technology-- مقدمهافرادی که در حوزه وب فعالیت می‌کنن، به راحتی می‌تونن جستجو بزنن و خیلی از موارد مربوط به یک برنامه وبی پایه بر React رو ببینن و نمونه‌ پیاده سازی‌های اون رو داشته باشن، موارد و مفهوم‌های مثل:پایش سمت سرور (Server Side Rendering)استفاده از React Routerاستفاده از CSS Modulesاستفاده از PostCSSتنظیمات Webpackنوشتن Expressتنظیمات برای جداسازی محیط develop و محیط productionابزارهای قوی برای Deploy برنامه‌های بزرگمقیاس پذیری یا همون Scale کردن برنامه‌هابرنامه‌های تک صفحه‌ای (Single Page Application)برنامه‌های پراگرسیو (Progressive Web Application)و...موارد زیاد هستن، و خیلی گیج کننده که گاهی همین زیادی تکنیک‌ها و تکنولوژی‌ها باعث میشه، این‌ها رو خوب کنار هم نگذاریم و چیز خوبی از آب در نیاد. یا اینکه کنار هم می‌گذاریم ولی چنگی به دل خودمون نمی‌زنه، یه چیز‌هایی رو توی سایت‌های شرکت‌های بزرگی مثل Pinterest یا Instagram یا Facebook و غیره، می‌بینیم که برامون سواله که این‌ها چطور عمل می‌کنند و چطور یک برنامه بزرگ React رو با تمام استاندارد‌ها پیکربندی می‌کنن و حجم عظیمی از برنامه نویس‌ها کنار هم بدون داشتن کوچکترین تداخلی کار می‌کنند.توی این مقاله قصد دارم با یک نگاه ساده یک مثال یا بهتره بگم که یه پلتفورم خوب، کامل و قابل بزرگ شدن در مقیاس‌های عظیم رو قدم به قدم توضیح بدم.در انتهای این مقاله شما یک ریپوی کامل دارید که می‌تونید یک برنامه React ی خوب و تمیز داشته باشید که شامل خیلی از تکنیک‌ها و تکنولوژی‌های روز و ترند هست. خروجی‌ شما خیلی خیلی شبیه کارهای خوب توی این حوزه خواهد بود و سعی کردم که همه گل‌ها رو یک جا جمع کنم. ولی این دلیلی بر این نیست که شما از اینی که هست نتونید بهترش کنید.خز؛پن ! (خیلی زیاد؛پس نخون) : اگر فاقد حوصله هستین و دوست دارید نتیجه رو نگاه کنید ریپو رو ببینین و ازش استفاده کنید.چیزی که من دلم می‌خواد اینه که اگر شما هم ایده یا نگرشی برای بهتر کردن این ریپو دارید، یه سر به Github بزنید، Fork کنید و کارتون رو Pull Request کنید. من و Andrew، کاملا استقبال می‌کنیم.-- می‌خوایم چی بسازیم؟اگر یه چرخ بزنید برای دیدن مثال‌های پیاده سازی یک React App موارد زیادی پیدا می‌کنید که هر کدوم ویژگی‌هایی رو دارند، مثل SSR یا استفاده از React Helmet و خیلی چیزهای دیگه اما بیشتر اون‌ها برای اهداف develop نوشته و انتشار داده می‌شن، هیچ کدوم هر دو هدف develop و deploy صحیح رو دنبال نمی‌کنن و استانداردهای این دو محیط رو اصلا بیان نمی‌کنن.من توی این مقاله می‌خوام هم محیط develop خوبی رو براتون شرح بدم که بدون خون ریزی و با سرعت زیاد کارتون رو انجام بدید هم محیط production رو با حداقل استانداردها داشته باشیم. باز هم تاکید می‌کنم این مقاله فوق العاده ساده هست و موارد زیادی رو من توش نیاوردم. که می‌تونید شما بیارید و در تکمیل این مقاله، مقاله بدید و کد‌ها رو هم به ریپوی اصلی Pull Request بدید و اینطوری باعث پیشرفتش بشید.-- ابزارها و تکنولوژی‌های مورد استفاده در این مقاله:ReactReact router 4React HelmetCSS ModulesPostCSSWebpack 3BabelExpressPM2-- نیازمندی‌ اولیهدر ابتدا شما باید Node نصب داشته باشید، ترجیحاً آخرین نسخه پایدار، که اگر ندارید از سایت نود دانلود و نصبش کنید.-- خوب حالا چیکار کنیم؟قدم بعدی اینه که برای برنامه‌ای که قراره بنویسیم یک فولدر بسازیم. از همین اول اتمام حجت کنم. با فولدر بندی، هم کار خودت دسته بندی میشه هم منظم‌تر میشه هم تا درصدی برای مقیاس پذیری داری آماده‌اش می‌کنی. هرکسی در فولدر بندی شیوه‌ای داره من اینطوری هستم که توی این مقاله هست. شما می‌تونی برای خودت اونی که احساس می‌کنی بهتره رو پیاده سازی کنی.خوب مثلا اسم فولدر اصلیمون رو می‌ذاریم react-example و بعد بسته به سیستم عاملتون با محیط کامندی وارد فولدر مربوطه بشید، برای ویندوزی‌ها cmd یا powershell هست و برای مک و لینوکس هم terminal ، من فرض می‌کنم که وارد شدید، حالا دستور زیر رو تایپ کنید:npm initاین دستور در هنگام اجرا شدن چندتا سوال ازتون می‌پرسه که پاسخش رو بدید، نگران نباشید این سوال و جواب‌ها برای ساختن فایل package.json هست که به راحتی می‌تونید بعدا اصلاحش کنید، پس اصلا نگران نباشید. یک سری سوالاتش رو هم که حال نکردید اصلا جواب ندید و کلید اینتر رو بزنید که سریع‌تر از این مرحله خلاص بشیم.خوب داره جالب میشه، من خودم خیلی ذوق دارم، حالا دستور زیر رو بزنید: npm install --save react@16.3.2 react-dom@16.3.2در واقع شما با دستور بالا دو  dependency اصلی این مقاله رو نصب کردید، فولدری کنار فایل package.json ساخته میشه به نام node_modules که این dependency ها و الباقی موارد رو اونجا نگه می‌داره که شما خیلی تحویلشون نگیرید، فعلا توی اون مراحل نیستیم که به این موارد اهمیت بدیم. اون عدد‌ها هم نسخه‌هایی هست که من دارم باهاشون کار می‌کنم و تاکید می‌کنم شما هم از همین نسخه استفاده کنید، چون این موارد خیلی زود بروز می‌شن و اگر شما خیلی دیر این مقاله رو بخونید ممکنه نسخه‌های جدید مشکلاتی ایجاد که عملا این مقاله رو بدرد نخور می‌کنه، برای همین شما با نسخه‌ای که من وارد می‌کنم نصب کنید که اجرای موفقی رو داشته باشید و بعدش اگر دلتون خواست به نسخه‌های جدیدتر بروزرسانی کنید، این کار رو خودم کردم، Andrew زمانی که این استک رو نوشت داستانش فرق داشت، خیلی چیز‌ها رو نداشت و از نسخه‌های پایین‌تری استفاده می‌کرد. من وقتی که مقاله‌اش رو خوندم حس کردم یه سری چیز‌ها می‌تونه بروزتر بشه و همین کار رو هم کردم و با ویرایش‌های دیگه بهش PR دادم و این مثال خوب رو پیشرفت دادم.میریم مرحله بعدی، خوب دستور زیر رو بزنید: npm install --save-dev babel-loader@7.0.0 babel-core@6.24.1 webpack@3.11.0این‌ها هم dependency های این پروژه هستند منتهی برای محیط ساختن یا همون develop برای همینه که بعد دستور install از فرمان save-dev استفاده کردم، بعدا که برید فایل package.json رو بخونید متوجه میشید چطوری دارن جدا میشن و در آینده میگم که اصلا این نوع سوا کردنشون یعنی چی.خوب حالا نوبت این شده که Babel رو نصب کنیم، سوال اینه که این چیه؟ ساده بگم که قراره شما کد‌های خیلی خیلی آپدیتی بزنید و از ویژگی‌های جدید جاوااسکریپت استفاده کنید ولی قرار نیست وقتی خروجی می‌گیرید و برنامه رو برای deploy آماده می‌کنید مرورگرها هم مثل شما خفن باشن، ممکنه مردم از مرورگرهای زمان قلی قلی میرزا استفاده کنن پس باید هوای اون‌ها رو هم داشته باشیم. Babel به شما اجازه میده خفن باشید و خفن کد بزنید ولی در نهایت زمانی که Webpack برای شما خروجی می‌سازه، خروجی‌ای میده بیرون که هر مرورگر پیرپاتال یا جوونی بفهمه. پس حالا کد زیر رو بزنید:npm install --save-dev babel-preset-es2015@6.24.1 babel-preset-react@6.24.1 babel-preset-env@1.5.1 babel-preset-stage-0@6.24.1این‌ها dependency های مورد نیاز بری تنظیم Babel توی این مقاله هستش، بسیاری پلاگین و dependency برای Babel هست که بعدا خودتون با نیاز‌ها و مشکلاتی که براتون پیش میاد باهاشون آشنا میشید، اینجا هم برای حداقلی این‌ها رو گذاشتم. روش استفاده‌اش هم اینه که شما باید یه  فایل بسازی به نام .babelrc که متاسفانه بخاطر زبان فارسی نقطه در انتها نمایش داده شده. اصل اسم به صورت زیر هست:.babelrcتوی این فایل باید تنظیمات Babel رو انجام بدید: {
  &quot;presets&quot;: [
    &quot;env&quot;,
    &quot;es2015&quot;,
    &quot;react&quot;,
    &quot;stage-0&quot;
  ]
}هر کدوم از این‌ها یک معنایی داره مثلا es2015 برای اینه که کد‌هایی که ES6 ی زده میشه مثل class یا constructor تبدیل میشه به ES5 و این باعث میشه اون مرورگر‌های قدیمی هم بفهمنش، یا مثلا react باعث میشه که کد‌های JSX تبدیل به توابع جاوااسکریپتی React بشن مثل  createElement . من بیشتر از توضیح نمی‌دم، می‌تونید در مورد الباقی جستجو و تحقیق کنید که چه به درد می‌خورن یا چه تنظیماتی دارند و چه چیز‌های دیگه‌ای میشه گذاشت، اگر سوال داشتید در همین مقاله در کامنت سوالاتتون رو بپرسید.-- تنظیمات Webpackتا الآن همه فایل‌ها و تنظیمات پایه‌ای بودن و همه رو توی روت پروژه یا همون فولدرمون گذاشتم، و از اینجا به بعد می‌خوام که فایل‌ها رو دسته بندی بریم جلو،‌ طوری که هم منظم باشن هم بدونیم چی کجاست. این نوع فولدربندی باعث میشه در آینده برای تغییرات هم راحت‌تر باشید هم به راحتی برنامه‌تون رو به مقیاس بزرگ‌تری ببرید.همونطور که در بالا گفته بودم ما دوتا محیط داریم، یکی برای ساختن یا develop و یکی هم برای محیط عملیاتی یا production ، پس برای این منظور یک پوشه به نام webpack بسازید و داخلش یک فایلی بسازید به نام webpack.development.config.js و محتوای اون رو اینطوری بنویسید:const path = require(&#039;path&#039;);
const ExtractTextPlugin = require(&#039;extract-text-webpack-plugin&#039;);

const distDir = path.join(__dirname, &#039;../dist&#039;);
const srcDir = path.join(__dirname, &#039;../src&#039;);

module.exports = [
    {
        name: &#039;client&#039;,
        target: &#039;web&#039;,
        entry: `${srcDir}/client.jsx`,
        output: {
            path: path.join(__dirname, &#039;dist&#039;),
            filename: &#039;client.js&#039;,
            publicPath: &#039;/dist/&#039;,
        },
        resolve: {
            extensions: [&#039;.js&#039;, &#039;.jsx&#039;]
        },
        devtool: &#039;source-map&#039;,
        module: {
            rules: [
                {
                    test: /\.(js|jsx)$/,
                    exclude: /(node_modules[\\\/])/,
                    use: [
                        {
                            loader: &#039;babel-loader&#039;,
                        }
                    ]
                },
                {
                    test: /\.pcss$/,
                    use: ExtractTextPlugin.extract({
                        fallback: &#039;style-loader&#039;,
                        use: [
                            {
                                loader: &#039;css-loader&#039;,
                                options: {
                                    modules: true,
                                    importLoaders: 1,
                                    localIdentName: &#039;[local]&#039;,
                                    sourceMap: true,
                                }
                            },
                            {
                                loader: &#039;postcss-loader&#039;,
                                options: {
                                    config: {
                                        path: `${__dirname}/../postcss/postcss.config.js`,
                                    }
                                }
                            }
                        ]
                    })
                },
            ],
        },
        plugins: [
            new ExtractTextPlugin({
                filename: &#039;styles.css&#039;,
                allChunks: true
            })
        ]
    },
    {
        name: &#039;server&#039;,
        target: &#039;node&#039;,
        entry: `${srcDir}/server.jsx`,
        output: {
            path: path.join(__dirname, &#039;dist&#039;),
            filename: &#039;server.js&#039;,
            libraryTarget: &#039;commonjs2&#039;,
            publicPath: &#039;/dist/&#039;,
        },
        resolve: {
            extensions: [&#039;.js&#039;, &#039;.jsx&#039;]
        },
        module: {
            rules: [
                {
                    test: /\.(js|jsx)$/,
                    exclude: /(node_modules[\\\/])/,
                    use: [
                        {
                            loader: &#039;babel-loader&#039;,
                        }
                    ]
                },
                {
                    test: /\.pcss$/,
                    use: [
                        {
                            loader: &#039;isomorphic-style-loader&#039;,
                        },
                        {
                            loader: &#039;css-loader&#039;,
                            options: {
                                modules: true,
                                importLoaders: 1,
                                localIdentName: &#039;[local]&#039;,
                                sourceMap: false
                            }
                        },
                        {
                            loader: &#039;postcss-loader&#039;,
                            options: {
                                config: {
                                    path: `${__dirname}/../postcss/postcss.config.js`,
                                }
                            }
                        }
                    ]
                }
            ],
        },
    }
];در این فایل می‌بینید که قسمت client و server رو جدا کردم و برای هر قسمت تنظیماتی گذاشتم که بعضی‌هاش مشابه هست و بعضی‌هاش فرق داره که اینجا خیلی توضیح نمی‌دونم، چون همینطوری این مقاله طولانی هست و توضیحات هر بخش اون یک مقاله جدا می‌خواد، اگر مایل بودید در کامنت یا توئیت به من امر کنید حتما توضیح می‌دم یا در صورت نیاز مقاله‌ای جدا می‌نویسم.-- تنظیمات PostCSSخوب، لازمه بگم که ماجرای این پیش پردازشگر CSS یکم از الباقی دوستانش جداست، شما نه تنها باید خودش رو نصب کنید، بلکه باید پلاگین‌هاش رو هم نصب کنید و اینطوری هی اون رو قوی و قوی‌تر می‌کنید، هرجا احساس کردید کاری رو انجام نمیده جستجو کنید، حتما پلاگین جالبی براش هست، من برای سادگی نصب خودش و حداقل پلاگین‌هاش رو در زیر قرار می‌گذارم:npm install --save-dev autoprefixer@8.3.0 css-loader@0.28.4 css-mqpacker@6.0.2 isomorphic-style-loader@4.0.0 postcss@6.0.21 postcss-apply@0.10.0 postcss-cssnext@3.1.0 postcss-custom-properties@7.0.0 postcss-extend@1.0.5 postcss-loader@2.1.4 postcss-nested@3.0.0 postcss-nested-ancestors@2.0.0 postcss-partial-import@4.1.0 postcss-scss@1.0.5 style-loader@0.21.0 extract-text-webpack-plugin@3.0.2داخل روت پروژه فولدری به نام postcss بسازید و داخلش فایلی بسازید به نام postcss.config.js و تنظیمات این CSS Preprocessor محبوب رو در اون قرار بدید، شاید بگید چرا از SCSS استفاده نکردم. اگر در مورد PostCSS یکم مطالعه کنید متوجه می‌شید چه فوایدی نصبت به الباقی هم خانواده‌هاش داره، یکی از فواید خوبش داشتن پلاگینی به نام autoprefixer هست که عملا نیاز شما رو به mixin ها از بین می‌بره و با یک تنظیم ساده در کد زیر می‌تونید سطح پوشش پشتیبانی از نظر CSS رو روی مرورگرها تغییر بدید:module.exports = {
    ident: &#039;postcss&#039;,
    syntax: &#039;postcss-scss&#039;,
    map: {
        &#039;inline&#039;: true,
    },
    plugins: {
        &#039;postcss-partial-import&#039;: {
            &#039;prefix&#039;: &#039;_&#039;,
            &#039;extension&#039;: &#039;.pcss&#039;,
            &#039;glob&#039;: false,
            &#039;path&#039;: [&#039;./../src/styles&#039;]
        },
        &#039;postcss-nested-ancestors&#039;: {},
        &#039;postcss-apply&#039;: {},
        &#039;postcss-custom-properties&#039;: {},
        &#039;postcss-nested&#039;: {},
        &#039;postcss-cssnext&#039;: {
            &#039;features&#039;: {
                &#039;nesting&#039;: false
            },
            &#039;warnForDuplicates&#039;: false
        },
        &#039;postcss-extend&#039;: {},
        &#039;css-mqpacker&#039;: {
            &#039;sort&#039;: true
        },
        &#039;autoprefixer&#039;: {
            &#039;browsers&#039;: [&#039;last 15 versions&#039;]
        },
    }
};-- حالا خود برنامهخیلی واضحه که برنامه ما ممکنه چندین صفحه داشته باشه و باید چیزی وجود داشته باشه که مسیر این صفحات رو هندل کنه و اینجاست که من دوست عزیزم react-router رو وارد بازی می‌کنم. فقط توجه داشته باشید من می‌خوام از نسخه آخر یا همون ۴ استفاده کنم برای همین با دستور زیر آخرین نسخهء ۴ رو نصب می‌کنم: npm install --save react-router-dom@4.2.2بعد از این کار یک فولدری بسازید به نام src و در اون فایلی به نام client.jsx بسازید و محتویات زیر رو در اون قرار بدید:import React from &#039;react&#039;;
import {hydrate} from &#039;react-dom&#039;;
import {BrowserRouter} from &#039;react-router-dom&#039;;
import App from &#039;./app/App&#039;;

hydrate((
    &lt;BrowserRouter&gt;
        &lt;App/&gt;
    &lt;/BrowserRouter&gt;
), document.getElementById(&#039;root&#039;));بعد کنار همین فایلی که ساختید فایلی بسازید به نام server.jsx و کد‌های زیر رو در اون قرار بدید:import React from &#039;react&#039;;
import ReactDOMServer from &#039;react-dom/server&#039;;
import {StaticRouter} from &#039;react-router-dom&#039;;
import {Helmet} from &quot;react-helmet&quot;;
import Template from &#039;./app/template&#039;;
import App from &#039;./app/App&#039;;

export default function serverRenderer({clientStats, serverStats}) {
    return (req, res, next) =&gt; {
        const context = {};
        const markup = ReactDOMServer.renderToString(
            &lt;StaticRouter location={req.url} context={context}&gt;
                &lt;App/&gt;
            &lt;/StaticRouter&gt;
        );
        const helmet = Helmet.renderStatic();

        res.status(200).send(Template({
            markup: markup,
            helmet: helmet,
        }));
    };
}حالا کنار این‌ها دو پوشه بسازید، توی یکیش فایل‌های اصلی React یا همون برنامه خودمون رو می‌نویسیم و توی یکی دیگه قراره فایل‌های PostCSS یا همون استایل‌های CSS رو قرار بدیم، اولی رو app و دومی رو styles نامگذاری کنید.-- -- فایل‌های برنامهداخل فولدر app در ابتدا فایل به نام template.jsx بسازید و تمپلیت اصلی html ی که قراره همه چیز در اون تزریق بشه رو بسازید:export default ({ markup, helmet }) =&gt; {
   return `&lt;!DOCTYPE html&gt;
         &lt;html ${helmet.htmlAttributes.toString()}&gt;
            &lt;head&gt;
               ${helmet.title.toString()}
               ${helmet.meta.toString()}
               ${helmet.link.toString()}              
            &lt;/head&gt;
            &lt;body ${helmet.bodyAttributes.toString()}&gt;
               &lt;div id=&quot;root&quot;&gt;${markup}&lt;/div&gt;
               &lt;script src=&quot;/dist/client.js&quot; async&gt;&lt;/script&gt;
            &lt;/body&gt;
         &lt;/html&gt;`;
};بعد یک فایلی بسازید به نام App.jsx که این فایلی هست که برنامه‌ اصلی رو داخلش می‌نویسید، من فعلا چیز ساده‌ای می‌نویسم، اما شما به دلخواه خودتون می‌تونید پوشه بندی کنید و یک مدل بزرگ‌تری رو خلق کنید:import React, {Component} from &#039;react&#039;;

export default class App extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            &lt;div&gt;                
                &lt;h1&gt;Hello World!&lt;/h1&gt;
            &lt;/div&gt;
        );
    }
}یکم جلوتر دوباره سراغ این فایل میام و یکم بهش چیز میز اضافه می‌کنم اما فعلا بذاریم ساده باشه که یه چیز ساده بتونیم توی مرورگر تماشا کنیم که خیالمون راحت باشه همه چیز داره درست کار می‌کنه.فقط یه چیز خیلی ساده اضافه کنم، react-helmet، این یکی انقدر ساده هستش که نگو، و فوق العاده بدرد بخور، ازوناست که کلی فواید SEOی داره برامون. درواقع قسمت head هر صفحه رو برامون dynamic میسازه و کلی آپشن داره که میشه ازش به راحتی استفاده کرد، برای نصب این از دستور زیر استفاده کنید:npm install --save react-helmet@5.2.0فعلا فقط این رو نصب کنید، زمانی که دوباره به فایل App.jsx برگشتیم، خودتون متوجه می‌شید که چه کارهای ساده ولی به درد بوخوری میشه باهاش کرد.-- -- فایل‌های استایلداخل فولدر styles یک فایل اصلی بسازید به نام styles.pcss و کنارش یک فولدر بسازید به نام partials و داخلش فایلی اضافه کنید به نام _partial.pcss و محتویات زیر رو در اون کپی کنید:// styles.pcss
@import &quot;partials/partial&quot;;

.component {
   @extend %box;
   color: #2f95ff;
}

.text {
   display: flex;
   @extend %box;
}

.test {
   display: flex;
}

.active {
   color: red;
}و// partials/_partial.pcss
%box {
  box-shadow: 0 0 10px 1px #ff6fc3;
}-- تنظیمات سرور developسرور محیط develop ما express.js خواهد بود، در واقع به این صورت هست که ما یک سری middleware استفاده می‌کنیم که زمانی که تغییراتی در فایل‌های PostCSS یا فایل‌های برنامه ایجاد می‌کنیم، به عبارتی داریم develop می‌کنیم، خودش خود به خود فایل‌های نهایی رو بسازه و ما نتیجه آخرین تغییراتمون رو داخل مرورگر ببینیم.ابتدا باید پکیج‌های dependency رو نصب کنیم:npm i --save-dev express@4.15.3 webpack-dev-middleware@2.0.6 webpack-hot-middleware@2.22.1 webpack-hot-server-middleware@0.5.0بعد در روت پروژه یا همون فولدر react-example پوشه‌ای می‌سازیم به نام express و تنظیمات محیط develop رو برای express درش قرار می‌دیم، برای این کار فایلی بسازید به نام development.js و داخلش اینطوری بنویسید:const express = require(&#039;express&#039;);
const app = express();
const webpack = require(&#039;webpack&#039;);
const config = require(&#039;./../webpack/webpack.development.config.js&#039;);
const compiler = webpack(config);
const webpackDevMiddleware = require(&#039;webpack-dev-middleware&#039;);
const webpackHotMiddleware = require(&#039;webpack-hot-middleware&#039;);
const webpackHotServerMiddleware = require(&#039;webpack-hot-server-middleware&#039;);

app.use(webpackDevMiddleware(compiler, {
    serverSideRender: true,
    publicPath: &quot;/dist/&quot;,
}));
app.use(webpackHotMiddleware(compiler.compilers.find(compiler =&gt; compiler.name === &#039;client&#039;)));
app.use(webpackHotServerMiddleware(compiler));

const PORT = process.env.PORT || 3000;

app.listen(PORT, error =&gt; {
    if (error) {

        return console.error(error);

    } else {

        console.log(`Development Express server running at http://localhost:${PORT}`);
    }
});-- ببینیم چی شد تا الآنحالا وقتشه یه تست ریز بریم ببینم تا الآن چیکار کردیم، برای اینکه ببینیم همه چیز رو تا الآن درست به کار گرفتیم یا نه دستور زیر رو در محیط کامندیمون اجرا می‌کنیم:node ./express/development.jsاگر ویندوز دارید و خطای NODE_ENV رو دیدید اصلا نگران نشید به این آدرس یه سر بزنید، اونجا نوشتم که چیکار باید بکنید، اگر خطا نداد که باید توی محیط کامندیتون جمله زیر رو ببینید:Development Express server running at http://localhost:3000اگر آره که نصف راه رو به سلامت رسیدید و می‌تونید مرورگرتون رو با آدرس http://localhost:3000 باز کنید و از شاهکاری که کاشتید لذت ببرید.-- تنظیمات React Routerتا الآن همه چیز فوق العاده بود. تقریبا کلی چیزای باحال رو کنار هم به درستی گذاشتیم و همه چیز با هم کار کرد. تاکید می‌کنم اگر مشکلی داشتید توی همین مقاله در قسمت کامنت مطرح کنید، دربست در خدمتم.ولی، این react-router رو فقط نصب کردیم و توی برنامه هنوز نیاوردیمش، اونجا که در مورد فایل App.jsx گفتم که بر میگردم، آهان، الآن وقتشه که برگردیم با هم و اون رو به شکلی یکم کامل‌تر بنویسیم. فایل App.jsx رو با کد‌های زیر دوباره ویرایشش کنید:import React, {Component} from &#039;react&#039;;
import Helmet from &quot;react-helmet&quot;;
import {Switch, Route} from &#039;react-router-dom&#039;;
import {Link, NavLink} from &#039;react-router-dom&#039;;
import styles from &#039;../styles/styles.pcss&#039;;

class Menu extends Component {
    render() {
        return (
            &lt;div&gt;
                &lt;ul&gt;
                    &lt;li&gt;
                        &lt;NavLink exact to={&#039;/&#039;} activeClassName={styles.active}&gt;Homepage&lt;/NavLink&gt;
                    &lt;/li&gt;
                    &lt;li&gt;
                        &lt;NavLink activeClassName={styles.active} to={&#039;/about&#039;}&gt;About&lt;/NavLink&gt;
                    &lt;/li&gt;
                    &lt;li&gt;
                        &lt;NavLink activeClassName={styles.active} to={&#039;/contact&#039;}&gt;Contact&lt;/NavLink&gt;
                    &lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
        );
    }
}


class Homepage extends Component {

    render() {
        return (
            &lt;div className={styles.component}&gt;
                &lt;Helmet title=&quot;Welcome to our Homepage&quot;/&gt;
                &lt;Menu/&gt;
                &lt;h1&gt;Homepage&lt;/h1&gt;
            &lt;/div&gt;
        );
    }
}

class About extends Component {
    render() {
        return (
            &lt;div&gt;
                &lt;Helmet title=&quot;About us&quot;/&gt;
                &lt;Menu/&gt;
                &lt;h1&gt;About&lt;/h1&gt;
            &lt;/div&gt;
        );
    }
}

class Contact extends Component {
    render() {
        return (
            &lt;div&gt;
                &lt;Helmet title=&quot;Contact us&quot;/&gt;
                &lt;Menu/&gt;
                &lt;h1&gt;Contact&lt;/h1&gt;
            &lt;/div&gt;
        );
    }
}


export default class App extends Component {

    render() {
        return (
            &lt;div&gt;
                &lt;Helmet
                    htmlAttributes={{lang: &quot;en&quot;, amp: undefined}} // amp takes no value
                    titleTemplate=&quot;%s | React App&quot;
                    titleAttributes={{itemprop: &quot;name&quot;, lang: &quot;en&quot;}}
                    meta={[
                        {name: &quot;description&quot;, content: &quot;Server side rendering example&quot;},
                        {name: &quot;viewport&quot;, content: &quot;width=device-width, initial-scale=1&quot;},
                    ]}
                    link={[{rel: &quot;stylesheet&quot;, href: &quot;/dist/styles.css&quot;}]}
                /&gt;
                &lt;Switch&gt;
                    &lt;Route exact path=&#039;/&#039; component={Homepage}/&gt;
                    &lt;Route path=&#039;/about&#039; component={About}/&gt;
                    &lt;Route path=&#039;/contact&#039; component={Contact}/&gt;
                &lt;/Switch&gt;
            &lt;/div&gt;
        );
    }
}خوب یه توضیح ریز بدم، ببینید الآن توی این فایل App.jsx جدیدمون سه تا کامپوننت جدید آوردیم به اسم‌های Homepage و About و Contact که در واقع نقش سه صفحه ما رو بازی می‌کنن.بعدش یه کامپوننتی ساختیم به اسم Menu که اولی همین فایل App.jsx قرارش دادیم و اون رو هم توی هر سه کامپوننت ایمپورت کردیم تا در هر سه صفحه مجزایی که داریم منو هم دیده بشه.نکته‌ای که وجود داره اینه که دیگه مثل گذشته قرار نیست که کلاس‌های تگ‌ها رو اضافه کنیم. ما دیگه با کلاس شدیم و قراره که با CSS-Modules کار کنیم. در طی روند این مقاله من خیلی ریز تنظیماتش رو وارد کردم و شما فقط نیازه بدونی که توی هر کامپوننتی که مجزاش می‌کنی باید با کد: import styles from &#039;../styles/styles.pcss&#039;; استایل‌ها رو مثل یک آبجکت اضافه کنید و توی هر تگ که خواستید کلاس بهش بدید از کد زیر استفاده کنید:&lt;div className={styles.container}&gt;
    &lt;div className={styles[&#039;container-top&#039;]}
        example
    &lt;/div&gt;
&lt;/div&gt;فکر کنم خیلی واضحه دیگه، توی فایل‌های PostCSS با هر اسمی که خواستید کلاس‌هاتون رو بسازید و اینجا به جای اینکه مستقیم اسمش رو صدا بزید اون رو به صورت فرزندی از آبجکت styles صدا بزنید، این کار در نسخه‌ای که برای deploy آماده می‌کنید یا همون نسخه production اسم کلاس‌ها رو در DOM به هش تبدیل می‌کنه و می‌تونید تا حداقل ۵ حرف ببریدش، اینطوری فایل CSS آخری که می‌سازید فوق العاده فشرده شده خواهد بود. حالا بعدا، زمانی که دارم در مورد تنظیمات Webpack در محیط production صحبت می‌کنم بیشتر باهاش آشنا می‌شید.نکتهء دیگه‌ای که خیلی عاشقشم دوست خوبم Helmet هست که به وضوح توی کد‌ها دیده میشه، در هر کامپوننت به صورت مجزا وجود داره، در کامپوننت root یا اصلی یا همون App کامپوننت هم دیده میشه که تنظیمات کلی‌ای رو داره اجرا می‌کنه. انقدر این تنظیمات ساده و خوانا هست که من اینجا از توضیحش صرف نظر می‌کنم.حالا برای اینکه دوباره ببینم چیکاره هستیم یکبار دیگه دستور اجرا رو برای develop اجرا می‌کنیم:node ./express/development.jsبه نظر معجزه میاد، آره، شما تونستید یه اسکلت عالی از یک برنامه پایه بر React بسازید که همه چیز‌های عالی رو داره. هر صفحه رو که با فشار منو صدا می‌زنید از سمت سرور داره پویش یا همون render میشه و کاملا هم سمت مرورگر شما dynamic هست. ولی به نظر شما کار ما تمام شده؟هم آره هم نه، آره: چون ما محیط develop عالی‌ای رو درست کردیم و نه: چون هنوز نمی‌دونیم چطور باید اون رو برای deploy روی سرور آماده کنیم.-- آماده سازی برای اعزام به محیط عملیاتیتا الآن هر کار کردیم، برای این بوده که محیط develop خوبی رو داشته باشیم، ولی از الآن به بعد دیگه قراره که تنظیمات متفاوتی برای production قرار بدیم که سه هدف اصلی رو حتما باید در نظر بگیریم:باندل کردن کل فایل‌های برنامه و فشرده سازی و از بین بردن debuggerها و console.logها و تبدیل به نسخه ES5.1استخراج فایل styles.css در یک فایل جدا و فشرده سازی و پاک کردن همه کامنت‌هاساختن فایل stats.json که درواقع عواملی Webpackی که برای محیط عملیاتی در سرور برای express نیاز هست رو توش نگه می‌داریم و اون‌هایی که برای محیط develop بوده رو دیگه نمی‌خواهیم.پیش به سوی تنظیمات برای محیط عملیاتی، کد‌های زیر را اجرا می‌کنیم:npm install --save-dev clean-webpack-plugin@0.1.19 stats-webpack-plugin@0.6.0 optimize-css-assets-webpack-plugin@3.2.0خوب حالا باید توی فولدر webpack یک فایل دیگه به نام webpack.production.config.js بسازید و داخلش رو با کد‌های زیر پر کنید:const path = require(&#039;path&#039;);
const webpack = require(&#039;webpack&#039;);
const ExtractTextPlugin = require(&#039;extract-text-webpack-plugin&#039;);
const StatsPlugin = require(&#039;stats-webpack-plugin&#039;);
const OptimizeCssAssetsPlugin = require(&#039;optimize-css-assets-webpack-plugin&#039;);
const CleanWebpackPlugin = require(&#039;clean-webpack-plugin&#039;);

const distDir = path.join(__dirname, &#039;../dist&#039;);
const srcDir = path.join(__dirname, &#039;../src&#039;);

module.exports = [
    {
        name: &#039;client&#039;,
        target: &#039;web&#039;,
        entry: `${srcDir}/client.jsx`,
        output: {
            path: distDir,
            filename: &#039;client.js&#039;,
            publicPath: distDir,
        },
        resolve: {
            extensions: [&#039;.js&#039;, &#039;.jsx&#039;]
        },
        module: {
            rules: [
                {
                    test: /\.(js|jsx)$/,
                    exclude: /(node_modules[\\\/])/,
                    use: [
                        {
                            loader: &#039;babel-loader&#039;,
                        }
                    ]
                },
                {
                    test: /\.pcss$/,
                    use: ExtractTextPlugin.extract({
                        fallback: &#039;style-loader&#039;,
                        use: [
                            {
                                loader: &#039;css-loader&#039;,
                                options: {
                                    modules: true,
                                    importLoaders: 1,
                                    localIdentName: &#039;[hash:base64:10]&#039;,
                                    sourceMap: false,
                                }
                            },
                            {
                                loader: &#039;postcss-loader&#039;,
                                options: {
                                    config: {
                                        path: `${__dirname}/../postcss/postcss.config.js`,
                                    }
                                }
                            }
                        ]
                    })
                }
            ],
        },
        plugins: [
            new ExtractTextPlugin({
                filename: &#039;styles.css&#039;,
                allChunks: true
            }),
            new webpack.DefinePlugin({
                &#039;process.env&#039;: {
                    NODE_ENV: &#039;&quot;production&quot;&#039;
                }
            }),
            new CleanWebpackPlugin(distDir),
            new webpack.optimize.UglifyJsPlugin({
                compress: {
                    warnings: false,
                    screw_ie8: true,
                    drop_console: true,
                    drop_debugger: true
                }
            }),
            new webpack.optimize.OccurrenceOrderPlugin(),
        ]
    },
    {
        name: &#039;server&#039;,
        target: &#039;node&#039;,
        entry: `${srcDir}/server.jsx`,
        output: {
            path: distDir,
            filename: &#039;server.js&#039;,
            libraryTarget: &#039;commonjs2&#039;,
            publicPath: distDir,
        },
        resolve: {
            extensions: [&#039;.js&#039;, &#039;.jsx&#039;]
        },
        module: {
            rules: [
                {
                    test: /\.(js|jsx)$/,
                    exclude: /(node_modules[\\\/])/,
                    use: [
                        {
                            loader: &#039;babel-loader&#039;,
                        }
                    ]
                },
                {
                    test: /\.pcss$/,
                    use: [
                        {
                            loader: &#039;isomorphic-style-loader&#039;,
                        },
                        {
                            loader: &#039;css-loader&#039;,
                            options: {
                                modules: true,
                                importLoaders: 1,
                                localIdentName: &#039;[hash:base64:10]&#039;,
                                sourceMap: false
                            }
                        },
                        {
                            loader: &#039;postcss-loader&#039;,
                            options: {
                                config: {
                                    path: `${__dirname}/../postcss/postcss.config.js`,
                                }
                            }
                        }
                    ]
                }
            ],
        },
        plugins: [
            new OptimizeCssAssetsPlugin({
                cssProcessorOptions: {discardComments: {removeAll: true}}
            }),
            new StatsPlugin(&#039;stats.json&#039;, {
                chunkModules: true,
                modules: true,
                chunks: true,
                exclude: [/node_modules[\\\/]react/],
            }),
        ]
    }
];و همینطور در فولدر ‌express یک فایل به نام production.js برای محیط production بسازید و کد‌های زیر رو داخلش کپی کنید:const express = require(&#039;express&#039;);
const path = require(&#039;path&#039;);
const app = express();
const ClientStatsPath = path.join(__dirname, &#039;./../dist/stats.json&#039;);
const ServerRendererPath = path.join(__dirname, &#039;./../dist/server.js&#039;);
const ServerRenderer = require(ServerRendererPath).default;
const Stats = require(ClientStatsPath);

app.use(&#039;/dist&#039;, express.static(path.join(__dirname, &#039;../dist&#039;)));
app.use(ServerRenderer(Stats));

const PORT = process.env.PORT || 3000;

app.listen(PORT, error =&gt; {
    if (error) {

        return console.error(error);

    } else {

        console.log(`Production Express server running at http://localhost:${PORT}`);
    }
});الآن دیگه باید بتونید با دستور زیر فایل‌هایی رو بسازید که قراره برای محیط عملیاتی به سرور اعزام بشه:NODE_ENV=production webpack -p --config ./webpack/webpack.production.config.js --progress --profile --colorsمشاهده می‌کنید که فایل‌هایی در فولدر dist ساخته شده و اگر دستور زیر رو در محیط کامندیتون اجرا کنید، شما درواقع محیط عملیاتی رو شبیه سازی کردید. یجورایی چیز نهایی که مردم می‌بینند در واقع همینه:NODE_ENV=production node ./express/production.js اگر الآن روی مرورگر Google Chrome دو افزونه React Developer Tools و Wappalyzer رو داشته باشید می‌بینید که علامت React روش ظاهر شده و مخصوصا افزونه React Developer Tools آبی شده و دیگه قرمز نیست. چون قرمز برای محیط دولوپ هست و آبی یعنی شما نسخه مخصوص production رو بردی روی سرور.جدا تبریک می‌گم. شما فوق العاده‌ای، چون روند این مقاله در عین اینکه ساده‌ترین شکل رو داشته ولی جزو طولانی‌ترین‌ها و پیچیده‌ترین‌ها بوده. وقتی تا اینجا اومدی جلو یعنی شما بهترینی، مدتی هم میگذره تا شما با معجزه‌ای که کردی بیشتر آشنا بشی و اون رو custom خودتون کنید. مثلا eslint بیارید، از Redux استفاده کنید، از Redux-Saga استفاده کنید، تست، مثل Jest رو اضافه کنید و خیلی چیز‌های باحال دیگه.-- اجرا روی سرور واقعیزمانی که همه کارهای بالا رو انجام دادید باید به نفر DevOps تون بگید که روی سرور به pm2 نیاز دارید. چون برنامه‌های خفن Reactی که کاربرهای زیادی داره رو با دستور بالا روی سرور اصلی اجرا نمی‌کنن، برای این کار باید روی سرور اصلی‌تون دستور زیر رو اجرا کنید:npm install pm2 -gو برای اجرا:NODE_ENV=production pm2 start ./express/production.js البته بگما، این کار رو روی کامپیوتری که تا الآن هم استفاده کردید می‌تونید استفاده کنید، هیچ اشکالی نداره، ببینین که چه شکلیه! ولی این خروجی و نمایشتون روی مرورگر اصلا با node ./express/production.js فرقی نداره، تفاوت‌هاش رو نفر DevOps میدونه که قراره مدیریت کش و لودبالانس و اینا اضافه کنه. اگر دوست داشتید می‌تونید که داک pm2 رو بخونید.-- اختتامبرای راحتی کار دولوپ، من دستوراتی رو در قسمت scripts در فایل package.json گذاشتم که می‌تونید از آدرس گیت‌هاب که در بالای صفحه گذاشتم استفاده کنید یا همین زیر هم براتون می‌نویسم:&quot;scripts&quot;: {
  &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;,
  &quot;dev&quot;: &quot;NODE_ENV=development node ./express/development.js&quot;,
  &quot;build&quot;: &quot;NODE_ENV=production webpack -p --config ./webpack/webpack.production.config.js --progress --profile --colors&quot;,
  &quot;prod&quot;: &quot;NODE_ENV=production webpack -p --config ./webpack/webpack.production.config.js --progress --profile --colors &amp;&amp; node ./express/production.js&quot;,
  &quot;pm2&quot;: &quot;NODE_ENV=production pm2 start ./express/production.js&quot;
}یه توصیه آخر هم از من داشته باشید، درسته که تا الآن داشتیم با npm کار می‌کردیم و الآن با تنظیم بالا مثلا برای شروع develop از دستور npm run dev استفاده می‌کنید ولی سرعت npm خیلی کم هست و زمانی که شما در فایل‌هاتون تغییرات ایجاد می‌کنید تقریبا ۲۷ الی ۳۰ ثانیه طول می‌کشه که براتون سازه جدید رو بسازه و با Hard Reload تغییرات رو ببینید. برای همین من توصیه می‌کنم که yarn رو نصب کنید و با دستور yarn dev شروع به develop کنید، باورتون نمیشه سازه رو در زیر ۵۰۰ میلی ثانیه میسازه.امیدوارم که تونسته باشم کمکتون کنم، همیشه موفق و شاد باشید.</description>
                <category>عامر لطفی اوریمی</category>
                <author>عامر لطفی اوریمی</author>
                <pubDate>Fri, 13 Jul 2018 22:23:20 +0430</pubDate>
            </item>
                    <item>
                <title>واقعا Node.js چیه؟!</title>
                <link>https://virgool.io/JavaScript8/nodejs-%DA%86%DB%8C%D8%B3%D8%AA-lst6ffw0nvgv</link>
                <description>همه جا این رو می‌خونیم که Node.js یک محیط اجرایی برای زبان جاوااسکریپت هست، خوب!؟ ایول! ولی این دقیقا یعنی چی؟ مگه قرار نبود جاوااسکریپت توی مرورگر اجرا بشه؟ پس فاز چیه؟ببینید محیط اجراییه Node.js فضا و تمام اون چیز‌هایی که نیازه که کد‌های نوشته شده جاوااسکریپت اجرا بشه رو داره. مثلا به این شکل نگاه کنید:اگر جاوا بلد باشید، خوب متوجه می‌شید که این یه تقلید ساده‌ هستشدر واقع Node.js از اونجایی اومد که برنامه نویس‌های جاوااسکریپت تصمیم گرفتن که فرای این باشن که فقط خلق مسائل خارق العاده توی مرورگر کنن.جاوااسکریپت هم توانایی و پتانسیل این رو داشت که مثل زبان‌های اسکریپتیه دیگه مثلا پایتون باشه و بتونه توی محیط غیر از مرورگر کار کنه.همونطور که توی عکس بالا می‌بینید، نشون دادم که موتور اصلی Node.js در واقع V8 هست، توی مرورگر هم همینه،‌ اونجا هم V8 داره کار می‌کنه. این سوال در ذهن همه تداعی میشه که موتور چیه؟V8 Engine :Dموتور V8 کد‌های جاوااسکریپت رو به کد‌های سطح پایین‌تر تبدیل می‌کنه که ماشین یا همون رایانه اون رو بهتر و سریع‌تر می‌فهمه، بهش میگن زبان ماشین. اینطوری که ماشین برای اجرای اون کد‌ها به تحلیل و تفسیرشون نیاز نداره.چرا Node.js ؟خود سایت Node.js اینطور بیان می‌کنه که:محیط Node.js بر اساس موتور V8 کروم ساخته شده.محیط Node.js از یک مدل رویداد محور و non-blocking I/O استفاده می‌کنه که این Node.js رو سبک و کارآمد می‌کنه.محیط Node.js اکوسیستمی برای پکیج‌هاش داره به نامه npm که بزرگ‌ترین اکوسیستم کتابخانه‌های متن باز در دنیاست.در مورد اولی صحبت کرده بودم، بهتره که در مورد دومی که مهمترینش هم هست یکم بیشتر توضیح بدم.منظور از I/O همون Input/Output هست. می‌تونه هر چیزی باشه، از خوندن/نوشتن توی فایل باشه تا ارسال درخواست‌های HTTP به یک API.این یعنی I/O برای اجرا زمان می‌بره و این یعنی بقیهء کارها الافش می‌شن، یجورایی بقیه رو نگه می‌داره تا کار خودش انجام بشه.خیلی کوتاه توضیح بدم، جاوااسکریپت ساختار non-blocking I/O داره و برای انجام کارهایی که به زمان نیاز داره، الباقی کارها رو الاف خودش نمی‌کنه، به طبع Node.js هم این خاصیت رو داره پس دیگه نیاز شما رو به داشتن multi-threading از بین می‌بره، چون دیگه سرور شما این توانایی رو داره که درخواست‌های زیادی رو همزمان جواب بده.خوب توجه کنید، شما باید خیلی خیلی خوب متوجه بشید که حلقه رویدادهای جاوااسکریپت چطوری کار می‌کنه، اصطلاح اصلیش رو بگم، باید بدونید event loop جاوااسکریپت چطوری کار می‌کنه، به شکل زیر توجه کنید:چرخه رویدادهای جاوااسکریپتمرحله به مرحله می‌خوام توضیح بدم که قشنگ متوجه بشید داستان چیه:تابع main به استک اضافه میشه.تابع console.log(&#x27;Starting app&#x27;) به استک اضافه میشه. اجرا میشه و از استک میاد بیرون.تابع setTimeout(2000) به استک اضافه میشه. setTimeout(2000) از API های Node.js هست. زمانی که صداش می‌زنیم تا اجراش کنیم در واقع اون رو توی لیست Node APIs ثبت می‌کنیم. اون صبر می‌کنه به اندازه زمانی که بهش دادیم که اینجا ۲۰۰۰ میلی ثانیه هست و بعد تابع callback خودش رو به صف اضافه می‌کنه.بعد از اینکه توی Node APIs ثبت شد، خود setTimeout(2000) از استک میاد بیرون.حالا می‌رسیم به setTimeout(0) که اون هم مثل دوست اولیش باهاش برخورد میشه. در لیست Node APIs ثبت می‌کنیم و از استک میاد بیرون.این دو عزیز صبر می‌کنن که زمانشون تمام بشه، بعد هر کدوم تابع‌های callback مربوط به خودشون رو توی صف قرار می‌دن. طبیعی هست که هر کسی زودتر، تابع callback اون هم توی صف جلوتره، اینجا setTimeout دومی چون زمانش صفر بود، callback ش زودتر میره توی صف و ۲۰۰۰ میلی ثانیه یا به عبارتی ۲ ثانیه بعد setTimeout اولی callback ش رو می‌فرسته توی صف و میشه نفر دوم صف.اینجا event loop مراقب هست که اول استک خالی بشه و بعد به ترتیب توابع داخل صف رو اجرا کنه.آخرین تابع یعنی console.log(&#x27;Finishing up&#x27;) هم به استک اضافه میشه، اجرا میشه و از استک خارج میشه و بعد اون هم main خارج میشه.حالا استک خالیه و event loop صف رو تک به تک شروع به اجرا می‌کنه. اولی تابع console.log(&#x27;Second setTimeout&#x27;) و بعدش هم console.log(&#x27;Inside of callback&#x27;)  و تمام.اینطوری میشه که شما خروجی کدی که توی عکس هست رو اینطوری می‌بینید:&quot;Starting app&quot;&quot;Finishing up&quot;&quot;Second setTimeout&quot;&quot;Inside of callback&quot;در مورد مساله سومی هم باید بگم که کتابخانه‌های زیاد و عالی‌ای در npm یا همون Node Package Manager وجود داره که خیلی‌ از گره‌ها رو باز کرده و از این به بعد هم می‌کنه و سرعت و کارآمدی برنامه نویسی شما رو بیشتر می‌کنه.چطوری یه کد ساده توی Node.js بزنیم؟کاری نداره بخدا، برای این کار نیازه که Node.js رو نصب کرده باشی که می‌تونی بری توی سایتش و نسبت به سیستم عاملتون فایلش رو دانلود کنید و نصب و تمام.این از اولش. بعدش هرجا که دلتون خواست، یه فایل بسازید مثلا example.js و توش یه کد خیلی خیلی ساده جاوااسکریپت بنویسید. مثلا بنویسید:console.log(&#039;Hello World!&#039;);خوب حالا محیط کامندیتون رو باز کنید، توی ویندوز مثلا cmd یا power shell و توی لینوکس و مک هم terminal و با اون به مکانی برید که فایل example.js داخلش وجود داره. حالا تایپ کنید:node example.jsو خروجی رو همونجا می‌تونید ببینید. دیدید؟ خیلی ساده، همین الآن شما یه Node.js کار شدید. البته که راه زیادی در پیش دارید. برای نوشتن یه برنامه کامل با زلم زیمبوهای خاص خودش خیلی چیز‌ها نیازه. آشنایی با API ها و فریمورک‌ها و هزار‌ان چیز دیگه که من پیشنهاد می‌کنم به منابع انگلیسی زبان مراجعه کنید. برای شروع پیشنهاد من کورس زیر هست:Lynda Node.js Essential Trainingامیدوارم این مقاله به کارتون بیاد. شاد و موفق باشید.</description>
                <category>عامر لطفی اوریمی</category>
                <author>عامر لطفی اوریمی</author>
                <pubDate>Tue, 19 Jun 2018 01:16:18 +0430</pubDate>
            </item>
                    <item>
                <title>الگوریتم‌های معروف با جاوااسکریپت</title>
                <link>https://virgool.io/JavaScript8/%D8%A7%D9%84%DA%AF%D9%88%D8%B1%DB%8C%D8%AA%D9%85%D9%87%D8%A7%DB%8C-%D9%85%D8%B9%D8%B1%D9%88%D9%81-%D8%A8%D8%A7-%D8%AC%D8%A7%D9%88%D8%A7%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA-whjnr2zdaeno</link>
                <description>شاید خیلی از شما دوستان مثل خود من باشید و از فضای دانشگاه و موضوعات مطرح شده در اونجا خیلی احساس رضایت نکنید، ولی درواقع اینطور هست که یه سری مطالب که توی دانشگاه بیان شد و مکررا هم برای همه ورودی‌های جدید مطرح میشه مطالب مهمی هستند که بعد‌ها توی ذات کارهای شما دیده میشه.برای نمونه الگوریتم‌های مشهور برنامه نویسی و بهینه‌سازی الگوریتم‌ها با دونستن معیار‌ها و موارد خاصشون هست. مثل الگوریتم مرتب‌سازی حبابی،‌ الگوریتم هیپ، انواع درخت‌ها، یافتن پیچیدگی الگوریتم‌های نوشته شده و...حالا فکرش رو بکنید شما به این موارد پایه‌ای تسلط داشته باشید و با زبان ترندی مثل #جاوااسکریپت هم اون رو پیاده سازی کنید، وای، عالیه، من که خیلی ذوق می‌کنم حتی بهش فکر می‌کنم.امروز یه Repository توی گیت‌هاب براتون دارم که به راحتی می‌تونید با پیاده‌سازی این روش‌ها و الگوریتم‌ها و ابزارها به زبان جاوااسکریپت آشنا بشید. همونطور هم که می‌دونید جاوااسکریپت سمت سرور هم می‌تونه کار کنه پس محدودیتی نداره و این تصور که این زبان فقط قراره در بستر مرورگر اینترنت شما اجرا بشه خیلی خیلی قدیمی هست.مواردی مثل موارد زیر در این ریپو پیاده سازی شده و شما می‌تونید با لذت به تماشا و یادگیری این پیاده‌سازی با جاوااسکریپت بپردازید:لیست‌ ارتباطی (Linked List)صف‌پشته‌درخت‌هاو...یا مثلا در مورد بهینه سازی الگوریتم‌ها &#x60;Optimization&#x60; هم توضیح داده و مهم‌تر اینکه با زبان جاوااسکریپت چطوری میشه کد بهتر با راندمان بیشتری نوشت:نمودار پیچیدگی الگوریتم‌هاامیدوارم که این ریپو که جزو ترندهای ماه گیت‌هاب هم بوده به شما توی کد نویسی با زبان جاوااسکریپت کمک کنه.</description>
                <category>عامر لطفی اوریمی</category>
                <author>عامر لطفی اوریمی</author>
                <pubDate>Sun, 10 Jun 2018 06:27:49 +0430</pubDate>
            </item>
            </channel>
</rss>