مطالب
آشنایی با CLR: قسمت هجدهم
در قسمت قبلی با نحوه‌ی نسخه بندی اسمبلی‌ها آشنا شدیم؛ ولی به غیر از نسخه بندی، فرهنگ (culture) هم قسمتی از عوامل شناسایی یک اسمبلی است. به عنوان نمونه من میتوانم یک اسمبلی داشته باشم که برای زبان آلمانی، انگلیسی آمریکایی، انگلیسی بریتانیایی و ... آماده شده است.
شناسایی فرهنگ یک اسمبلی از طریق یک رشته است که شامل یک تگ اصلی و ثانویه طبق استاندارد RFC1766 می‌باشد. جدول زیر تعدادی از این تگ‌ها را نمایش می‌دهد.
 تگ اولیه  تگ ثانویه  فرهنگ مربوطه 
 De آلمانی 
 De  AT  آلمانی اتریشی
 De  CH  آلمانی سوئیسی
 En  -  انگلیسی
 En  GB  انگلیسی بریتانیا
 En  US  انگلیسی آمریکایی
در حالت عادی که یک اسمبلی را که تنها شامل کد می‌شود، دارید برای آن culture تعریف نمی‌شود. چون مشخصه‌ی خاصی ندارد که به آن فرهنگ خاصی هم تعلق بگیرد. به این اسمبلی‌ها Culture Neutral یا خنثی می‌گویند.
حال اگر شما در حال طراحی برنامه‌ای هستید که منابع Resources شامل مشخصه‌های فرهنگی و منطقه‌ای می‌شوند، مایکروسافت به شدت توصیه می‌کند که بحث کد را از منابع جدا کرده و اسمبلی هایشان جدا شوند. یک اسمبلی برای کدها و منابع مشترک استفاده شود که هیچ خصوصیت فرهنگی و منطقه‌ای خاصی ندارد. حال یک یا چند اسمبلی جداگانه برای منابع ساخته که هر کدام از آن‌ها به فرهنگ و منطقه‌ی خاصی اشاره می‌کنند. به این نوع اسمبلی‌ها Satellite Assembly یا اسمبلی ماهواره‌ای گویند.
عموما از ابزار AL برای ساخت اسمبلی‌های ماهواره ای استفاده می‌شود. دلیل آن هم اینست که این اسمبلی‌ها چون عموما کدی را شامل نمی‌شوند، ساخت آن‌ها از طریق کامپایلر ممکن نیست. برای معرفی یک اسمبلی ماهواره‌ای باید از سوئیچ c یا culture استفاده کرد و به عنوان ورودی، این سوئیچ تگ‌ها را به آن نسبت داد.
/c[ulture]:En-US
بعد از اینکه اسمبلی ساخته شد در مسیر برنامه، در یک زیردایرکتوری که با همان شناسه‌ی تگ‌ها نام گرفته است، ذخیره می‌کنیم. به عنوان مثال اگر مسیر زیر، مسیر برنامه ما باشد:
C:\MyApp
اسمبلی ماهواره‌ای با مشخصات بالا باید در مسیر زیر قرار بگیرد:
C:\MyApp\en-US
در صورتی که قصد دارید در زمان اجرا به منابع یک اسمبلی ماهواره‌ای دسترسی پیدا کنید می‌توانید از کلاس زیر استفاده کنید:
System.Resources.ResourceManager
به هر حال اگر کدهای شما در فرهنگ و منطقه تاثیر دارند و دوست دارید اسمبلی کدها هم به عنوان یک اسمبلی ماهواره‌ای شناخته شوند از خصوصیت زیر برای معرفی اسمبلی خود استفاده کنید:
 System.Reflection.AssemblyCultureAttribute

===============
[assembly:AssemblyCulture("de­-CH")]
در AL هم از سوئیچ Culture/ استفاده می‌شود. به طور عادی شما نباید یک اسمبلی بسازید که به اسمبلی ماهواره ای اشاره می‌کند و جداول متادیتا اسمبلی‌ها باید به اسمبلی‌های خنثی اشاره کنند. اگر شما قصد دسترسی به اعضاء و خصوصیات یک اسمبلی ماهواره‌ای را دارید باید از طریق Reflection که در آینده در مورد آن صحبت خواهد شد اینکار را انجام دهید.( در  کتاب جفری ریچر   به فصل بیست و سوم Assembly Loading and Reflection مراجعه شود)
نظرات نظرسنجی‌ها
اگر بخواهید کنار دات نت بر روی یک پلتفرم یا زبان دیگری نیز کار کنید کدام را انتخاب می کنید؟
بله در موردش کمی مطالعه داشتم، 2-3 سالی هست توی خیلی از اپهای آموزش برنامه نویسی اندروید هم یادگیریشو گذاشتن، حتی برخی به عنوان اولین زبان اندروید نویسی یادش می‌دن. چون خودم دات نت رو یک محیط یکپارچه می‌بینم و تفاوت خاصی بین c# یا vb.net نمیبینم، پلتفرم جاوا رو هم یک محیط واحد میبینم! به هرحال همه زبانهای محیط جاوا در نهایت به کد ماشین مجازی جاوا ترجمه میشن، و قدرت یکسانی دارن. اگر میفرمایید یک گزینه دیگر به عنوان کاتلین هم اضافه میکنم، یا عنوان جاوا رو به "یکی از زبانهای پلتفرم  جاوا، مثل جاوا، کاتلین، اسکالا و ..." تغییر میدم.
مطالب
شروع کار با webpack - قسمت سوم
در مطلب قبلی با فایل‌های پیکربندی وبپک، وب سرور وبپک، لودر‌ها و ... آشنا شدیم .


استفاده از preLoader‌ها در وبپک 
پیش‌تر با Loader‌ها آشنا شدیم و دلیل استفاده‌ی از آنها نیز ذکر و Loader تایپ اسکریپت را نیز نصب کرده و با استفاده از آن فایل‌های پروژه را ترنسپایل کردیم. اما ممکن است که همه‌ی کارها در استفاده از یک Loader خلاصه نشوند. ممکن است بخواهید از یک ابزار Linting مانند jsHint  قبل از اجرای Loader ها بهره ببرید و این دقیقا کاری است که به preLoader‌ها سپرده می‌شود. به عنوان مثال پیش لودر jsHint را نصب خواهیم کرد. اضافه کردن preLoader‌ها در فایل پیکربندی وبپک تفاوتی با Loader‌ها نخواهد داشت و دارای همان قسمت‌هایی است که برای Loader‌ها تعریف کردیم.
پیش از هر کاری ابتدا jsHint را نصب کرده و سپس loader آن را نیز نصب می‌کنیم. دستورات مورد نیاز، در ادامه آورده شده اند:
npm install -D jsHint jsHint-loader
سپس در ادامه به فایل پیکربندی وبپک مراجعه کرده و قسمت preLoader را به آن اضافه می‌کنیم:
module.exports = {
    entry:['./shared.js','./main.ts']
    ,output:{
        filename:'bundle.js'
    }
    ,watch :true
    ,module:{
        preLoaders:[
            {
                test:/\.js$/
                ,exclude:/node_modules/
                ,loader:'jshint-loader'
            }
        ],
        loaders:[
            {
                test:/\.ts$/
                ,exclude:/node_modules/
                ,loader:'ts-loader'
            }
        ]
    }
    
}

حال وب سرور وبپک را اجرا می‌کنیم. در خط فرمان نتیجه‌ی اجرا شدن jsHint در تصویر قابل مشاهده است که از دو فایل پروژه ایراد گرفته است:


همچنین برای تکمیل قابل ذکر است که وبپک دارای postLoaders نیز می‌باشد که پس از Loader‌های اصلی اجرا می‌شوند.
لیست کاملی از Loader‌ها را می‌توانید در اینجا مشاهده کنید .تمامی لودرهای وبپک

Minify کردن باندل‌ها با استفاده از وبپک

در صورتی که باندل ساخته شده تا به اینجای کار را باز کرده باشید، مشاهده کرده‌اید که باندل ساخته شده Minify شده نیست. ساده‌ترین روش جهت Minify کردن باندل ساخته شده در هنگام فراخوانی وبپک با استفاده از یک پرچم در خط فرمان می‌باشد. دستور مورد نیاز در ادامه آورده شده است.
// در حالتی که به صورت محلی وبپک نصب شده است
npm run webpack -- -p
// درحالتی که وبپک به صورت سراسری اجرا می‌شود
webpack -p
حال در صورتی که به باندل ساخته شده مراجعه کنید، باندل در حالت Minify شده قرار دارد.

اضافه کردن فایل پیکربندی مخصوص بیلد‌های اصلی پروژه

قطعا شما نیز در حین توسعه‌ی پروژه از دستورات لاگ یا اندازه گیری زمان اجرای یک قطعه کد و ... استفاده می‌کنید و حضور این کد‌ها در باندل نهایی دلیلی ندارد. یک راهکار این است که کدهایی را که فقط جهت توسعه‌ی پروژه و دیباگ بودند و سودی در نتیجه‌ی نهایی ندارند، به صورت دستی پاک کنیم و در صورتی که حجم این طور دستورات بالا باشند، قطعا کار جالبی نخواهد بود و همچنین حذف کلی این دستورات نیز در ادامه برای برگشت به پروژه ممکن است مشکل زا باشد.
راهکاری که با وبپک می‌توان پیش گرفت این است که از یک Loader جهت بیلد‌های اصلی استفاده کرده و مثلن تمامی کامنت‌ها و دستورات لاگ کننده و ... را از بیلد نهایی حذف کنیم. جهت اینکار یک فایل پیکربندی مخصوص را به بیلدهای اصلی به پروژه اضافه می‌کنیم و اسم فایل را webpack.prod.config.js می‌گذاریم.
قدم بعدی نصب یک loader می‌باشد که وظیفه‌ی حذف مواردی را دارد که برای آن مشخص خواهیم کرد. این لودر strip-loader نام دارد و با دستور زیر آن را در پروژه اضافه می‌کنیم.
npm install -D strip-loader
سپس وارد فایل پیکربندی که فقط جهت تولید باندل‌های اصلی پروژه ایجاد کرده‌ایم (webpack.prod.config.js) می‌شویم و کد‌های زیر را وارد می‌کنیم.
// webpack.prod.config.js
 //تنظیمات قبلی را می‌خوانیم
var devConfig = require("./webpack.config.js");
// لودری که وظیفه‌ی حذف کردن دارد را وارد می‌کنیم
var stripLoader = require("strip-loader");

// مانند قبل یک آبجکت با موارد مورد نظر برای لودر می‌سازیم
var stripLoaderConfig = {
    test:[/\.js$/,/\.ts$/],
    exclude :/node_modules/
    ,loader:stripLoader.loader("console.log")
}

// اضافه کردن به لیست لودرهای قبلی
devConfig.module.loaders.push(stripLoaderConfig);

// و در آخر اکسپورت کردن تنظیمات جدید وقبلی
module.exports = devConfig;
در توضیح کد‌های بالا در خط اول ابتدا فایل پیکربندی را که در توسعه‌ی عادی پروژه استفاده می‌شد، می‌خوانیم و در آبجکتی با نام devConfig ذخیره می‌کنیم. مزیت اینکار این می‌باشد که از تعریف تنظیمات تکراری و مورد نیاز جلوگیری می‌کند (نکته : اگر بخاطر داشته باشید در مطلب قبلی ذکر شد که فایل‌های پیکربندی در فرمت commonjs می‌باشند و در نتیجه امکان وارد کردن آنها با استفاده از تابع require امکان پذیر است).
خط بعدی نیز loader ی که وظیفه‌ی حذف موارد مورد نظر ما را دارد وارد می‌کنیم و در ادامه یک آبجکت را با تعاریفی که قبلن از لودر‌ها داشتیم می‌سازیم. تنها نکته در قسمت تعریف اسم لودر می‌باشد.
loader:stripLoader.loader("console.log")
در کد بالا مواردی را که مورد نیاز است از سورس اصلی در سورس نهایی حذف شود، به لودر معرفی می‌کنیم. در اینجا تمامی دستوراتی که شامل console.log می‌شوند از بیلد نهایی باندل حذف خواهند شد.
تنها مرحله‌ی باقی مانده، فراخوانی وبپک با استفاده از فایل پیکربندی جدید می‌باشد. برای اینکار با استفاده از پرچم config محل فایل جدید پیکربندی را به وبپک معرفی می‌کنیم تا از فایل پیکربندی پیش فرض قبلی استفاده نکند.
// در حالتی که وبپک به صورت محلی نصب شده است
npm run webpack -- --config webpack.prod.config.js -p
// در حالتی که وبپک به صورت سراسری نصب شده باشد
webpack --config webpack.prod.config.js -p
پس از اجرای این دستور و باز کردن صفحه‌ی index.html خواهید دید که پیغامی در کنسول مرورگر ظاهر نخواهد شد و دستورات console.log همگی حذف شده‌اند.
توجه داشته باشید که اگر برای ساخت باندل از وبپک استفاده کرده‌اید، برای میزبانی فایل‌های پروژه از وب سرور وبپک استفاده نکنید و از وب سروری دیگر (مانند http-server یا IIS و ...) استفاده کنید؛ چرا که باندل توسط وب سرور وبپک دوباره ساخته می‌شود و تغییرات از بین می‌روند. در صورتی که می‌خواهید از وب سرور وبپک برای میزبانی بیلد نهایی پروژه نیز استفاده کنید، فایل پیکربندی بیلد نهایی را نیز به وب سرور وبپک با استفاده از دستور زیر معرفی کنید:
// زمانی که وبپک به صورت محلی در پروژه نصب شده است
npm run webpackserver -- --config webpack.prod.config.js  -p
//در حالتی که وبپک به صورت گلوبال ( سراسری ) نصب می‌باشد
webpack-dev-server --config webpack.prod.config.js  -p

مدیریت فایل و فولدرها با استفاده وبپک
تا به اینجای کار اگر به ساختار چینش فایل‌ها در پروژه دقت کنید خواهید دید که همگی فایل‌ها در مسیر اصلی پروژه قرار دارند و این روش مناسبی برای مدیریت فایل‌ها و فولدرها در پروژه‌های واقعی و بزرگ نیست. در ادامه قصد داریم این مسئله را حل کرده و ساختار مشخصی را برای محل قرارگیری فایل‌های پروژه با کمک وبپک ایجاد کنیم.
در اولین قدم فولدری را برای اسکریپت‌ها با نام js ایجاد کرده و اسکریپت‌ها را به این فولدر انتقال می‌دهیم.
در قدم دوم برای فایل‌های استاتیک پروژه مانند صفحات html و ... فولدر دیگری را با نام assets ایجاد می‌کنیم و این گونه فایل‌ها را در آن قرار خواهیم داد.
تا اینجای کار در صورتی که وبپک را اجرا کنید، مسیرهای جدید را پیدا نخواهد کرد و دچار خطا خواهد شد. پس به فایل پیکربندی ( webpack.config.js ) مراجعه کرده و وبپک را از ساختار جدید پروژه خبردار می‌کنیم.
// new webpack.config.js file
//ماژول توکار نود جی اس
var path = require("path");

module.exports = {
    // مشخص کردن زمینه برای فایل‌های ورودی
    context:path.resolve("js"),
    entry:['./shared.js','./main.ts']
    ,output:{
       // مشخص کردن محل قرارگیری باندل ساخته شده
        path:path.resolve("build/js"),
      // درخواست از سمت چه مسیری برای باندل خواهد آمد ؟
        publicPath:"assets/js",
        filename:'bundle.js'
    }
    ,
    devServer:{
        //راهنمایی برای وب سرور جهت اینکه فایل‌ها را از چه محلی سرو کند
        contentBase:"assets"
    }

    ,watch :true
    ,module:{
        
        loaders:[
            {
                test:/\.ts$/
                ,exclude:/node_modules/
                ,loader:'ts-loader'
            }
        ]
    }
    
}
در خط اول فایل پیکربندی جدید، ماژول توکار path از نود جی اس را وارد می‌کنیم و سپس کلید جدیدی را به تنظیمات وبپک با نام context اضافه می‌کنیم که زمینه‌ی فایل‌های ورودی را مشخص خواهد کرد. قبلا ذکر شد که فولدری با نام js را ساخته و اسکریپت‌ها را در آن قرار می‌دهیم. پس با کمک ماژول path این مسیر را به وبپک معرفی می‌کنیم.
context:path.resolve("js")
تغییر بعدی را در تنظیمات برای ساخت باندل داریم که مشخص کردن مسیر قرارگیری جدید باندل می‌باشد که با کلید جدیدی با نام path، مسیر قرارگیری باندل پس از ساخته شدن را به وبپک اطلاع می‌دهیم و در ادامه کلید دیگری با نام publicPath اضافه شده که راهنمایی برای وب سرور وبپک می‌باشد تا با استفاده از آن درخواست‌هایی که به مسیر مشخص شده می‌آیند، از مسیری که در کلید path نامیده شده سرو شوند.
// تغییرات در شی output
// این کلید جدید مسیر قرار گیری جدید باندل را به وبپک اطلاع می‌دهد
path:path.resolve("build/js"),
//  راهنما برای وب سرور وبپک جهت میزبانی مسیر زیر از کلید بالا
publicPath:"assets/js",
آخرین تغییر در فایل پیکربندی، مربوط به اضافه شدن آبجکت جدید devServer می‌باشد که در آن کلیدی اضافه شده که مسیر اصلی فایل‌های میزبانی شده را اعلام می‌کند. به طور مثال فایل html اصلی پروژه را بالاتر اشاره کردیم که در این مسیر قرار می‌دهیم.
در نهایت وارد فایل index.html می‌شویم و مسیر جدید باندل را به آن معرفی میکنیم.
//index.html

<html>
    <head>
        first part of webpack tut!
    </head>
    <body>
        <h1>webpack is awesome !</h1>
        <script src="assets/js/bundle.js"></script>
    </body>
</html>
قابل مشاهده است که مسیر باندل ذکر شده در اینجا وجود خارجی ندارد و وبپک آن را با کمک تنظیماتش، به صورت پویا پیدا خواهد کرد. در تصویر زیر سعی بر روشن‌تر شدن این مسئله شده است.


حال با اجرا کردن وب سرور وبپک می‌توان مشاهده کرد که مسیرهای جدید، بدون مشکل توسط وبپک پیدا شده و فایل‌ها سرو می‌شوند. قابل توجه است که این نوع چینش پروژه قابل تغییر و شخصی سازی برای پروژه‌های گوناگون می‌باشد.


ساخت فایل‌های سورس مپ  (source map)


ساده‌ترین راه جهت ساخت فایل‌های سورس مپ با استفاده از یک پرچم در هنگام فراخوانی وبپک به صورت زیر می‌باشد.

// فعال کردن ساخت سورس مپ‌ها 
npm run webpack -- -d 
// یا  در هنگام نصب گلوبال
webpack -d
// جهت استفاده به همراه وب سرور
npm run webpackserver -- -d
// یا به صورت نصب گلوبال
webpack-dev-server -d
راه دوم با استفاده از انجام تغییرات در فایل پیکربندی وبپک می‌باشد؛ به این صورت که کلیدی را به این فایل اضافه می‌کنیم.
// webpack.config.js
// کلید جدید اضافه شده در فایل پیکربندی
devtool:"#source-map"
حال در هنگام فراخوانی وبپک فایل سورس مپ نیز ساخته خواهد شد و احتیاجی به استفاده از پرچم خط فرمان در هنگام فراخوانی نیست.
با اجرای وب سرور وبپک خواهید دید که سورس مپ‌ها در منوی توسعه دهنده‌ی مرورگر قابل دستیابی می‌باشند.

ساخت چندین باندل گوناگون

قصد داریم به پروژه، دو صفحه‌ی دیگر را نیز با نام‌های aboutme و contact اضافه کنیم. هر یک از این صفحات اسکریپت مخصوص به خود را خواهد داشت و باندل نهایی نیز شامل تمامی آنها خواهد شد. در صورتی که این خروجی مطلوب ما نباشد و به طور مثال بخواهیم مکانیزمی شبیه به lazy loading اسکریپت‌ها را داشته باشیم و فقط زمانی اسکریپت‌ها بارگذاری شوند که به آنها احتیاج باشد، برای انجام این کار با وبپک به صورت زیر عمل خواهیم کرد.
دو صفحه‌ی html جدید را با عناوین ذکر شده‌ی بالا به پوشه‌ی assets اضافه می‌کنیم و برای هریک نیز اسکریپتی با همان نام خواهیم ساخت و در پوشه‌ی js قرار می‌دهیم.
محتوای صفحات بدین شکل می‌باشد.
// index.html file
<html>
<head>

    <title>
        third part of webpack tut!
    </title>
</head>

<body>
    <nav>
        <a href="aboutme.html">about me</a>
        <a href="contact.html">contact</a>
    </nav>
    <h1>webpack is awesome !</h1>
    <script src="assets/js/shared.js"></script>
    <script src="assets/js/index.js"></script>
</body>

</html>

// aboutme.html file
<html>

<head>

    <title>
        about me page !
    </title>
</head>

<body>
    <nav>
        <a href="index.html">index</a>
        <a href="contact.html">contact</a>
    </nav>
    <h1>webpack is awesome !</h1>
    <script src="assets/js/shared.js"></script>
    <script src="assets/js/aboutme.js"></script>
</body>

</html>

// contact.html file

<html>

<head>

    <title>
        contact me page !
    </title>
</head>

<body>
    <nav>
        <a href="index.html">index</a>
        <a href="aboutme.html">about me</a>
    </nav>
    <h1>webpack is awesome !</h1>
    <script src="assets/js/shared.js"></script>
    <script src="assets/js/contact.js"></script>
</body>

</html>
در هر یک از صفحات یک اسکریپت مخصوص آن صفحه و همچنین یک اسکریپت با نام shared.js که قبلا فرض کردیم نقش ماژولی را دارد که در سرتاسر پروژه از آن استفاده می‌شود، اضافه شده است. حال این تغییرات را در فایل پیکربندی وبپک به آن معرفی می‌کنیم.
var path = require("path");
var webpack = require("webpack");
// وارد کردن پلاگینی از وب پک برای ساخت تکه‌های مختلف اسکریپت‌ها 
// معرفی اسکریپت shared.js
var commonChunkPlugin = new webpack.optimize.CommonsChunkPlugin("shared.js");
module.exports = {
    context:path.resolve("js"),
    //entry:['./shared.js','./main.ts']
   // معرفی اسکریپت‌های جدید به وبپک
    entry:{
        index:"./main.js",
        aboutme:"./aboutme.js",
        contact:"./contact.js"
    }
    ,output:{
        path:path.resolve("build/js"),
        publicPath:"assets/js",
     //   filename:'bundle.js'
     // به جای یک باندل کلی از وبپک میخاهیم برای هر ورودی باندلی جدید بسازد
        filename:"[name].js"
    }
    // رجیستر کردن پلاگین 
    ,plugins:[commonChunkPlugin]
    ,
    devServer:{
        contentBase:"assets"
    }
    //,devtool:"#source-map"
    ,watch :true
    ,module:{...
    }
    
}
جهت انجام این کار از یک پلاگین وبپک با نام CommonsChunkPlugin کمک گرفته‌ایم که به ما کمک می‌کند اسکریپت shared.js را به عنوان یک وابستگی در تمامی صفحاتمان داشته باشیم. نحوه‌ی کار این پلاگین نیز از نامش مشخص است و نقاط Common را می‌توان با آن مشخص کرد. تغییر بعدی نیز در کلید entry می‌باشد که اسکریپت‌های جدید را با استفاده از اسمشان به وبپک معرفی کرده‌ایم و سپس در کلید output نیز به وبپک خبر داده‌ایم که برای هر ورودی، باندل جداگانه‌ی خود را بسازد. تکه کد  filename:[name].js به وبپک می‌گوید که باندل‌های جداگانه، با نام خود اسکریپت ساخته شوند و در نهایت کلید جدید plugins به وبپک پلاگین CommonsChunkPlugin را اضافه می‌کند.
حال با اجرای وبپک می‌توان دید که سه باندل ساخته شده که همگی به اسکریپت shared.js وابستگی دارند و اگر این اسکریپت را از صفحات HTML حذف کنید، با خطا رو به رو خواهید شد. این پلاگین قدرت ساخت باندل‌هایی با خاصیت مشخص کردن وابستگی‌ها و همچنین تو در تویی‌ها خاص را نیز دارد. برای مطالعه‌ی بیشتر می‌توانید به اینجا مراجعه کنید: پلاگین commonsChunk

در قسمت بعدی با استفاده از وبپک فایل‌های css، فونت‌ها و تصاویر را نیز باندل خواهیم کرد.

فایل‌های مطلب:
سورس تا قبل از قسمت ایجاد تغییرات در ساختار فایل‌های پروژه :dntwebpack-part3-beforeFileAndFolderManagment.zip
سورس برای بعد از ایجاد تغییرات در ساختار فایل‌های پروژه : dntwebpack-part3AfterFileOrganization.zip

مطالب
طرحبندی صفحات وب با بوت استرپ 4 - قسمت سوم
قابلیت‌های یک Flex Container در بوت استرپ 4

یک Flex Container متداول به این صورت کار می‌کند:

این کلاس‌ها که موارد داخل پرانتز آن‌ها اختیاری است، المان را تبدیل به یک المان Flexbox می‌کنند. حالت نمایشی پیش‌فرض آن‌ها block است؛ اما اگر نیاز بود می‌توان آن‌ها را تبدیل به in-line نیز کرد. بنابراین ساده‌ترین Flex Container را می‌توان با افزودن کلاس d-flex ایجاد کرد.

بر روی یک Flex Container می‌توان کلاس‌های تعیین جهت را نیز تعریف کرد:

به این ترتیب می‌توان آیتم‌ها را به صورت ردیف‌ها و یا ستون‌هایی، نمایش داد. مقدار row در اینجا به صورت پیش‌فرض اعمال می‌شود. بنابراین ذکر کلاس خالی flex به معنای قرار دادن المان‌ها در طی چندین ردیف در صفحه است. در اینجا استفاده‌ی از reverse، نمایش المان‌ها را از راست به چپ میسر می‌کند.

در یک Flex Container امکان تعیین ترتیب عناصر نیز وجود دارد:

این مورد را در مطلب «طرحبندی صفحات وب با بوت استرپ 4 - قسمت دوم » بررسی کردیم. کلاس order را علاوه بر ستون‌ها، بر روی هر دربرگیرنده‌ای که دارای کلاس d-flex است نیز می‌توان اعمال کرد.

همچنین امکان تنظیم فواصل بین آیتم‌ها نیز در یک Flex Container پیش بینی شده‌است:

برای مثال استفاده‌ی از مقدار تراز center، روش بسیار مناسبی برای قرار دادن عناصر، در میانه‌ی افقی صفحه است. این مورد را نیز در قسمت قبل بررسی کردیم.

می‌توان نحوه‌ی Wrap المان‌ها را بر اساس فضای خالی در یک Flex Container به صورت زیر تنظیم کرد:

که در اینجا دو مقدار wrap و nowrap قابل تنظیم است. در حالت wrap، اگر آیتم‌ها با اندازه‌ی خودشان در ردیف جاری جا نشدند، به سطر یا سطرهای بعدی منتقل خواهند شد. حالت پیش‌فرض nowrap است.

برای تغییر تراز عمودی المان‌ها در یک Flex Container از کلاس align-content استفاده می‌شود:

این مورد را نیز در قسمت قبل بررسی کردیم و همانند کار با ستون‌ها می‌باشد.


یک مثال: بررسی ویژگی‌های یک Flex Container

<head>
    <style>
        .item {
          background: #f0ad4e;
          text-align: center;
          width: 150px;
          height: 30px;
          border: 1px solid white;
        }
    </style>
</head>

<body>
    <div class="container bg-danger">
        <div class="bg-info" style="height:100vh">
            <div class="item">Exotic</div>
            <div class="item">Grooming</div>
            <div class="item">Health</div>
            <div class="item">Nutrition</div>
            <div class="item">Pests</div>
            <div class="item">Vaccinations</div>
        </div>
    </div>
</body>
در اینجا ارتفاع container به 100vh تنظیم شده‌است تا کل view-port را پوشش دهد و رنگ آن نیز به bg-info تنظیم شده‌است تا بتوان تغییر محل تراز عمودی را بهتر مشاهده کرد.
در ابتدا کلاس d-flex را به div داخل container اضافه می‌کنیم:
<div class="bg-info d-flex" style="height:100vh">
بلافاصله مشاهده خواهیم کرد که عناصر تعریف شده در طی یک ردیف از چپ به راست نمایش داده می‌شوند:


و اگر جهت این Flex Container را به صورت صریح مشخص کنیم:
<div class="bg-info d-flex flex-column" style="height:100vh">
آیتم‌های درون آن به صورت یک ستون نمایش داده می‌شوند:


و یا اگر بخواهیم آیتم‌ها را از راست به چپ به صورت یک ردیف نمایش دهیم می‌توان از flex-row-reverse استفاده کرد:

<div class="bg-info d-flex flex-row-reverse" style="height:100vh">


و اگر بجای row در این حالت column را مقدار دهی کنیم:
<div class="bg-info d-flex flex-sm-column-reverse" style="height:100vh">


آیتم‌ها از پایین صفحه شروع خواهند شد. البته در این مثال break-point از نوع sm نیز ذکر شده‌است تا پس از گذر از این اندازه‌ی صفحه، چنین اتفاقی رخ دهد.

و یا اگر بخواهیم آیتم‌ها از راست به چپ در طی یک ردیف، پس از اندازه‌ی صفحه‌ی sm و همچنین در میانه‌ی صفحه ظاهر شوند، می‌توان از کلاس justify-content استفاده کرد:
<div class="bg-info d-flex flex-sm-row-reverse justify-content-center"
     style="height:100vh">
با این خروجی:


و اگر wrap را فعال کنیم:
<div class="bg-info d-flex flex-sm-row-reverse justify-content-center flex-wrap"
     style="height:100vh">


اگر آیتم‌ها با اندازه‌ی اصلی خودشان، در ردیف جاری جا نشدند، به سطرهای بعدی منتقل خواهند شد.
اگر nowrap را فعال کنیم:
<div class="bg-info d-flex flex-sm-row-reverse justify-content-center flex-nowrap"
     style="height:100vh">
سعی می‌کند در ردیف جاری، آیتم‌ها را تا حد ممکن کوچک کرده و نمایش دهد:


و با فعالسازی align-content-start، تمام آیتم‌ها را به سمت بالای صفحه هدایت می‌کند و align-content-end، آن‌ها را از پایین صفحه شروع خواهد کرد:
<div class="bg-info d-flex flex-sm-row-reverse justify-content-center flex-wrap align-content-start"
     style="height:100vh">



کنترل آیتم‌های قرار گرفته‌ی درون یک Flex Container در بوت استرپ 4

علاوه بر امکان کنترل ویژگی‌های یک Flex Container، اجزای قرار گرفته‌ی درون آن‌ها را نیز می‌توان کنترل کرد و اینکار توسط کلاس align-self میسر است:


این مورد نیز همانند توضیحات کلاس align-self اعمالی به ستون‌ها است که در قسمت قبل بررسی کردیم.

به علاوه در اینجا امکان تعریف floating elements نیز مسیر است که شبیه به دسترسی به امکانات CSS در بوت استرپ است با امکان تنظیم break-points:

فرض کنید به تمام آیتم‌های داخل Flex Container کلاس float-left را اضافه کرده‌ایم. در این حالت Container قابلیت ردیابی اندازه‌ی این آیتم‌ها را از دست می‌دهد. به همین جهت با اعمال کلاس clearfix بوت استرپ به container، مجددا امکان ردیابی این آیتم‌ها را پیدا می‌کند.


کلاس‌های تعریف margin و padding در بوت استرپ 4

در بوت استرپ 4 کلاس‌های ویژه‌ای برای ایجاد margin و padding بین عناصر در نظر گرفته شده‌اند که خلاصه‌ی آن‌ها فرمول زیر است:

ابتدا با تعریف یک خاصیت شروع می‌شود؛ مانند m یا p، برای کنترل margin و padding. سپس لبه‌ای که باید به آن اعمال شود بدون فاصله و یا - ذکر می‌شود؛ مانند mt به معنای margin-top. در این فرمول x به معنای اعمال همزمان به چپ و راست است و y به معنای اعمال همزمان به بالا و پایین و اگر می‌خواهید آیتم‌های کناری آیتم جاری را به دو طرف لبه‌ها هدایت کنید از mx-auto استفاده کنید.
در اینجا امکان اعمال یک break-point اختیاری نیز وجود دارد. در آخر اندازه ذکر می‌شود که بین 0 تا 5 متغیر است.

یک مثال: اعمال کلاس‌های padding و margin بوت استرپ 4

<head>
    <style>
        .item {
          background: #f0ad4e;
          text-align: center;
          border: 1px solid white;
        }
    </style>
</head>

<body>
    <div class="container bg-danger">
        <div class="bg-info d-flex">
            <div class="item">Exotic</div>
            <div class="item">Grooming</div>
            <div class="item bg-danger ml-3 my-sm-3 pb-3 pt-5">Health</div>
            <div class="item">Nutrition</div>
            <div class="item">Pests</div>
            <div class="item">Vaccinations</div>
        </div>
    </div>
</body>
در اینجا به آیتم Health یک margin-left با اندازه‌ی 3، یک margin بالا و پایین فعال شونده‌ی پس از sm با اندازه‌ی 3، یک padding پایین با اندازه‌ی 3 و یک padding بالا با اندازه‌ی 5 اضافه شده‌است؛ با این خروجی:



نمایش و مخفی سازی عناصر در بوت استرپ 4

کلاس invisible سبب می‌شود تا المانی در صفحه نمایش داده نشود، اما این المان همچنان فضای اختصاصی خود را خواهد داشت. کلاس visible به معنای نمایان بودن المانی تنها برای screen readers است (دستگاه‌های کمکی معلول‌ها).
اما روش اصلی نمایش و یا مخفی سازی عناصر در بوت استرپ 4، استفاده از خاصیت display است:

برای مثال با انتساب کلاس d-sm-none به المانی، می‌توان سبب مخفی شدن آن پس از گذر از sm شد.


امکان تعیین اندازه‌ی عناصر در بوت استرپ 4

بوت استرپ 4 تعدادی کلاس ویژه را برای تعیین اندازه‌ی عناصر نیز افزوده‌است:


در اینجا w=width، h=height، mw=max-height و mh=max-height است با مقادیر 25، 50، 75 و 100 و مقدار پیش‌فرض آن 100 است (یعنی پوشاندن کل container).


کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید: Bootstrap4_06.zip
نظرات مطالب
AngularJS #2
در مورد ترکیب Client Side Templates با MVC: یکی از خوبی‌های بازگشت دادن یک partial view کامل در MVC (که بله، یک HTML کامل رو بر می‌گردونه در حالت Ajax ایی مثلا) نسبت به این روش، امکان استفاده از متدهای کمکی سمت سرور برای رندر کردن View هست. مثلا فرض کنید یک لیست فایل‌ها قراره نمایش داده بشه. در View یا Partial View میشه بدون تعریف یک کلاس اضافه‌تر برای بازگشت دادن اطلاعات به صورت JSON که بخواد در AngularJS سمت کلاینت استفاده بشه، اطلاعات رو خیلی ساده برای نمایش، با razor و سی‌شارپ فرمت کرد. مثلا تاریخ رو شمسی کرد. اندازه رو به کیلوبایت یا مگابایت نمایش داد (در حد فراخوانی یک متد الحاقی). یک if و else گذاشت که اگر کاربر لاگین بود این قسمت از partial view رو که درون حلقه داره تولید میشه، مشاهده نکنه یا برعکس. یک قسمت از حلقه هم یک فرم کوچک درست کرد برای ارسال دیتا به سرور اون هم فرمی که آدرسش رو از T4MVC به صورت strongly typed می‌گیره و یا فیلدهاش از Html Helperهای MVC استفاده می‌کنند که این‌ها هم سمت سرور رندر می‌شن.  الان چون تمام کار با جاوا اسکریپت باید انجام بشه، یعنی تمام این مراحل رو باید به صورت JSON بازگشت داد که AngularJS بخواد اون‌ها رو سمت کلاینت، سر هم کنه.  به علاوه امکان کامپایل کردن Viewهای razor و یافتن خطاهای احتمالی رو هم از دست می‌دیم چون همه چیز قراره سمت کلاینت رندر بشه.
نظرات مطالب
احراز هویت و اعتبارسنجی کاربران در برنامه‌های Angular - قسمت دوم - سرویس اعتبارسنجی
- سازنده‌ی کلاس سرویس Auth هست که کار اطلاع رسانی به کامپوننت هدر را انجام می‌دهد. علت قرار گرفتن این قطعه کد، در هدر هم دقیقا اجرای آن با ریفرش صفحه است. بنابراین این قسمت و همچنین مشترکین به BehaviorSubject آن‌را بررسی کنید:
 constructor() {
    this.updateStatusOnPageRefresh();
  }
- اگر با وجود مقادیر token در کش مرورگر، این مقادیر کار نمی‌کنند، نیاز به پیاده سازی «نکته‌ی مهم: نیاز به دائمی کردن کلیدهای رمزنگاری سمت سرور» را دارید. ری استارت برنامه = تولید کلیدهای رمزنگاری جدید = غیرمعتبر شدن اطلاعات سمت کاربر و برگشت خوردن آن‌ها در سمت سرور
مطالب
معرفی Selector های CSS - قسمت 7
61- :any-link
تمامی تگ‌هایی را انتخاب می‌کند که می‌توانند نقش لینک را در صفحه ایفا کنند. در واقع تگ‌های a، area و link را انتخاب می‌نماید که دارای ویژگی href هستند و به عنوان لینک عمل می‌کنند.
<style>
    :any-link {
        color: red;
    }
</style>
<a href="page1.htm">Link 1</a>
در مثال فوق، متن Link 1 به رنگ قرمز نمایش می‌یابد.
           Selector  نسخه CSS
No No
No
No No :any-link  4
62- :local-link
تمامی لینک هایی را انتخاب می‌کند که با آدرس صفحه‌ی جاری یکسان می‌باشند.
<style>
    :local-link {
        color: red;
    }
</style>
<a href="http://www.example.com/article/">Link 1</a>
<a href="http://www.example.com/article">Link 2</a>
<a href="http://www.example.com/article/">Link 3</a>
<a href="http://www.example.com/article/12">Link 4</a>
با فرض اینکه آدرس صفحه‌ی جاری http://www.example.com/article/   می باشد مثال فوق را بررسی می‌کنیم. متن Link 1 و Link3 به رنگ قرمز نمایش می‌یابند، زیرا مشابه آدرس صفحه‌ی جاری می‌باشند.
           Selector  نسخه CSS
No No
No
No No :local-link  4 
63- :local-link(n)
تمامی لینک هایی را انتخاب می‌کند که آدرس آنها با آدرس صفحه‌ی جاری یکسان بوده و n بخش از آدرس آنها با بخش‌های آدرس جاری یکسان باشند. در واقع n، تعداد بخش هایی از آدرس لینک را مشخص می‌کند که با بخش‌های آدرس صفحه‌ی جاری مطابقت داشته باشند. در مطابقت آدرس، از scheme، username، password، port، query string و fragment صرف نظر می‌شود تا یکسان بودن آدرس را تشخیص دهد. سپس تشخیص می‌دهد کدام بخش‌های آدرس با هم یکسان می‌باشند. جهت اطلاع باید عرض کنم که شکل کامل یک آدرس به صورت scheme:[//[user:password@]host[:port]][/]path[?querystring][#fragment] می‌باشد.
<style>
    :local-link {
        color: red;
    }
    :local-link(0) {
        text-decoration: none;
    }
    :local-link(1) {
        text-decoration: overline;
    }
    :local-link(2) {
        background: blue;
    }
</style>
<a href="http://www.example.com">Link 1</a>
<a href="http://www.example.com/2016">Link 2</a>
<a href="http://www.example.com/2016/01">Link 3</a>
<a href="http://www.example.com/2016/01/">Link 4</a>
<a href="http://www.example.com/2016/01/02">Link 5</a>
<a href="https://www.example.com/2016/01/">Link 6</a>
<a href="http://example.com/2016/01">Link 7</a>
با فرض اینکه آدرس صفحه‌ی جاری http://www.example.com/2016/01/ می باشد مثال فوق را بررسی میکنیم. Link 1 تحت تاثیر Selector دوم، بدون زیرخط نمایش می‌یابد. Link 2 تحت تاثیر Selector دوم و سوم، بدون زیرخط و با روخط نمایش می‌یابد. Link 3، Link 5 و Link 6 تحت تاثیر Selector دوم و سوم و چهارم، بدون زیرخط، با روخط و پس زمینه‌ی آبی نمایش می‌یابند. Link 6 به دلیل استفاده از https نمی‌تواند تحت تاثیر Selector اول قرار بگیرد. Link 4 تحت تاثیر Selector اول و دوم و سوم و چهارم، به رنگ قرمز، بدون زیرخط، با روخط و پس زمینه‌ی آبی نمایش می‌یابد. Link 7 هم بدون تاثیر هیچ Selector ی بر روی آن، بدون قالب باقی می‌ماند، زیرا قسمت host لینک با آدرس مطابقت ندارد.
           Selector  نسخه CSS
No No
No
No No :local-link(n)  4
64- :active-drop-target
تگی را انتخاب می‌کند که در حال حاضر به عنوان مقصد یک تگ drag (کشیده) شده در نظر گرفته شده است. به عبارت دیگر، تگی را با عمل drag کشیده ایم و بر روی یک تگ مقصد قرار داده ایم، ولی هنوز عمل drop یا رها کردن صورت نگرفته است.
              Selector  نسخه CSS
No No
No
No No :active-drop-target   4 
65- :valid-drop-target
تگی را انتخاب می‌کند که در حال حاضر به عنوان مقصد یک تگ drag (کشیده) شده در نظر گرفته شده است و برای عمل drop معتبر می‌باشد. به عبارت دیگر، تگ مقصد امکان پذیرش یک تگ را با عمل Drag & Drop دارد.
              Selector  نسخه CSS
No No
No
No No :valid-drop-target   4 
66- :invalid-drop-target
تگی را انتخاب می‌کند که در حال حاضر به عنوان مقصد یک تگ drag (کشیده) شده در نظر گرفته شده است و برای عمل drop معتبر نمی‌باشد. به عبارت دیگر، تگ مقصد امکان پذیرش یک تگ را با عمل Drag & Drop ندارد.
              Selector  نسخه CSS
No No
No
No No :invalid-drop-target   4 
<style>
    :active-drop-target {
        background: blue;
    }
    :valid-drop-target {
        border: 1px solid green;
    }
    :invalid-drop-target {
        border: 1px solid red;
    }
    .container {
        width: 200px;
        height: 200px;
    }
</style>
<div class="container"></div>
<img src="image.jpg" draggable="true"/>
در مثال فوق، با Drag نمودن تصویر بر روی تگ div، تحت تاثیر Selector اول، رنگ پس زمینه‌ی div آبی می‌شود. اگر امکان پذیرش img توسط تگ div وجود داشته باشد، کادری سبز رنگ دور تگ div نمایش می‌یابد در غیر اینصورت کادر قرمز رنگ دور آن نمایش خواهد یافت.
67- :current
تگی را انتخاب می‌کند که در حال حاضر در حال نمایش یا ارائه می‌باشد. این Selector در زمان پردازش صوت، تصویر، نمایش زیر نویس و غیره در تگ canvas مورد استفاده قرار می‌گیرد.
              Selector  نسخه CSS
No No
No
No No :current   4 
68- :past
تگی را انتخاب می‌کند که قبل از :current نمایش یافته است.
              Selector  نسخه CSS
No No
No
No No :past   4 
69- :future
تگی را انتخاب می‌کند که بعد از :current نمایش یافته است.
              Selector  نسخه CSS
No No
No
No No :future   4 
هر سه Selector فوق می‌توانند با دریافت آرگومان به صورت مجموعه ای از Selector ها، تگ‌های خاصی را انتخاب کنند یا نتیجه‌ی انتخاب را محدود نمایند. اگر بدون آرگومان به کار روند، تک مورد نظر را بدون در نظر گرفتن محدویت انتخاب می‌نمایند.
<style>
    :past(div,p) {
        background: red;
    }
    :current(div,p) {
        background: green;
    }
    :future(div,p) {
        background: yellow;
    }
</style>
در مثال فوق، تگ‌های div یا p که در حال حاضر در حال نمایش می‌باشند، با پس زمینه‌ی سبز، تگی که قبل از :current نمایش یافته است با پس زمینه‌ی قرمز و تگی که بعد از :current نمایش خواهد یافت با پس زمینه‌ی زرد نمایش می‌یابد.
70- :placeholder-shown
تمامی تگ‌های input و textarea را انتخاب می‌کند که در حال نمایش یا حاوی placeholder می‌باشند و هنوز متنی در آنها وارد نشده است. در حال حاضر به صورت آزمایشی و با vendor prefix قابل استفاده است.
<style>
    :placeholder-shown {
        color: gray;
    }
</style>
<input placeholder="Enter Username"/>
<input placeholder="Enter Password"/>
در مثال فوق، اگر در هر کدام از تگ‌های input، هیچ متنی وارد نشده باشد، متن‌های Enter Username و Enter Password به رنگ طوسی نمایش می‌یابند.
              Selector  نسخه CSS
-webkit- -wekit-
-ms-
-moz- -webkit- :placeholder-shown   4 















مطالب
آشنایی با ساختار IIS قسمت اول
در مقاله قبل در مورد نحوه ذخیره سازی در حافظه نوشتیم و به user mode و kernel mode اشاراتی کردیم که می‌توانید به آن رجوع کنید.
در این سری مقالات قصد داریم به بررسی اجزا و روند کاری موجود در IIS بپردازیم که چگونه IIS کار می‌کند و شامل چه بخش هایی می‌شود. مطمئنا آشنایی با این بخش‌ها در روند شناسایی رفتارهای وب اپلیکیشن‌ها و واکنش‌های سرور، کمک زیادی به ما خواهد کرد. در اینجا نسخه IIS7 را به عنوان مرجع در نظر گرفته‌ایم.
وب سرور IIS در عبارت مخفف Internet information services به معنی سرویس‌های اطلاعاتی اینترنت می‌باشد. IIS شامل کامپوننت‌های زیادی است که هر کدام ازآن‌ها کار خاصی را انجام میدهند؛ برای مثال گوش دادن به درخواست‌های ارسال شده به سرور، مدیریت فرآیندها Process و خواندن فایل‌های پیکربندی Configuration؛ این اجزا شامل protocol listener ،Http.sys و WSA و .. می‌شوند.
Protocol Listeners
این پروتکل‌ها به درخواست‌های رسیده گوش کرده و آن‌ها را مورد پردازش قرار می‌دهند و پاسخی را به درخواست کننده، ارسال می‌کنند. هر listener بر اساس نوع پروتکل متفاوت هست. به عنوان مثال کلاینتی، درخواست صفحه‌ای را می‌کند و http listener که به آن Http.sys می‌گویند به آن پاسخ می‌دهد. به طور پیش فرض http.sys به درخواست‌های http و https گوش فرا می‌دهد، این کامپوننت از IIS6 اضافه شده است ولی در نسخه 7 از SSL نیز پشتیبانی می‌کند.
Http.sys یا Hypertext transfer protocol stack
کار این واحد در سه مرحله دریافت درخواست، ارسال آن به واحد پردازش IIS و ارسال پاسخ به کلاینت است؛ قبل از نسخه 6 از Winsock یا windows socket api  که یک کامپوننت user-mod بود استفاده می‌شد ولی Http.sys یک کامپوننت Kernel-mod هست.

Http.sys مزایای زیر را به همراه دارد:

  • صف درخواست مد کرنل: به خاطر اینکه کرنل مستقیما درخواست‌ها را به پروسه‌های مربوطه میفرستد و اگر پروسه موجود نباشد، درخواست را در صف گذاشته تا بعدا پروسه مورد نظر آن را از صف بیرون بکشد.
  • برای درخواست‌ها یک پیش پردازش و همچنین اعمال فیلترهای امنیتی اعمال می‌گردد. 
  • عملیات کش کردن تماما در محیط کرنل مد صورت می‌گیرد؛ بدون اینکه به حالت یوزرمد سوییچ کند. مد کرنل دسترسی بسیار راحت و مستقیمی را برای استفاده از منابع دارد و لازم نیست مانند مد کاربر به لایه‌های زیرین، درخواست کاری را بدهد؛ چرا که خود مستقیما وارد عمل می‌شود و برداشته شدن واسط در سر راه، موجب افزایش عمل caching می‌شود. همچنین دسترسی به کش باعث می‌شود که مستقیما پاسخ از کش به کاربر برسد و توابع پردازشی در حافظه بارگذاری نشوند. البته این کش کردن محدودیت هایی را هم به همراه دارد:
    1. کش کرنل به صورت پیش فرض بر روی صفحات ایستا فعال شده است؛ نه برای صفحاتی با محتوای پویا که البته این مورد قابل تغییر است که نحوه این تغییر را پایینتر توضیح خواهیم داد.
    2. اگر آدرس درخواستی شامل کوئری باشد صفحه کش نخواهد شد:    http://www.site.info/postarchive.htm?id=25 
    3. برای پاسخ ازمکانیزم‌های فشرده سازی پویا استفاده شده باشد مثل gzip کش نخواهد شد
    4. صفحه درخواست شده صفحه اصلی سایت باشد کش نخواهد شد :   http://www.dotnettip.info ولی اگر درخواست بدین صورت باشه http://www.domain.com/default.htm  کش خواهد کرد.
    5. درخواست به صورت ناشناس anonymous نباشد  و نیاز به authentication داشته باشد کش نخواهد شد (یعنی در هدر شامل گزینه authorization می‌باشد).
    6. درخواست باید از نوع نسخه http1 به بعد باشد.
    7. اگر درخواست شامل Entity-body باشد کش نخواهد کرد.
    8. درخواست شامل If-Range/Range header باشد کش نمی‌شود.
    9. کل حجم response بییشتر از اندازه تعیین شده باشد کش نخواهد گردید، این اندازه در کلید ریجستری UriMaxUriBytes قرار دارد. اطلاعات بیشتر
    10. اندازه هدر بیشتر از اندازه تعیین شده باشد که عموما اندازه تعیین شده یک کیلو بایت است.
    11. کش پر باشد، کش انجام نخواهد گرفت.
    برای فعال سازی کش کرنل راهنمای زیر را دنبال کنید:
    گزینه output cache را در IIS، فعال کنید و سپس گزینه Add را بزنید. کادر add cache rule که باز شود، از شما میخواهد یکی از دو نوع کش مد کاربر و مد کرنل را انتخاب کنید و  مشخص کنید چه نوع فایل‌هایی (مثلا aspx) از این قوانین پیروری کنند و مکانیزم کش کردن به سه روش جلوگیری از کش کردن، کش زمان دار و کش بر اساس آخرین تغییر فایل انجام گردد.


    برای تعیین مقدار سایز کش response که در بالا اشاره کردیم می‌توانید در همان پنجره، گزینه edit feature settings را انتخاب کنید.


    این قسمت از مطلب که به نقل از مقاله  آقای Karol Jarkovsky در این آدرس است یک سری تست هایی با نرم افزار(Web Capacity Analysis Tool (WCAT  گرفته است که به نتایج زیر دست پیدا کرده است:
    Kernel Cache Disabled    4 clients/160 threads/30 sec      257 req/sec
    Kernel Cache Enabled     4 clients/160 threads/30 sec      553 req/sec 
    همانطور که می‌بینید نتیجه فعال سازی کش کرنل پاسخ به بیش از دو برابر درخواست در حالت غیرفعال آن است که یک عدد فوق العاده به حساب میاد.
    برای اینکه خودتان هم تست کرده باشید در این آدرس  برنامه را دانلود کنید و به دنبال فایل request.cfg بگردید و از صحت پارامترهای server و url اطمینان پیدا کنید. در گام بعدی 5 پنجره خط فرمان باز کرده و در یکی از آن‌ها دستور netsh http show cachestate را بنویسید تا تمامی وروردی‌های entry که در کش کرنل ذخیره شده اند لیست شوند. البته در اولین تست کش را غیرفعال کنید و به این ترتیب نباید چیزی نمایش داده شود. در همان پنجره فرمان wcctl –a localhost –c config.cfg –s request.cfg  را زده تا کنترلر برنامه در وضعیت listening قرار بگیرد. در 4 پنجره دیگر فرمان wcclient localhost از شاخه کلاینت را نوشته تا تست آغاز شود. بعد از انجام تست به شاخه نصب کنترلر WCAT رفته و فایل log را بخوانید و اگر دوباره دستور نمایش کش کرنل را بزنید باید خالی باشد. حالا کش را فعال کنید و دوباره عملیات تست را از سر بگیرید و اگر دستور netsh را ارسال کنید باید کش کرنل دارای ورودی باشد.
    برای تغییرات در سطح http.sys می‌توانید از ریجستری کمک بگیرید. در اینجا تعداد زیادی از تنظیمات ذخیره شده در ریجستری برای http.sys لیست شده است.
    مطالب
    آشنایی با CLR: قسمت هفتم
    کدهای IL و تایید آن ها

    ساختار استکی
    IL از ساختار استک استفاده می‌کند. به این معنی که تمامی دستور العمل‌ها داخل آن push شده و نتیجه‌ی اجرای آن‌ها pop می‌شوند. از آنجا که IL به طور مستقیم ارتباطی با ثبات‌ها ندارد، ایجاد زبانهای برنامه نویسی جدید بر اساس CLR بسیار راحت‌تر هست و عمل کامپایل، تبدیل کردن به کدهای IL می‌باشد.

    بدون نوع بودن(Typeless)
    از دیگر مزیت‌های آن این است که کدهای IL بدون نوع هستند. به این معنی که موقع افزودن دستورالعملی به داخل استک، دو عملگر وارد می‌شوند و هیچ جداسازی در رابطه با سیستم‌های 32 یا 64 بیت صورت نمی‌گیرد و موقع اجرای برنامه است که تصمیم می‌گیرد از چه عملگرهایی باید استفاده شود.

    Virtual Address Space
    بزرگترین مزیت این سیستم‌ها امنیت و مقاومت آن هاست. موقعی که تبدیل کد IL به سمت کد بومی صورت می‌گیرد، CLR فرآیندی را با نام verification یا تاییدیه، اجرا می‌کند. این فرآیند تمامی کدهای IL را بررسی می‌کند تا از امنیت کدها اطمینان کسب کند. برای مثال بررسی می‌کند که هر متدی صدا زده می‌شود با تعدادی پارامترهای صحیح صدا زده شود و به هر پارامتر آن نوع صحیحش پاس شود و مقدار بازگشتی هر متد به درستی استفاده شود. متادیتا شامل اطلاعات تمامی پیاده سازی‌ها و متدها و نوع هاست که در انجام تاییدیه مورد استفاده قرار می‌گیرد.
    در ویندوز هر پروسه، یک آدرس مجازی در حافظه دارد و این جدا سازی حافظه و ایجاد یک حافظه مجازی کاری لازم اجراست. شما نمی‌توانید به کد یک برنامه اعتماد داشته باشید که از حد خود تخطی نخواهد کرد و فرآیند برنامه‌ی دیگر را مختل نخواهد کرد. با خواندن و نوشتن در یک آدرس نامعتبر حافظه، ما این اطمینان را کسب می‌کنیم که هیچ گاه تخطی در حافظه صورت نمی‌گیرد.
    قبلا به طور مفصل در این مورد ذخیره سازی در حافظه صحبت کرده ایم.

    Hosting
    از آنجا که پروسه‌های ویندوزی به مقدار زیادی از منابع سیستم عامل نیاز دارند که باعث کاهش منابع و محدودیت در آن می‌شوند و نهایت کارآیی سیستم را پایین می‌آورد، ولی با کاهش تعدادی برنامه‌های در حال اجرا به یک پروسه‌ی واحد می‌توان کارآیی سیستم را بهبود بخشید و منابع کمتری مورد استفاده قرار می‌گیرند که این یکی دیگر از مزایای کدهای managed نسبت به unmanaged است. CLR در حقیقت این قابلیت را به شما می‌دهد تا چند برنامه‌ی مدیریت شده را در قالب یک پروسه به اجرا درآورید. هر برنامه‌ی مدیریت شده به طور پیش فرض بر روی یک appDomain اجرا می‌گردد و هر فایل EXE روی حافظه‌ی مجازی مختص خودش اجرا می‌شود. هر چند پروسه‌هایی از قبیل IIS و SQL Server که پروسه‌های CLR را پشتیبانی یا هاست می‌کنند می‌توانند تصمیم بگیرند که آیا appDomain‌ها را در یک پروسه‌ی واحد اجرا کنند یا خیر که در مقاله‌های آتی آن را بررسی می‌کنیم.

    کد ناامن یا غیر ایمن UnSafe Code
    به طور پیش فرض سی شارپ کدهای ایمنی را تولید می‌کند، ولی این اجازه را می‌دهد که اگر برنامه نویس بخواهد  کدهای ناامن بزند، قادر به انجام آن باشد. این کدهای ناامن دسترسی مستقیم به خانه‌های حافظه و دستکاری بایت هاست. این مورد قابلیت قدرتمندی است که به توسعه دهنده اجازه می‌دهد که با کدهای مدیریت نشده ارتباط برقرار کند یا یک الگوریتم با اهمیت زمانی بالا را جهت بهبود کارآیی، اجرا کند.
     هر چند یک کد ناامن سبب ریسک بزرگی می‌شود و می‌تواند وضعیت بسیاری از ساختارهای ذخیره شده در حافظه را به هم بزند و امنیت برنامه را تا حد زیادی کاهش دهد.  به همین دلیل سی شارپ نیاز دارد تا تمامی متدهایی که شامل کد unsafe هستند را با کلمه کلیدی unsafe علامت گذاری کند. همچنین کمپایلر سی شارپ نیاز دارد تا شما این کدها را با سوئیچ unsafe/ کامپایل کنید.

    موقعیکه جیت تلاش دارد تا یک کد ناامن را کامپایل کند، اسمبلی را بررسی می‌کند که آیا این متد اجازه و تاییدیه آن را دارد یا خیر. آیا  System.Security.Permissions.SecurityPermission با فلگ SkipVerification مقدار دهی شده است یا خیر. اگر پاسخ مثبت بود JIT آن‌ها را کامپایل کرده و اجازه‌ی اجرای آن‌ها را می‌دهد. CLR به این کد اعتماد می‌کند و امیدوار است که آدرس دهی مستقیم و دستکاری بایت‌های حافظه موجب آسیبی نگردد. ولی اگر پاسخ منفی بود، یک استثناء از نوع System.InvalidProgramException یا System.Security.VerificationException را ایجاد می‌کند تا از اجرای این متد جلوگیری به عمل آید. در واقع کل برنامه خاتمه میابد ولی آسیبی به حافظه نمی‌زند.

    پی نوشت: سیستم به  اسمبلی هایی که از روی ماشین یا از طریق شبکه  به اشتراک گذاشته می‌شوند اعتماد کامل میکند که این اعتماد شامل کدهای ناامن هم می‌شود ولی به طور پیش فرض به اسمبلی هایی از طریق اینترنت اجرا می‌شوند اجازه اجرای کدهای ناامن را نمی‌دهد و اگر شامل کدهای ناامن شود یکی از خطاهایی که در بالا به آن اشاره کردیم را صادر می‌کنند. در صورتی که مدیر یا کاربر سیستم اجازه اجرای آن را بدهد تمامی مسئولیت‌های این اجرا بر گردن اوست.

    در این زمینه مایکروسافت ابزار سودمندی را با نام PEVerify .exe را معرفی کرده است که به بررسی تمامی متدهای یک اسمبلی پرداخته و در صورت وجود کد ناامن به شما اطلاع میدهد. بهتر است از این موضوع اطلاع داشته باشید که این ابزار نیاز دارد تا به متادیتاهای یک اسمبلی نیاز داشته باشید. باید این ابزار بتواند به تمامی ارجاعات آن دسترسی داشته باشد که در مورد عملیات بایندینگ در آینده بیشتر صحبت می‌کنیم.

    IL و حقوق حق تالیف آن
    بسیاری از توسعه دهندگان از اینکه IL هیچ شرایطی برای حفظ حق تالیف آن‌ها ایجاد نکرده است، ناراحت هستند. چرا که ابزارهای زیادی هستند که با انجام عملیات مهندسی معکوس می‌توانند به الگوریتم آنان دست پیدا کنند و میدانید که IL خیلی سطح پایین نیست و برگرداندن آن به شکل یک کد، کار راحت‌تری هست و بعضی ابزارها کدهای خوبی هم ارائه می‌کنند. از دست این ابزارها می‌توان به ILDisassembler و  JustDecompile اشاره کرد.
    اگر علاقمند هستید این عیب را برطرف کنید، می‌توانید از ابزارهای ثالث که به ابزارهای obfuscator (یک نمونه سورس باز ) معروف هستند استفاده کنید تا با کمی پیچیدگی در متادیتاها، این مشکل را تا حدی برطرف کنند. ولی این ابزارها خیلی کامل نیستند، چرا که نباید به کامپایل کردن کار لطمه بزنند. پس اگر باز خیلی نگران این مورد هستید می‌توانید الگوریتم‌های حساس و اساسی خود را در قالب unmanaged code ارائه کنید که در بالا اشاراتی به آن کرده‌ایم.
    برنامه‌های تحت وب به دلیل عدم دسترسی دیگران از امنیت کاملتری برخوردار هستند.
    مطالب
    چرا در جاوااسکریپت نیازی به استفاده از loopها ندارید!
    در زبان‌های برنامه نویسی، از loopها برای پیمایش عناصر یک مجموعه استفاده میشود. این پیمایش ممکن است صرفا جهت نمایش و یا دستکاری نمودن عناصر مجموعه، مورد استفاده قرار بگیرد (دستوراتی نظیر for,while,do while).
    کد زیر را در نظر بگیرید که در آن قصد داریم عناصر مجموعه‌ای را تبدیل به حروف بزرگ کنیم. اینکار به طور معمول با استفاده از  loopهای معمول، به شکل زیر انجام میشود:
    let names = ["Jack", "Jecci", "Ram", "Tom"];
    let upperCaseNames = [];
    for(let i=0, totalNames = names.length; i< totalNames ; i= i +1) {
        upperCaseNames = names[i].toUpperCase();
    }
    در  ECMAScript 5 توابعی معرفی شد که میتوانیم از آنها بجای loopها استفاده کنیم.
    let names = ["Jack", "Jecci", "Ram", "Tom"];
    let upperCaseNames = names.map(name => name.toUpperCase());
    تابع map یک آرایه‌ی جدید را بازگشت می‌دهد (توسعه دهندگان React Js  از این تابع استفاده زیادی دارند). وقتی تابع map را بکارمیبرید، قابلیت استفاده از دستوراتی مانند  break , continue و return را نخواهید داشت و در صورت نیاز میتوانید از توابعی همچون some و یا every استفاده نمایید. 
    مثال دیگری را در نظر بگیرید که در آن قصد داریم یک action  و عملی را روی عناصر مجموعه‌ای اعمال کنیم. در اینجا چاپ عناصر در نظر گرفته شده‌است:
    function print(name) {
       console.log(name);
    }
    let names = ["Jack", "Jecci", "Ram", "Tom"];
    for(let i=0, totalNames = names.length; i< totalNames ; i= i +1) {
        print(names[i])
    }
    با استفاده از تابع forEach، کد فوق بصورت زیر بازنویسی و خلاصه نویسی می‌شود:
    function print(name) {
       console.log(name);
    }
    let names = ["Jack", "Jecci", "Ram", "Tom"];
    names.forEach(name=> print(name));
    
    //  اگر صرفا چاپ در کنسول مد نظر هست
    
    let names = ["Jack", "Jecci", "Ram", "Tom"];
    names.forEach(name=> console.log(name));


    در مثالی دیگر قصد فیلتر کردن عناصر مجموعه‌ای را بر اساس شرطی خاص داریم (عناصر فرد):
    function isOdd(n) {
       return n %2;
    }
    let numbers = [1,2,3,4,5];
    let odd = [];
    for(let i=0, total = numbers.length; i< total ; i= i +1) {
       let number = numbers[i];
       if( isOdd(number) ) {
          odd.push(number);
       }
    }
    با استفاده از تابع filter، کد فوق را بهبود می‌دهیم:
    let numbers = [1,2,3,4,5, 6, 7]
    let odd = numbers.filter(n => n%2);
    فرض کنید قرار است یک خروجی را بعد از پیمایش عناصر مجموعه‌ای داشته باشیم (مجموع عناصر):
    let numbers = [1,2,3,4,5]
    let result = 0;
    for(let i=0, total = numbers.length; i< total ; i= i +1) {
       result = result + numbers[i];
    }
    با استفاده از تابع  reduce، کد فوق را بازنویسی میکنیم:
    let numbers = [1,2,3,4,5,6,7];
    function sum(accumulator, currentValue){
       return accumulator + currentValue;
    }
    let initialVal = 0;
    let result = numbers.reduce(sum, initialVal);
    
    // یا بصورت زیر کد را خلاصه نمود
    
    let numbers = [1,2,3,4,5,6,7, 10];
    let result = numbers.reduce((acc, val)=> acc+val, 0);

    در مثال دیگری قصد بررسی این مورد را داریم که آیا  آرایه‌ای، دارای مقدار خاصی می‌باشد و در صورت دارا بودن آن آیتم، از ادامه پیمایش خارج شود:
    let names = ["ram",, "rahul", "raj", "rahul"];
    for(let i=0, totalNames = names.length; i< totalNames ; i= i +1) {
       if(names[i] === "rahul") {
         console.log(" found rahul");
         break; 
       }
    }
    اکنون با استفاده از تابع some، بصورت زیر کد را بهبود میدهیم: 
    let names = ["ram",, "rahul", "raj", "rahul"];
    let isRahulPresent = names.some(name => name==="rahul");
    if(isRahulPresent) {
      console.log("found rahul"); 
    }

    در یک آرایه قصد داریم شرطی را بر روی همه‌ی عناصر آن چک کنیم و در صورت صحت شرط، بر روی کل مجموعه، action یا عملی را انجام دهیم:
    let numbers = [1,2,3,4,5, 0];
    for(let i=0, total = numbers.length; i< total ; i= i +1) {
        if(numbers[i] <= 0) {
          console.log("0 present in array");
          break;
         }
    }

    این کد را با استفاده از تابع every، بصورت زیر بازنویسی میکنیم:
    let numbers = [1,2,3,4,5,0];
    let isZeroFree = numbers.every(e => e > 0);
    if(!isZeroFree) {
        console.log("0 present in array");
    }

    نتیجه گیری:
     استفاده از این نوع توابع، مزیت‌های زیر را به همراه دارد:
    • خوانایی بهتر
    • فهم راحت
    • خطایابی آسان‌تر